Bug 7752 - drivers/net/wireless/zd1211rw/zd_chip.c:1461 ASSERT r >= 0 VIOLATED!
Summary: drivers/net/wireless/zd1211rw/zd_chip.c:1461 ASSERT r >= 0 VIOLATED!
Status: REJECTED INSUFFICIENT_DATA
Alias: None
Product: Drivers
Classification: Unclassified
Component: network-wireless (show other bugs)
Hardware: i386 Linux
: P2 normal
Assignee: Ulrich Kunitz
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-12-29 20:44 UTC by Maxime Austruy
Modified: 2009-03-02 16:52 UTC (History)
5 users (show)

See Also:
Kernel Version: 2.6.20-rc2-g7479b1ce
Subsystem:
Regression: ---
Bisected commit-id:


Attachments
Patch for debug output (861 bytes, patch)
2006-12-30 12:32 UTC, Ulrich Kunitz
Details | Diff

Description Maxime Austruy 2006-12-29 20:44:24 UTC
Most recent kernel where this bug did *NOT* occur: Not sure. I saw this with 2.6.19.

 firmware version 4721
 zd1211b chip 0ace:1215 v4810 high 00-02-72 AL2230_RF pa0 g--N

I was exercising a wireless link with a simple script
run over an ssh connection:

  while [ true ]; do ls -al; done

After 20-30min, I got this:

drivers/net/wireless/zd1211rw/zd_chip.c:1461 ASSERT r >= 0 VIOLATED!
 [<c010412a>] show_trace_log_lvl+0x1a/0x30
 [<c01048a2>] show_trace+0x12/0x20
 [<c01049a6>] dump_stack+0x16/0x20
 [<fa93f98c>] zd_rx_qual_percent+0x4c/0x180 [zd1211rw]
 [<fa941685>] do_rx+0xe5/0x470 [zd1211rw]
 [<c011f048>] tasklet_action+0x38/0x80
 [<c011ef52>] __do_softirq+0x62/0xc0
 [<c011f005>] do_softirq+0x55/0x60
 [<c011f278>] irq_exit+0x48/0x50
 [<c0105af7>] do_IRQ+0x57/0x90
 [<c0103b96>] common_interrupt+0x2e/0x34
 [<c02bde48>] n_tty_chars_in_buffer+0x38/0x80
 [<c02c0819>] pty_chars_in_buffer+0x19/0x40
 [<c02be555>] normal_poll+0xd5/0x150
 [<c02bac36>] tty_poll+0x66/0x80
 [<c016b5a7>] do_select+0x317/0x590
 [<c016b9f6>] core_sys_select+0x1d6/0x330
 [<c016c19f>] sys_select+0x3f/0x1b0
 [<c01031ac>] syscall_call+0x7/0xb
 =======================

coming from:

static int ofdm_qual_percent(u8 status_quality, u8 rate, unsigned int size)
{
        int r;

        r = ofdm_qual_db(status_quality, rate, size);
        ZD_ASSERT(r >= 0);   <--- XXX
        if (r < 0)
                r = 0;

        r = (r * 100)/29;
        return r <= 100 ? r : 100;
}

A quick look at the code shows that it could be coming
from a bogus value given by the h/w in:
 status->signal_quality_ofdm

Note that there are also lots and lots of:
 zd1211rw 5-3:1.0: zd_mac_rx() Packet with length 22 to small.
as well as a few:
 zd1211rw 5-3:1.0: zd_mac_rx() Packet with length 1 to small.
very rarely:
 zd1211rw 5-3:1.0: zd_mac_rx() Packet with length 17 to small.
and also two instances of:
 zd1211rw 5-3:1.0: zd_mac_rx() Error in packet.

Like I mentioned, I also saw this ASSERT fail with 2.6.19.

Tentatively assigning this to Daniel.
Comment 1 Ulrich Kunitz 2006-12-30 12:32:31 UTC
Created attachment 9970 [details]
Patch for debug output
Comment 2 Ulrich Kunitz 2006-12-30 12:37:43 UTC
The debugging ASSERT indicates unexpected behaviour, but the case is correctly
handled by the code. To find the cause and fix it -- I added a patch, which
outputs additional information.

The other debug message indicate that the device sends broken packets to the
host. This is handled correctly by the driver and doesn't indicate a bug of the
driver.
Comment 3 Natalie Protasevich 2007-08-01 23:22:43 UTC
Any updates on this problem? 
Thanks.
Comment 4 Zac Wheeler 2009-03-02 16:52:19 UTC
This appears to still be present in 2.6.28.4.

I could very well be wrong, but this looks to me to be caused by the variable 'size' equal to zero being passed to ofdm_qual_db(status_quality, rate, size) which does not check for this condition before it divides by 'size':

x = (10000 * status_quality)/size;

I avoid the issue (since I am not interested in figuring out what the correct thing is to do with a size of zero, maybe return -EINVAL?) by modifying the calling function so:

static int ofdm_qual_percent(u8 status_quality, u8 zd_rate, unsigned int size)
{
        int r = 0;

        if (size > 0)
                 r = ofdm_qual_db(status_quality, zd_rate, size);
        ZD_ASSERT(r >= 0);
        if (r < 0)
                r = 0;

        r = (r * 100)/29;
        return r <= 100 ? r : 100;
}

Note You need to log in before you can comment on or make changes to this bug.