Message ID | 877dk162mo.ffs@nanos.tec.linutronix.de |
---|---|
State | New |
Headers | show |
Series | [RFC] r8152: Ensure that napi_schedule() is handled | expand |
On Sat, May 15, 2021 at 01:23:02AM +0200, Thomas Gleixner wrote: > We can make that work but sure I'm not going to argue when you decide to > just go for raise_softirq_irqsoff(). > > I just hacked that check up which is actually useful beyond NAPI. It's > straight forward except for that flush_smp_call_function_from_idle() > oddball, which immeditately triggered that assert because block mq uses > __raise_softirq_irqsoff() in a smp function call... > > See below. Peter might have opinions though :) Yeah, lovely stuff :-) > +#define lockdep_assert_softirq_raise_ok() \ > +do { \ > + WARN_ON_ONCE(__lockdep_enabled && \ > + !current->softirq_raise_safe && \ > + !(softirq_count() | hardirq_count())); \ > +} while (0) > --- a/kernel/smp.c > +++ b/kernel/smp.c > @@ -691,7 +691,9 @@ void flush_smp_call_function_from_idle(v > cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->idle, CFD_SEQ_NOCPU, > smp_processor_id(), CFD_SEQ_IDLE); > local_irq_save(flags); > + lockdep_set_softirq_raise_safe(); > flush_smp_call_function_queue(true); > + lockdep_clear_softirq_raise_safe(); > if (local_softirq_pending()) > do_softirq(); I think it might make more sense to raise hardirq_count() in/for flush_smp_call_function_queue() callers that aren't already from hardirq context. That's this site and smpcfd_dying_cpu(). Then we can do away with this new special case.
On Sat, May 15 2021 at 15:09, Peter Zijlstra wrote: > On Sat, May 15, 2021 at 01:23:02AM +0200, Thomas Gleixner wrote: >> --- a/kernel/smp.c >> +++ b/kernel/smp.c >> @@ -691,7 +691,9 @@ void flush_smp_call_function_from_idle(v >> cfd_seq_store(this_cpu_ptr(&cfd_seq_local)->idle, CFD_SEQ_NOCPU, >> smp_processor_id(), CFD_SEQ_IDLE); >> local_irq_save(flags); >> + lockdep_set_softirq_raise_safe(); >> flush_smp_call_function_queue(true); >> + lockdep_clear_softirq_raise_safe(); >> if (local_softirq_pending()) >> do_softirq(); > > I think it might make more sense to raise hardirq_count() in/for > flush_smp_call_function_queue() callers that aren't already from hardirq > context. That's this site and smpcfd_dying_cpu(). > > Then we can do away with this new special case. Right. Though I just checked smpcfd_dying_cpu(). That ones does not run softirqs after flushing the function queue and it can't do that because that's in the CPU dying phase with interrupts disabled where the CPU is already half torn down. Especially as softirq processing enables interrupts, which might cause even more havoc. Anyway how is it safe to run arbitrary functions there after the CPU removed itself from the online mask? That's daft to put it mildly. Thanks, tglx
--- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -1543,6 +1543,17 @@ void write_mii_word(struct net_device *n r8152_mdio_write(tp, reg, val); } +/* + * Wrapper around napi_schedule() to ensure that the raised network softirq + * is actually handled. + */ +static void r8152_napi_schedule(struct napi_struct *napi) +{ + local_bh_disable(); + napi_schedule(napi); + local_bh_enable(); +} + static int r8152_submit_rx(struct r8152 *tp, struct rx_agg *agg, gfp_t mem_flags); @@ -1753,7 +1764,7 @@ static void read_bulk_callback(struct ur spin_lock_irqsave(&tp->rx_lock, flags); list_add_tail(&agg->list, &tp->rx_done); spin_unlock_irqrestore(&tp->rx_lock, flags); - napi_schedule(&tp->napi); + r8152_napi_schedule(&tp->napi); return; case -ESHUTDOWN: rtl_set_unplug(tp); @@ -2640,7 +2651,7 @@ int r8152_submit_rx(struct r8152 *tp, st netif_err(tp, rx_err, tp->netdev, "Couldn't submit rx[%p], ret = %d\n", agg, ret); - napi_schedule(&tp->napi); + r8152_napi_schedule(&tp->napi); } return ret; @@ -8202,7 +8213,7 @@ static int rtl8152_post_reset(struct usb usb_submit_urb(tp->intr_urb, GFP_KERNEL); if (!list_empty(&tp->rx_done)) - napi_schedule(&tp->napi); + r8152_napi_schedule(&tp->napi); return 0; } @@ -8256,7 +8267,7 @@ static int rtl8152_runtime_resume(struct smp_mb__after_atomic(); if (!list_empty(&tp->rx_done)) - napi_schedule(&tp->napi); + r8152_napi_schedule(&tp->napi); usb_submit_urb(tp->intr_urb, GFP_NOIO); } else {