| From foo@baz Wed May 28 21:03:54 PDT 2014 |
| From: Nikolay Aleksandrov <nikolay@redhat.com> |
| Date: Fri, 9 May 2014 11:11:39 +0200 |
| Subject: sfc: fix calling of free_irq with already free vector |
| |
| From: Nikolay Aleksandrov <nikolay@redhat.com> |
| |
| [ Upstream commit 1c3639005f48492e5f2d965779efd814e80f8b15 ] |
| |
| If the sfc driver is in legacy interrupt mode (either explicitly by |
| using interrupt_mode module param or by falling back to it) it will |
| hit a warning at kernel/irq/manage.c because it will try to free an irq |
| which wasn't allocated by it in the first place because the MSI(X) irqs are |
| zero and it'll try to free them unconditionally. So fix it by checking if |
| we're in legacy mode and freeing the appropriate irqs. |
| |
| CC: Zenghui Shi <zshi@redhat.com> |
| CC: Ben Hutchings <ben@decadent.org.uk> |
| CC: <linux-net-drivers@solarflare.com> |
| CC: Shradha Shah <sshah@solarflare.com> |
| CC: David S. Miller <davem@davemloft.net> |
| |
| Fixes: 1899c111a535 ("sfc: Fix IRQ cleanup in case of a probe failure") |
| Reported-by: Zenghui Shi <zshi@redhat.com> |
| Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com> |
| Acked-by: Shradha Shah <sshah@solarflare.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/ethernet/sfc/nic.c | 14 ++++++++------ |
| 1 file changed, 8 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/net/ethernet/sfc/nic.c |
| +++ b/drivers/net/ethernet/sfc/nic.c |
| @@ -156,13 +156,15 @@ void efx_nic_fini_interrupt(struct efx_n |
| efx->net_dev->rx_cpu_rmap = NULL; |
| #endif |
| |
| - /* Disable MSI/MSI-X interrupts */ |
| - efx_for_each_channel(channel, efx) |
| - free_irq(channel->irq, &efx->msi_context[channel->channel]); |
| - |
| - /* Disable legacy interrupt */ |
| - if (efx->legacy_irq) |
| + if (EFX_INT_MODE_USE_MSI(efx)) { |
| + /* Disable MSI/MSI-X interrupts */ |
| + efx_for_each_channel(channel, efx) |
| + free_irq(channel->irq, |
| + &efx->msi_context[channel->channel]); |
| + } else { |
| + /* Disable legacy interrupt */ |
| free_irq(efx->legacy_irq, efx); |
| + } |
| } |
| |
| /* Register dump */ |