public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* 2.6.19 lot's of oops in  mmx_copy_page/ mmx_clear_page functions
@ 2006-12-10 11:32 matthieu castet
  2006-12-10 19:02 ` Maxime Austruy
  0 siblings, 1 reply; 3+ messages in thread
From: matthieu castet @ 2006-12-10 11:32 UTC (permalink / raw)
  To: Linux Kernel list

Hi,

with 2.6.19 I got some random crash and I got kernel opps.
There all happens in  mmx_copy_page/ mmx_clear_page functions with 
differents process : Xorg, cat, mozilla, ...


What could be the cause of these crashes ?
What can I provide in order to debug this ?


Thanks

Matthieu CASTET



BUG: unable to handle kernel paging request at virtual address fffb9000
  printing eip:
c01be1bd
*pde = 00002067
Oops: 0000 [#1]
PREEMPT
Modules linked in: michael_mic arc4 ecb ieee80211_crypt_tkip ehci_hcd 
videodev v4l1_compat v4l2_common nfs nfsd exportfs lockd sunrpc sd_mod 
sg sr_mod ppdev lp autofs4 button processor ipt_TOS ipt_MASQUERADE 
ipt_ULOG ipt_LOG xt_tcpudp xt_state ipt_REJECT ipt_iprange xt_conntrack 
iptable_mangle ip_nat_irc ip_nat_ftp iptable_nat ip_nat ip_conntrack_irc 
ip_conntrack_ftp ip_conntrack iptable_filter ip_tables x_tables ide_cd 
cdrom pcspkr snd_mpu401 ns558 parport_pc parport 8250_pnp 8250 
serial_core floppy snd_via82xx snd_mpu401_uart emu10k1_gp gameport 
snd_emu10k1_synth snd_emux_synth snd_seq_virmidi snd_seq_midi_emul 
snd_seq_oss snd_seq_midi snd_seq_midi_event snd_seq snd_emu10k1 
snd_rawmidi snd_ac97_codec snd_ac97_bus snd_pcm_oss snd_mixer_oss 
snd_pcm snd_seq_device snd_timer snd_page_alloc snd_util_mem snd_hwdep 
snd soundcore mii zd1211rw firmware_class ieee80211softmac ieee80211 
ieee80211_crypt via_agp agpgart clip atm nls_iso8859_1 nls_cp437 vfat 
fat nls_base reiserfs w83627hf hwmon_vid i2c_isa i2c_core evdev rtc
CPU:    0
EIP:    0060:[<c01be1bd>]    Not tainted VLI
EFLAGS: 00010246   (2.6.19 #1)
EIP is at mmx_copy_page+0x51/0x123
eax: fffb9000   ebx: e2db9000   ecx: 00000000   edx: e2db9000
esi: fffb9000   edi: e2db9000   ebp: c17e6040   esp: f671defc
ds: 007b   es: 007b   ss: 0068
Process automount (pid: 11921, ti=f671c000 task=f7cf0050 task.ti=f671c000)
Stack: fffb9000 eb216040 c0140045 8001003c f5c95e40 f4ee2abc c145b720 
00000000
        3f302065 f4ee2afc eb216040 f5c95e40 c014145f eb216040 f4f8a800 
f4ee2afc
        3f302065 393b4393 8001003c f4ee2abc 00000040 f4f8a800 00000000 
f671df94
Call Trace:
  [<c0140045>] do_wp_page+0x291/0x414
  [<c014145f>] __handle_mm_fault+0x7d2/0x873
  [<c0112593>] do_page_fault+0x213/0x4dc
  [<c0112380>] do_page_fault+0x0/0x4dc
  [<c02a01e1>] error_code+0x39/0x40
  =======================
Code: f4 ff 0f 0d 06 0f 0d 46 40 0f 0d 86 80 00 00 00 0f 0d 86 c0 00 00 
00 0f 0d 86 00 01 00 00 31 c9 89 fa 89 f0 0f 0d 80 40 01 00 00 <0f> 6f 
00 0f e7 02 0f 6f 48 08 0f e7 4a 08 0f 6f 50 10 0f e7 52
EIP: [<c01be1bd>] mmx_copy_page+0x51/0x123 SS:ESP 0068:f671defc
  <6>note: automount[11921] exited with preempt_count 3



Sumary of Others failures :
/var/log/syslog:Dec 10 10:40:14 localhost kernel: BUG: unable to handle 
kernel paging request at virtual address fffb9b20
/var/log/syslog:Dec 10 10:40:14 localhost kernel: EIP is at 
mmx_clear_page+0x38/0x7e
/var/log/syslog:Dec 10 10:40:14 localhost kernel: Process iceape-bin 
(pid: 7061, ti=f7410000 task=eeb5a070 task.ti=f7410000)
/var/log/syslog:Dec 10 10:40:14 localhost kernel: EIP: [<c01be406>] 
mmx_clear_page+0x38/0x7e SS:ESP 0068:f7411eb0
/var/log/syslog:Dec 10 10:40:24 localhost kernel: BUG: unable to handle 
kernel paging request at virtual address fffb9a60
/var/log/syslog:Dec 10 10:40:24 localhost kernel: EIP is at 
mmx_clear_page+0x38/0x7e
/var/log/syslog:Dec 10 10:40:24 localhost kernel: Process cc1 (pid: 
21797, ti=d62ea000 task=e86eb070 task.ti=d62ea000)
/var/log/syslog:Dec 10 10:40:24 localhost kernel: EIP: [<c01be406>] 
mmx_clear_page+0x38/0x7e SS:ESP 0068:d62ebeb0
/var/log/syslog:Dec 10 11:12:37 localhost kernel: BUG: unable to handle 
kernel paging request at virtual address fffb9000
/var/log/syslog:Dec 10 11:12:37 localhost kernel: EIP is at 
mmx_copy_page+0x51/0x123
/var/log/syslog:Dec 10 11:12:37 localhost kernel: Process automount 
(pid: 11921, ti=f671c000 task=f7cf0050 task.ti=f671c000)
/var/log/syslog:Dec 10 11:12:37 localhost kernel: EIP: [<c01be1bd>] 
mmx_copy_page+0x51/0x123 SS:ESP 0068:f671defc
/var/log/syslog.0:Dec  9 19:21:50 localhost kernel: Process modprobe 
(pid: 20516, ti=ee3d8000 task=f649f580 task.ti=ee3d8000)
/var/log/syslog.0:Dec  9 22:15:15 localhost kernel: BUG: unable to 
handle kernel paging request at virtual address fffb9000
/var/log/syslog.0:Dec  9 22:15:15 localhost kernel: EIP is at 
mmx_clear_page+0x29/0x7e
/var/log/syslog.0:Dec  9 22:15:15 localhost kernel: Process Xorg (pid: 
9479, ti=d4ae0000 task=f671ca90 task.ti=d4ae0000)
/var/log/syslog.0:Dec  9 22:15:15 localhost kernel: EIP: [<c01be3f7>] 
mmx_clear_page+0x29/0x7e SS:ESP 0068:d4ae1eb0
/var/log/syslog.0:Dec  9 22:15:15 localhost kernel:  [<c01be3f7>] 
mmx_clear_page+0x29/0x7e
/var/log/syslog.0:Dec  9 22:15:15 localhost kernel:  [<c01be3f7>] 
mmx_clear_page+0x29/0x7e
/var/log/syslog.0:Dec 10 00:06:31 localhost kernel: BUG: unable to 
handle kernel paging request at virtual address fffb9340
/var/log/syslog.0:Dec 10 00:06:31 localhost kernel: EIP is at 
mmx_clear_page+0x29/0x7e
/var/log/syslog.0:Dec 10 00:06:31 localhost kernel: Process Xorg (pid: 
10450, ti=c758e000 task=d42fa030 task.ti=c758e000)
/var/log/syslog.0:Dec 10 00:06:31 localhost kernel: EIP: [<c01be3f7>] 
mmx_clear_page+0x29/0x7e SS:ESP 0068:c758feb0
/var/log/syslog.0:Dec 10 00:06:31 localhost kernel:  [<c01be3f7>] 
mmx_clear_page+0x29/0x7e
/var/log/syslog.0:Dec 10 00:06:31 localhost kernel:  [<c01be3f7>] 
mmx_clear_page+0x29/0x7e
/var/log/syslog.0:Dec 10 10:23:00 localhost kernel: BUG: unable to 
handle kernel paging request at virtual address fffb9000
/var/log/syslog.0:Dec 10 10:23:00 localhost kernel: EIP is at 
mmx_copy_page+0x51/0x123
/var/log/syslog.0:Dec 10 10:23:00 localhost kernel: Process cat (pid: 
8977, ti=db79c000 task=df987030 task.ti=db79c000)
/var/log/syslog.0:Dec 10 10:23:00 localhost kernel: EIP: [<c01be1bd>] 
mmx_copy_page+0x51/0x123 SS:ESP 0068:db79ddc8

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: 2.6.19 lot's of oops in  mmx_copy_page/ mmx_clear_page functions
  2006-12-10 11:32 2.6.19 lot's of oops in mmx_copy_page/ mmx_clear_page functions matthieu castet
@ 2006-12-10 19:02 ` Maxime Austruy
  2006-12-10 19:25   ` Ulrich Kunitz
  0 siblings, 1 reply; 3+ messages in thread
From: Maxime Austruy @ 2006-12-10 19:02 UTC (permalink / raw)
  To: matthieu castet; +Cc: Linux Kernel list, Daniel Drake, Ulrich Kunitz


Matthieu,

On Sun, Dec 10, 2006 at 12:32:08PM +0100, matthieu castet wrote:
> Hi,
> 
> with 2.6.19 I got some random crash and I got kernel opps.
> There all happens in  mmx_copy_page/ mmx_clear_page functions with 
> differents process : Xorg, cat, mozilla, ...
> 
> 
> What could be the cause of these crashes ?
> What can I provide in order to debug this ?

FWIW, I've seen the same oops on my box. My instance was caused by a
combination of:
 . zd1211rw calling ieee80211_rx in irq context while it's supposed to
   be called in softirq,
 . crypto code only expecting to be called in softirq/user context but
   not enforcing it.  Consequently, it ends up doing 
      v = kmap_atomic(..., KM_USER0);
   even when invoked by the zd1211rw driver in irq context, causing some
   corruption.

Given that you have zd1211rw insmod'd, that could be it.  I have some
hacks that work around this bug, but Ulrich has a patch ready that
should fix this. Thanks,

Max

> 
> 
> Thanks
> 
> Matthieu CASTET
> 
> 
> 
> BUG: unable to handle kernel paging request at virtual address fffb9000
>  printing eip:
> c01be1bd
> *pde = 00002067
> Oops: 0000 [#1]
> PREEMPT
> Modules linked in: michael_mic arc4 ecb ieee80211_crypt_tkip ehci_hcd 
> videodev v4l1_compat v4l2_common nfs nfsd exportfs lockd sunrpc sd_mod 
> sg sr_mod ppdev lp autofs4 button processor ipt_TOS ipt_MASQUERADE 
> ipt_ULOG ipt_LOG xt_tcpudp xt_state ipt_REJECT ipt_iprange xt_conntrack 
> iptable_mangle ip_nat_irc ip_nat_ftp iptable_nat ip_nat ip_conntrack_irc 
> ip_conntrack_ftp ip_conntrack iptable_filter ip_tables x_tables ide_cd 
> cdrom pcspkr snd_mpu401 ns558 parport_pc parport 8250_pnp 8250 
> serial_core floppy snd_via82xx snd_mpu401_uart emu10k1_gp gameport 
> snd_emu10k1_synth snd_emux_synth snd_seq_virmidi snd_seq_midi_emul 
> snd_seq_oss snd_seq_midi snd_seq_midi_event snd_seq snd_emu10k1 
> snd_rawmidi snd_ac97_codec snd_ac97_bus snd_pcm_oss snd_mixer_oss 
> snd_pcm snd_seq_device snd_timer snd_page_alloc snd_util_mem snd_hwdep 
> snd soundcore mii zd1211rw firmware_class ieee80211softmac ieee80211 
> ieee80211_crypt via_agp agpgart clip atm nls_iso8859_1 nls_cp437 vfat 
> fat nls_base reiserfs w83627hf hwmon_vid i2c_isa i2c_core evdev rtc
> CPU:    0
> EIP:    0060:[<c01be1bd>]    Not tainted VLI
> EFLAGS: 00010246   (2.6.19 #1)
> EIP is at mmx_copy_page+0x51/0x123
> eax: fffb9000   ebx: e2db9000   ecx: 00000000   edx: e2db9000
> esi: fffb9000   edi: e2db9000   ebp: c17e6040   esp: f671defc
> ds: 007b   es: 007b   ss: 0068
> Process automount (pid: 11921, ti=f671c000 task=f7cf0050 task.ti=f671c000)
> Stack: fffb9000 eb216040 c0140045 8001003c f5c95e40 f4ee2abc c145b720 
> 00000000
>        3f302065 f4ee2afc eb216040 f5c95e40 c014145f eb216040 f4f8a800 
> f4ee2afc
>        3f302065 393b4393 8001003c f4ee2abc 00000040 f4f8a800 00000000 
> f671df94
> Call Trace:
>  [<c0140045>] do_wp_page+0x291/0x414
>  [<c014145f>] __handle_mm_fault+0x7d2/0x873
>  [<c0112593>] do_page_fault+0x213/0x4dc
>  [<c0112380>] do_page_fault+0x0/0x4dc
>  [<c02a01e1>] error_code+0x39/0x40
>  =======================
> Code: f4 ff 0f 0d 06 0f 0d 46 40 0f 0d 86 80 00 00 00 0f 0d 86 c0 00 00 
> 00 0f 0d 86 00 01 00 00 31 c9 89 fa 89 f0 0f 0d 80 40 01 00 00 <0f> 6f 
> 00 0f e7 02 0f 6f 48 08 0f e7 4a 08 0f 6f 50 10 0f e7 52
> EIP: [<c01be1bd>] mmx_copy_page+0x51/0x123 SS:ESP 0068:f671defc
>  <6>note: automount[11921] exited with preempt_count 3
> 
> 
> 
> Sumary of Others failures :
> /var/log/syslog:Dec 10 10:40:14 localhost kernel: BUG: unable to handle 
> kernel paging request at virtual address fffb9b20
> /var/log/syslog:Dec 10 10:40:14 localhost kernel: EIP is at 
> mmx_clear_page+0x38/0x7e
> /var/log/syslog:Dec 10 10:40:14 localhost kernel: Process iceape-bin 
> (pid: 7061, ti=f7410000 task=eeb5a070 task.ti=f7410000)
> /var/log/syslog:Dec 10 10:40:14 localhost kernel: EIP: [<c01be406>] 
> mmx_clear_page+0x38/0x7e SS:ESP 0068:f7411eb0
> /var/log/syslog:Dec 10 10:40:24 localhost kernel: BUG: unable to handle 
> kernel paging request at virtual address fffb9a60
> /var/log/syslog:Dec 10 10:40:24 localhost kernel: EIP is at 
> mmx_clear_page+0x38/0x7e
> /var/log/syslog:Dec 10 10:40:24 localhost kernel: Process cc1 (pid: 
> 21797, ti=d62ea000 task=e86eb070 task.ti=d62ea000)
> /var/log/syslog:Dec 10 10:40:24 localhost kernel: EIP: [<c01be406>] 
> mmx_clear_page+0x38/0x7e SS:ESP 0068:d62ebeb0
> /var/log/syslog:Dec 10 11:12:37 localhost kernel: BUG: unable to handle 
> kernel paging request at virtual address fffb9000
> /var/log/syslog:Dec 10 11:12:37 localhost kernel: EIP is at 
> mmx_copy_page+0x51/0x123
> /var/log/syslog:Dec 10 11:12:37 localhost kernel: Process automount 
> (pid: 11921, ti=f671c000 task=f7cf0050 task.ti=f671c000)
> /var/log/syslog:Dec 10 11:12:37 localhost kernel: EIP: [<c01be1bd>] 
> mmx_copy_page+0x51/0x123 SS:ESP 0068:f671defc
> /var/log/syslog.0:Dec  9 19:21:50 localhost kernel: Process modprobe 
> (pid: 20516, ti=ee3d8000 task=f649f580 task.ti=ee3d8000)
> /var/log/syslog.0:Dec  9 22:15:15 localhost kernel: BUG: unable to 
> handle kernel paging request at virtual address fffb9000
> /var/log/syslog.0:Dec  9 22:15:15 localhost kernel: EIP is at 
> mmx_clear_page+0x29/0x7e
> /var/log/syslog.0:Dec  9 22:15:15 localhost kernel: Process Xorg (pid: 
> 9479, ti=d4ae0000 task=f671ca90 task.ti=d4ae0000)
> /var/log/syslog.0:Dec  9 22:15:15 localhost kernel: EIP: [<c01be3f7>] 
> mmx_clear_page+0x29/0x7e SS:ESP 0068:d4ae1eb0
> /var/log/syslog.0:Dec  9 22:15:15 localhost kernel:  [<c01be3f7>] 
> mmx_clear_page+0x29/0x7e
> /var/log/syslog.0:Dec  9 22:15:15 localhost kernel:  [<c01be3f7>] 
> mmx_clear_page+0x29/0x7e
> /var/log/syslog.0:Dec 10 00:06:31 localhost kernel: BUG: unable to 
> handle kernel paging request at virtual address fffb9340
> /var/log/syslog.0:Dec 10 00:06:31 localhost kernel: EIP is at 
> mmx_clear_page+0x29/0x7e
> /var/log/syslog.0:Dec 10 00:06:31 localhost kernel: Process Xorg (pid: 
> 10450, ti=c758e000 task=d42fa030 task.ti=c758e000)
> /var/log/syslog.0:Dec 10 00:06:31 localhost kernel: EIP: [<c01be3f7>] 
> mmx_clear_page+0x29/0x7e SS:ESP 0068:c758feb0
> /var/log/syslog.0:Dec 10 00:06:31 localhost kernel:  [<c01be3f7>] 
> mmx_clear_page+0x29/0x7e
> /var/log/syslog.0:Dec 10 00:06:31 localhost kernel:  [<c01be3f7>] 
> mmx_clear_page+0x29/0x7e
> /var/log/syslog.0:Dec 10 10:23:00 localhost kernel: BUG: unable to 
> handle kernel paging request at virtual address fffb9000
> /var/log/syslog.0:Dec 10 10:23:00 localhost kernel: EIP is at 
> mmx_copy_page+0x51/0x123
> /var/log/syslog.0:Dec 10 10:23:00 localhost kernel: Process cat (pid: 
> 8977, ti=db79c000 task=df987030 task.ti=db79c000)
> /var/log/syslog.0:Dec 10 10:23:00 localhost kernel: EIP: [<c01be1bd>] 
> mmx_copy_page+0x51/0x123 SS:ESP 0068:db79ddc8
> -
> 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	[flat|nested] 3+ messages in thread

* Re: 2.6.19 lot's of oops in  mmx_copy_page/ mmx_clear_page functions
  2006-12-10 19:02 ` Maxime Austruy
