diff options
author | Robert Jennings <rcj@linux.vnet.ibm.com> | 2010-07-16 00:57:25 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-07-16 16:03:23 -0400 |
commit | ee2e6114de3bdb1c34f3910b690f990483e981ab (patch) | |
tree | a6b4de8355b31824103e24dc81bc0515c08d99b0 | |
parent | 0f6142fa96a4ce799ccaa4cdb38fc4a715eb9d35 (diff) |
ibmveth: lost IRQ while closing/opening device leads to service loss
The order of freeing the IRQ and freeing the device in firmware
in ibmveth_close can cause the adapter to become unusable after a
subsequent ibmveth_open. Only a reboot of the OS will make the
network device usable again. This is seen when cycling the adapter
up and down while there is network activity.
There is a window where an IRQ will be left unserviced (H_EOI will not
be called). The solution is to make a VIO_IRQ_DISABLE h_call, free the
device with firmware, and then call free_irq.
Signed-off-by: Robert Jennings <rcj@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ibmveth.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 7acb3edc47ef..2602852cc55a 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c | |||
@@ -677,7 +677,7 @@ static int ibmveth_close(struct net_device *netdev) | |||
677 | if (!adapter->pool_config) | 677 | if (!adapter->pool_config) |
678 | netif_stop_queue(netdev); | 678 | netif_stop_queue(netdev); |
679 | 679 | ||
680 | free_irq(netdev->irq, netdev); | 680 | h_vio_signal(adapter->vdev->unit_address, VIO_IRQ_DISABLE); |
681 | 681 | ||
682 | do { | 682 | do { |
683 | lpar_rc = h_free_logical_lan(adapter->vdev->unit_address); | 683 | lpar_rc = h_free_logical_lan(adapter->vdev->unit_address); |
@@ -689,6 +689,8 @@ static int ibmveth_close(struct net_device *netdev) | |||
689 | lpar_rc); | 689 | lpar_rc); |
690 | } | 690 | } |
691 | 691 | ||
692 | free_irq(netdev->irq, netdev); | ||
693 | |||
692 | adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8); | 694 | adapter->rx_no_buffer = *(u64*)(((char*)adapter->buffer_list_addr) + 4096 - 8); |
693 | 695 | ||
694 | ibmveth_cleanup(adapter); | 696 | ibmveth_cleanup(adapter); |