Return-path: Received: from mail-ew0-f17.google.com ([209.85.219.17]:34549 "EHLO mail-ew0-f17.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754013AbZAEUcW (ORCPT ); Mon, 5 Jan 2009 15:32:22 -0500 Message-ID: <49626E4D.3010705@gmail.com> (sfid-20090105_213228_076704_32181AA3) Date: Mon, 05 Jan 2009 20:32:13 +0000 MIME-Version: 1.0 To: Andrey Borzenkov CC: orinoco-devel@lists.sourceforge.net, linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org Subject: Re: 2.6.28: warn_slowpath in orinoco receive path References: <200901052005.12428.arvidjaar@mail.ru> In-Reply-To: <200901052005.12428.arvidjaar@mail.ru> Content-Type: text/plain; charset=ISO-8859-1 From: Dave Sender: linux-wireless-owner@vger.kernel.org List-ID: Andrey Borzenkov wrote: > I would appreciate explanation which condition triggers this > warn_slowpath. Otherwise does it ring the bell for someone? Network was > dead after it till I reloaded modules (orinoco and hermes). > > [89479.105038] WARNING: at /home/bor/src/linux-git/lib/list_debug.c:30 > __list_add+0x8f/0xa0() > [89479.105058] list_add corruption. prev->next should be next > (dddb3568), but was cbc28978. (prev=dddb3568). > [89479.106002] Pid: 15746, comm: X Not tainted 2.6.28-1avb #26 > [89479.106020] Call Trace: > [89479.106062] [] warn_slowpath+0x60/0x80 > [89479.106104] [] ? native_sched_clock+0x20/0x70 > [89479.106194] [] ? lock_release_holdtime+0x35/0x200 > [89479.106218] [] ? __slab_alloc+0x550/0x560 > [89479.106254] [] ? _spin_unlock+0x1d/0x20 > [89479.106270] [] ? __slab_alloc+0x550/0x560 > [89479.106302] [] ? delay_tsc+0x17/0x24 > [89479.106319] [] ? __const_udelay+0x21/0x30 > [89479.106376] [] ? hermes_bap_seek+0x112/0x1e0 [hermes] > [89479.106396] [] ? trace_hardirqs_off+0xb/0x10 > [89479.106418] [] ? __kmalloc_track_caller+0xb7/0x110 > [89479.106448] [] ? dev_alloc_skb+0x1c/0x30 > [89479.106465] [] ? dev_alloc_skb+0x1c/0x30 > [89479.106482] [] __list_add+0x8f/0xa0 > [89479.106551] [] orinoco_interrupt+0xcae/0x16c0 [orinoco] > [89479.106574] [] ? tick_dev_program_event+0x33/0xb0 > [89479.106594] [] ? native_sched_clock+0x20/0x70 > [89479.106613] [] ? lock_release_holdtime+0x35/0x200 > [89479.106662] [] ? trace_hardirqs_off+0xb/0x10 > [89479.106892] [] ? usb_hcd_irq+0x97/0xa0 [usbcore] > [89479.106926] [] handle_IRQ_event+0x29/0x60 > [89479.106947] [] handle_level_irq+0x69/0xe0 > [89479.106963] [] ? handle_level_irq+0x0/0xe0 > [89479.106977] [] ? tcp_v4_rcv+0x633/0x6e0 > [89479.107025] [] ? common_interrupt+0x28/0x30 > [89479.107057] [] ? sk_run_filter+0x320/0x7a0 > [89479.107078] [] ? list_del+0x21/0x90 > [89479.107106] [] ? orinoco_rx_isr_tasklet+0x2ce/0x480 > [orinoco] > [89479.107131] [] ? __lock_acquire+0x160/0x1650 > [89479.107151] [] ? native_sched_clock+0x20/0x70 > [89479.107169] [] ? lock_release_holdtime+0x35/0x200 > [89479.107200] [] ? irq_enter+0xa/0x60 > [89479.107217] [] ? do_IRQ+0xd2/0x130 > [89479.107518] [] ? restore_nocheck_notrace+0x0/0xe > [89479.107542] [] ? __do_softirq+0x0/0x110 > [89479.107561] [] ? trace_hardirqs_on_caller+0x74/0x140 > [89479.107583] [] ? trace_hardirqs_on_thunk+0xc/0x10 > [89479.107602] [] ? tasklet_action+0x27/0x90 > [89479.107620] [] ? trace_hardirqs_on_caller+0x74/0x140 > [89479.107638] [] ? tasklet_action+0x43/0x90 > [89479.107655] [] ? __do_softirq+0x6f/0x110 > [89479.107674] [] ? __do_softirq+0x0/0x110 > [89479.107685] [] ? handle_level_irq+0x0/0xe0 > [89479.107715] [] ? irq_exit+0x5d/0x80 > [89479.107732] [] ? do_IRQ+0xd2/0x130 > [89479.107747] [] ? sysenter_exit+0xf/0x16 > [89479.107765] [] ? trace_hardirqs_on_caller+0xfd/0x140 > [89479.107782] [] ? common_interrupt+0x28/0x30 > [89479.107797] ---[ end trace a1fc0a52df4a729d ]--- Looks like the RX interrupt occurred at an inconvenient point during the list_del call in the RX tasklet (orinoco_rx_isr_tasklet). The call needs to be protected from the RX interrupt. Quick patch included below - I'm not sure that the local_irq_* functions are the ones we need, but it compiles and runs. I don't suppose you're able to reproduce the error? Dave. --- diff --git a/drivers/net/wireless/orinoco/orinoco.c b/drivers/net/wireless/orinoco/orinoco.c index b33e13f..9a2d6be 100644 --- a/drivers/net/wireless/orinoco/orinoco.c +++ b/drivers/net/wireless/orinoco/orinoco.c @@ -1616,9 +1616,15 @@ static void orinoco_rx_isr_tasklet(unsigned long data) /* extract desc and skb from queue */ list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) { + unsigned long flags; + desc = rx_data->desc; skb = rx_data->skb; + + local_irq_save(flags); list_del(&rx_data->list); + local_irq_restore(flags); + kfree(rx_data); orinoco_rx(dev, desc, skb);