aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com>2017-07-10 09:55:46 -0400
committerDavid S. Miller <davem@davemloft.net>2017-07-11 16:40:22 -0400
commit6a146f3a5894b751cef16feb3d7903e45e3c445c (patch)
tree07842a437dde31130b7d13f505987b1426a60807
parent91d1ae475b9833097e078c2581c9265d033cdbe4 (diff)
cxgb4: fix BUG() on interrupt deallocating path of ULD
Since the introduction of ULD (Upper-Layer Drivers), the MSI-X deallocating path changed in cxgb4: the driver frees the interrupts of ULD when unregistering it or on shutdown PCI handler. Problem is that if a MSI-X is not freed before deallocated in the PCI layer, it will trigger a BUG() due to still "alive" interrupt being tentatively quiesced. The below trace was observed when doing a simple unbind of Chelsio's adapter PCI function, like: "echo 001e:80:00.4 > /sys/bus/pci/drivers/cxgb4/unbind" Trace: kernel BUG at drivers/pci/msi.c:352! Oops: Exception in kernel mode, sig: 5 [#1] ... NIP [c0000000005a5e60] free_msi_irqs+0xa0/0x250 LR [c0000000005a5e50] free_msi_irqs+0x90/0x250 Call Trace: [c0000000005a5e50] free_msi_irqs+0x90/0x250 (unreliable) [c0000000005a72c4] pci_disable_msix+0x124/0x180 [d000000011e06708] disable_msi+0x88/0xb0 [cxgb4] [d000000011e06948] free_some_resources+0xa8/0x160 [cxgb4] [d000000011e06d60] remove_one+0x170/0x3c0 [cxgb4] [c00000000058a910] pci_device_remove+0x70/0x110 [c00000000064ef04] device_release_driver_internal+0x1f4/0x2c0 ... This patch fixes the issue by refactoring the shutdown path of ULD on cxgb4 driver, by properly freeing and disabling interrupts on PCI remove handler too. Fixes: 0fbc81b3ad51 ("Allocate resources dynamically for all cxgb4 ULD's") Reported-by: Harsha Thyagaraja <hathyaga@in.ibm.com> Signed-off-by: Guilherme G. Piccoli <gpiccoli@linux.vnet.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c16
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c42
2 files changed, 36 insertions, 22 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 86f92e31e8aa..e403fa18f1b1 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -2083,12 +2083,12 @@ static void detach_ulds(struct adapter *adap)
2083 2083
2084 mutex_lock(&uld_mutex); 2084 mutex_lock(&uld_mutex);
2085 list_del(&adap->list_node); 2085 list_del(&adap->list_node);
2086
2086 for (i = 0; i < CXGB4_ULD_MAX; i++) 2087 for (i = 0; i < CXGB4_ULD_MAX; i++)
2087 if (adap->uld && adap->uld[i].handle) { 2088 if (adap->uld && adap->uld[i].handle)
2088 adap->uld[i].state_change(adap->uld[i].handle, 2089 adap->uld[i].state_change(adap->uld[i].handle,
2089 CXGB4_STATE_DETACH); 2090 CXGB4_STATE_DETACH);
2090 adap->uld[i].handle = NULL; 2091
2091 }
2092 if (netevent_registered && list_empty(&adapter_list)) { 2092 if (netevent_registered && list_empty(&adapter_list)) {
2093 unregister_netevent_notifier(&cxgb4_netevent_nb); 2093 unregister_netevent_notifier(&cxgb4_netevent_nb);
2094 netevent_registered = false; 2094 netevent_registered = false;
@@ -5303,8 +5303,10 @@ static void remove_one(struct pci_dev *pdev)
5303 */ 5303 */
5304 destroy_workqueue(adapter->workq); 5304 destroy_workqueue(adapter->workq);
5305 5305
5306 if (is_uld(adapter)) 5306 if (is_uld(adapter)) {
5307 detach_ulds(adapter); 5307 detach_ulds(adapter);
5308 t4_uld_clean_up(adapter);
5309 }
5308 5310
5309 disable_interrupts(adapter); 5311 disable_interrupts(adapter);
5310 5312
@@ -5385,7 +5387,11 @@ static void shutdown_one(struct pci_dev *pdev)
5385 if (adapter->port[i]->reg_state == NETREG_REGISTERED) 5387 if (adapter->port[i]->reg_state == NETREG_REGISTERED)
5386 cxgb_close(adapter->port[i]); 5388 cxgb_close(adapter->port[i]);
5387 5389
5388 t4_uld_clean_up(adapter); 5390 if (is_uld(adapter)) {
5391 detach_ulds(adapter);
5392 t4_uld_clean_up(adapter);
5393 }
5394
5389 disable_interrupts(adapter); 5395 disable_interrupts(adapter);
5390 disable_msi(adapter); 5396 disable_msi(adapter);
5391 5397
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
index ec53fe9dec68..71a315bc1409 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_uld.c
@@ -589,22 +589,37 @@ void t4_uld_mem_free(struct adapter *adap)
589 kfree(adap->uld); 589 kfree(adap->uld);
590} 590}
591 591
592/* This function should be called with uld_mutex taken. */
593static void cxgb4_shutdown_uld_adapter(struct adapter *adap, enum cxgb4_uld type)
594{
595 if (adap->uld[type].handle) {
596 adap->uld[type].handle = NULL;
597 adap->uld[type].add = NULL;
598 release_sge_txq_uld(adap, type);
599
600 if (adap->flags & FULL_INIT_DONE)
601 quiesce_rx_uld(adap, type);
602
603 if (adap->flags & USING_MSIX)
604 free_msix_queue_irqs_uld(adap, type);
605
606 free_sge_queues_uld(adap, type);
607 free_queues_uld(adap, type);
608 }
609}
610
592void t4_uld_clean_up(struct adapter *adap) 611void t4_uld_clean_up(struct adapter *adap)
593{ 612{
594 unsigned int i; 613 unsigned int i;
595 614
596 if (!adap->uld) 615 mutex_lock(&uld_mutex);
597 return;
598 for (i = 0; i < CXGB4_ULD_MAX; i++) { 616 for (i = 0; i < CXGB4_ULD_MAX; i++) {
599 if (!adap->uld[i].handle) 617 if (!adap->uld[i].handle)
600 continue; 618 continue;
601 if (adap->flags & FULL_INIT_DONE) 619
602 quiesce_rx_uld(adap, i); 620 cxgb4_shutdown_uld_adapter(adap, i);
603 if (adap->flags & USING_MSIX)
604 free_msix_queue_irqs_uld(adap, i);
605 free_sge_queues_uld(adap, i);
606 free_queues_uld(adap, i);
607 } 621 }
622 mutex_unlock(&uld_mutex);
608} 623}
609 624
610static void uld_init(struct adapter *adap, struct cxgb4_lld_info *lld) 625static void uld_init(struct adapter *adap, struct cxgb4_lld_info *lld)
@@ -783,15 +798,8 @@ int cxgb4_unregister_uld(enum cxgb4_uld type)
783 continue; 798 continue;
784 if (type == CXGB4_ULD_ISCSIT && is_t4(adap->params.chip)) 799 if (type == CXGB4_ULD_ISCSIT && is_t4(adap->params.chip))
785 continue; 800 continue;
786 adap->uld[type].handle = NULL; 801
787 adap->uld[type].add = NULL; 802 cxgb4_shutdown_uld_adapter(adap, type);
788 release_sge_txq_uld(adap, type);
789 if (adap->flags & FULL_INIT_DONE)
790 quiesce_rx_uld(adap, type);
791 if (adap->flags & USING_MSIX)
792 free_msix_queue_irqs_uld(adap, type);
793 free_sge_queues_uld(adap, type);
794 free_queues_uld(adap, type);
795 } 803 }
796 mutex_unlock(&uld_mutex); 804 mutex_unlock(&uld_mutex);
797 805