@ 2006-12-10 19:25   ` Ulrich Kunitz
  0 siblings, 0 replies; 3+ messages in thread
From: Ulrich Kunitz @ 2006-12-10 19:25 UTC (permalink / raw)
  To: Maxime Austruy
  Cc: zd1211-devs, matthieu castet, Linux Kernel list, Daniel Drake

On 06-12-10 11:02 Maxime Austruy wrote:

> 
> Matthieu,
> 
> On Sun, Dec 10, 2006 at 12:32:08PM +0100, matthieu castet wrote:
> > Hi,
> > 
> > with 2.6.19 I got some random crash and I got kernel opps.
> > There all happens in  mmx_copy_page/ mmx_clear_page functions with 
> > differents process : Xorg, cat, mozilla, ...
> > 
> > 
> > What could be the cause of these crashes ?
> > What can I provide in order to debug this ?
> 
> FWIW, I've seen the same oops on my box. My instance was caused by a
> combination of:
>  . zd1211rw calling ieee80211_rx in irq context while it's supposed to
>    be called in softirq,
>  . crypto code only expecting to be called in softirq/user context but
>    not enforcing it.  Consequently, it ends up doing 
>       v = kmap_atomic(..., KM_USER0);
>    even when invoked by the zd1211rw driver in irq context, causing some
>    corruption.
> 
> Given that you have zd1211rw insmod'd, that could be it.  I have some
> hacks that work around this bug, but Ulrich has a patch ready that
> should fix this. Thanks,
> 
> Max

Here is the patch against vanilla 2.6.19.

For Linus' latest tree I have sent also patches on netdev.

Users of my out-of-kernel git tree, should look at the branch rx.

Uli

[PATCH] zd1211rw: Call ieee80211_rx in tasklet

The driver called ieee80211_rx in hardware irq context. This
caused a problem withe crypto libraries and was against the
documentation/intention of the ieee80211_rx function. This patch
fixes that.

Signed-off-by: Ulrich Kunitz <kune@deine-taler.de>
---
 drivers/net/wireless/zd1211rw/zd_mac.c |   88 ++++++++++++++++++++++++--------
 drivers/net/wireless/zd1211rw/zd_mac.h |    6 ++
 drivers/net/wireless/zd1211rw/zd_usb.c |    4 +
 3 files changed, 72 insertions(+), 26 deletions(-)

diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c
index a7d29bd..f52dd3a 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.c
+++ b/drivers/net/wireless/zd1211rw/zd_mac.c
@@ -37,6 +37,8 @@ static void housekeeping_init(struct zd_
 static void housekeeping_enable(struct zd_mac *mac);
 static void housekeeping_disable(struct zd_mac *mac);
 
+static void do_rx(unsigned long mac_ptr);
+
 int zd_mac_init(struct zd_mac *mac,
 	        struct net_device *netdev,
 	        struct usb_interface *intf)
@@ -47,6 +49,10 @@ int zd_mac_init(struct zd_mac *mac,
 	spin_lock_init(&mac->lock);
 	mac->netdev = netdev;
 
+	skb_queue_head_init(&mac->rx_queue);
+	tasklet_init(&mac->rx_tasklet, do_rx, (unsigned long)mac);
+	tasklet_disable(&mac->rx_tasklet);
+
 	ieee_init(ieee);
 	softmac_init(ieee80211_priv(netdev));
 	zd_chip_init(&mac->chip, netdev, intf);
@@ -132,6 +138,8 @@ out:
 
 void zd_mac_clear(struct zd_mac *mac)
 {
+	skb_queue_purge(&mac->rx_queue);
+	tasklet_kill(&mac->rx_tasklet);
 	zd_chip_clear(&mac->chip);
 	ZD_ASSERT(!spin_is_locked(&mac->lock));
 	ZD_MEMCLEAR(mac, sizeof(struct zd_mac));
@@ -160,6 +168,8 @@ int zd_mac_open(struct net_device *netde
 	struct zd_chip *chip = &mac->chip;
 	int r;
 
+	tasklet_enable(&mac->rx_tasklet);
+
 	r = zd_chip_enable_int(chip);
 	if (r < 0)
 		goto out;
@@ -210,6 +220,8 @@ int zd_mac_stop(struct net_device *netde
 	 */
 
 	zd_chip_disable_rx(chip);
+	skb_queue_purge(&mac->rx_queue);
+	tasklet_disable(&mac->rx_tasklet);
 	housekeeping_disable(mac);
 	ieee80211softmac_stop(netdev);
 
@@ -873,45 +885,75 @@ static int fill_rx_stats(struct ieee8021
 	return 0;
 }
 
-int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length)
+static void zd_mac_rx(struct zd_mac *mac, struct sk_buff *skb)
 {
 	int r;
 	struct ieee80211_device *ieee = zd_mac_to_ieee80211(mac);
 	struct ieee80211_rx_stats stats;
 	const struct rx_status *status;
-	struct sk_buff *skb;
 
-	if (length < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
-	             IEEE80211_FCS_LEN + sizeof(struct rx_status))
-		return -EINVAL;
+	if (skb->len < ZD_PLCP_HEADER_SIZE + IEEE80211_1ADDR_LEN +
+	               IEEE80211_FCS_LEN + sizeof(struct rx_status))
+	{
+		dev_warn(zd_mac_dev(mac), "Packet with length %u to small.\n",
+			 skb->len);
+		goto free_skb;
+	}
 
-	r = fill_rx_stats(&stats, &status, mac, buffer, length);
-	if (r)
-		return r;
+	r = fill_rx_stats(&stats, &status, mac, skb->data, skb->len);
+	if (r) {
+		/* Only packets with rx errors are included here. */
+		goto free_skb;
+	}
 
-	length -= ZD_PLCP_HEADER_SIZE+IEEE80211_FCS_LEN+
-		  sizeof(struct rx_status);
-	buffer += ZD_PLCP_HEADER_SIZE;
+	__skb_pull(skb, ZD_PLCP_HEADER_SIZE);
+	__skb_trim(skb, skb->len -
+		        (IEEE80211_FCS_LEN + sizeof(struct rx_status)));
 
-	update_qual_rssi(mac, buffer, length, stats.signal, stats.rssi);
+	update_qual_rssi(mac, skb->data, skb->len, stats.signal,
+		         status->signal_strength);
 
-	r = filter_rx(ieee, buffer, length, &stats);
-	if (r <= 0)
-		return r;
+	r = filter_rx(ieee, skb->data, skb->len, &stats);
+	if (r <= 0) {
+		if (r < 0)
+			dev_dbg_f(zd_mac_dev(mac), "Error in packet.\n");
+		goto free_skb;
+	}
 
-	skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
-	if (!skb)
-		return -ENOMEM;
 	if (ieee->iw_mode == IW_MODE_MONITOR)
-		fill_rt_header(skb_put(skb, sizeof(struct zd_rt_hdr)), mac,
+		fill_rt_header(skb_push(skb, sizeof(struct zd_rt_hdr)), mac,
 			       &stats, status);
-	memcpy(skb_put(skb, length), buffer, length);
 
 	r = ieee80211_rx(ieee, skb, &stats);
-	if (!r) {
-		ZD_ASSERT(in_irq());
-		dev_kfree_skb_irq(skb);
+	if (r)
+		return;
+free_skb:
+	/* We are always in a soft irq. */
+	dev_kfree_skb(skb);
+}
+
+static void do_rx(unsigned long mac_ptr)
+{
+	struct zd_mac *mac = (struct zd_mac *)mac_ptr;
+	struct sk_buff *skb;
+
+	while ((skb = skb_dequeue(&mac->rx_queue)) != NULL)
+		zd_mac_rx(mac, skb);
+}
+
+int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length)
+{
+	struct sk_buff *skb;
+
+	skb = dev_alloc_skb(sizeof(struct zd_rt_hdr) + length);
+	if (!skb) {
+		dev_warn(zd_mac_dev(mac), "Could not allocate skb.\n");
+		return -ENOMEM;
 	}
+	skb_reserve(skb, sizeof(struct zd_rt_hdr));
+	memcpy(__skb_put(skb, length), buffer, length);
+	skb_queue_tail(&mac->rx_queue, skb);
+	tasklet_schedule(&mac->rx_tasklet);
 	return 0;
 }
 
diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h
index b8ea3de..c1bea87 100644
--- a/drivers/net/wireless/zd1211rw/zd_mac.h
+++ b/drivers/net/wireless/zd1211rw/zd_mac.h
@@ -133,6 +133,10 @@ struct zd_mac {
 	/* Unlocked reading possible */
 	struct iw_statistics iw_stats;
 	struct housekeeping housekeeping;
+
+	struct tasklet_struct rx_tasklet;
+	struct sk_buff_head rx_queue;
+
 	unsigned int stats_count;
 	u8 qual_buffer[ZD_MAC_STATS_BUFFER_SIZE];
 	u8 rssi_buffer[ZD_MAC_STATS_BUFFER_SIZE];
@@ -174,7 +178,7 @@ int zd_mac_open(struct net_device *netde
 int zd_mac_stop(struct net_device *netdev);
 int zd_mac_set_mac_address(struct net_device *dev, void *p);
 
-int zd_mac_rx(struct zd_mac *mac, const u8 *buffer, unsigned int length);
+int zd_mac_rx_irq(struct zd_mac *mac, const u8 *buffer, unsigned int length);
 
 int zd_mac_set_regdomain(struct zd_mac *zd_mac, u8 regdomain);
 u8 zd_mac_get_regdomain(struct zd_mac *zd_mac);
diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c
index 3faaeb2..4a5f5d5 100644
--- a/drivers/net/wireless/zd1211rw/zd_usb.c
+++ b/drivers/net/wireless/zd1211rw/zd_usb.c
@@ -599,13 +599,13 @@ static void handle_rx_packet(struct zd_u
 			n = l+k;
 			if (n > length)
 				return;
-			zd_mac_rx(mac, buffer+l, k);
+			zd_mac_rx_irq(mac, buffer+l, k);
 			if (i >= 2)
 				return;
 			l = (n+3) & ~3;
 		}
 	} else {
-		zd_mac_rx(mac, buffer, length);
+		zd_mac_rx_irq(mac, buffer, length);
 	}
 }
 
-- 
1.4.1


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2006-12-10 19:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-12-10 11:32 2.6.19 lot's of oops in mmx_copy_page/ mmx_clear_page functions matthieu castet
2006-12-10 19:02 ` Maxime Austruy
2006-12-10 19:25   ` Ulrich Kunitz

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