| From 44b341ae13557f646061530d281fbc19c5ae9111 Mon Sep 17 00:00:00 2001 |
| From: Darren Hart <dvhltc@us.ibm.com> |
| Date: Tue, 18 May 2010 14:33:07 -0700 |
| Subject: [PATCH] net: ehea: make rx irq handler non-threaded (IRQF_NODELAY) |
| |
| commit 44b341ae13557f646061530d281fbc19c5ae9111 in tip. |
| |
| The underlying hardware is edge triggered but presented by XICS as level |
| triggered. The edge triggered interrupts are not reissued after masking. This |
| is not a problem in mainline which does not mask the interrupt (relying on the |
| EOI mechanism instead). The threaded interrupts in PREEMPT_RT do mask the |
| interrupt, and can lose interrupts that occurred while masked, resulting in a |
| hung ethernet interface. |
| |
| The receive handler simply calls napi_schedule(), as such, there is no |
| significant additional overhead in making this non-threaded, since we either |
| wakeup the threaded irq handler to call napi_schedule(), or just call |
| napi_schedule() directly to wakeup the softirqs. As the receive handler is |
| lockless, there is no need to convert any of the ehea spinlock_t's to |
| raw_spinlock_t's. |
| |
| Without this patch, a simple scp file copy loop would fail quickly (usually |
| seconds). We have over two hours of sustained scp activity with the patch |
| applied. |
| |
| Credit goes to Will Schmidt for lots of instrumentation and tracing which |
| clarified the scenario and to Thomas Gleixner for the incredibly simple |
| solution. |
| |
| Signed-off-by: Darren Hart <dvhltc@us.ibm.com> |
| Acked-by: Will Schmidt <will_schmidt@vnet.ibm.com> |
| Cc: Jan-Bernd Themann <themann@de.ibm.com> |
| Cc: Nivedita Singhvi <niv@us.ibm.com> |
| Cc: Brian King <bjking1@us.ibm.com> |
| Cc: Michael Ellerman <ellerman@au1.ibm.com> |
| Cc: Doug Maxey <doug.maxey@us.ibm.com> |
| LKML-Reference: <4BF30793.5070300@us.ibm.com> |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| |
| diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c |
| index 7b62336..ec2d6d4 100644 |
| --- a/drivers/net/ehea/ehea_main.c |
| +++ b/drivers/net/ehea/ehea_main.c |
| @@ -1264,8 +1264,8 @@ static int ehea_reg_interrupts(struct net_device *dev) |
| "%s-queue%d", dev->name, i); |
| ret = ibmebus_request_irq(pr->eq->attr.ist1, |
| ehea_recv_irq_handler, |
| - IRQF_DISABLED, pr->int_send_name, |
| - pr); |
| + IRQF_DISABLED | IRQF_NODELAY, |
| + pr->int_send_name, pr); |
| if (ret) { |
| ehea_error("failed registering irq for ehea_queue " |
| "port_res_nr:%d, ist=%X", i, |
| -- |
| 1.7.1.1 |
| |