diff options
author | Gavin Shan <shangw@linux.vnet.ibm.com> | 2014-01-22 23:27:34 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-23 16:21:03 -0500 |
commit | 144be3d9f72fca538871b69b1f4c4af6f39d562a (patch) | |
tree | 53a4dd4093b834ce4eb4ef0ac3e421f20bf791cf /drivers/net | |
parent | 0cd8f9cc0654c06adde353c6532114c5f53a18e8 (diff) |
net/cxgb4: Avoid disabling PCI device for towice
If we have EEH error happens to the adapter and we have to remove
it from the system for some reasons (e.g. more than 5 EEH errors
detected from the device in last hour), the adapter will be disabled
for towice separately by eeh_err_detected() and remove_one(), which
will incur following unexpected backtrace. The patch tries to avoid
it.
WARNING: at drivers/pci/pci.c:1431
CPU: 12 PID: 121 Comm: eehd Not tainted 3.13.0-rc7+ #1
task: c0000001823a3780 ti: c00000018240c000 task.ti: c00000018240c000
NIP: c0000000003c1e40 LR: c0000000003c1e3c CTR: 0000000001764c5c
REGS: c00000018240f470 TRAP: 0700 Not tainted (3.13.0-rc7+)
MSR: 8000000000029032 <SF,EE,ME,IR,DR,RI> CR: 28000024 XER: 00000004
CFAR: c000000000706528 SOFTE: 1
GPR00: c0000000003c1e3c c00000018240f6f0 c0000000010fe1f8 0000000000000035
GPR04: 0000000000000000 0000000000000000 00000000003ae509 0000000000000000
GPR08: 000000000000346f 0000000000000000 0000000000000000 0000000000003fef
GPR12: 0000000028000022 c00000000ec93000 c0000000000c11b0 c000000184ac3e40
GPR16: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
GPR20: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
GPR24: 0000000000000000 c0000000009398d8 c00000000101f9c0 c0000001860ae000
GPR28: c000000182ba0000 00000000000001f0 c0000001860ae6f8 c0000001860ae000
NIP [c0000000003c1e40] .pci_disable_device+0xd0/0xf0
LR [c0000000003c1e3c] .pci_disable_device+0xcc/0xf0
Call Trace:
[c0000000003c1e3c] .pci_disable_device+0xcc/0xf0 (unreliable)
[d0000000073881c4] .remove_one+0x174/0x320 [cxgb4]
[c0000000003c57e0] .pci_device_remove+0x60/0x100
[c00000000046396c] .__device_release_driver+0x9c/0x120
[c000000000463a20] .device_release_driver+0x30/0x60
[c0000000003bcdb4] .pci_stop_bus_device+0x94/0xd0
[c0000000003bcf48] .pci_stop_and_remove_bus_device+0x18/0x30
[c00000000003f548] .pcibios_remove_pci_devices+0xa8/0x140
[c000000000035c00] .eeh_handle_normal_event+0xa0/0x3c0
[c000000000035f50] .eeh_handle_event+0x30/0x2b0
[c0000000000362c4] .eeh_event_handler+0xf4/0x1b0
[c0000000000c12b8] .kthread+0x108/0x130
[c00000000000a168] .ret_from_kernel_thread+0x5c/0x74
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | 5 | ||||
-rw-r--r-- | drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | 23 |
2 files changed, 21 insertions, 7 deletions
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h index 16782b2cff49..1f4b9b30b9ed 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h | |||
@@ -387,8 +387,9 @@ struct work_struct; | |||
387 | 387 | ||
388 | enum { /* adapter flags */ | 388 | enum { /* adapter flags */ |
389 | FULL_INIT_DONE = (1 << 0), | 389 | FULL_INIT_DONE = (1 << 0), |
390 | USING_MSI = (1 << 1), | 390 | DEV_ENABLED = (1 << 1), |
391 | USING_MSIX = (1 << 2), | 391 | USING_MSI = (1 << 2), |
392 | USING_MSIX = (1 << 3), | ||
392 | FW_OK = (1 << 4), | 393 | FW_OK = (1 << 4), |
393 | RSS_TNLALLLOOKUP = (1 << 5), | 394 | RSS_TNLALLLOOKUP = (1 << 5), |
394 | USING_SOFT_PARAMS = (1 << 6), | 395 | USING_SOFT_PARAMS = (1 << 6), |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index fff02ed1295e..c8eafbf1f51d 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | |||
@@ -5505,7 +5505,10 @@ static pci_ers_result_t eeh_err_detected(struct pci_dev *pdev, | |||
5505 | if (adap->flags & FULL_INIT_DONE) | 5505 | if (adap->flags & FULL_INIT_DONE) |
5506 | cxgb_down(adap); | 5506 | cxgb_down(adap); |
5507 | rtnl_unlock(); | 5507 | rtnl_unlock(); |
5508 | pci_disable_device(pdev); | 5508 | if ((adap->flags & DEV_ENABLED)) { |
5509 | pci_disable_device(pdev); | ||
5510 | adap->flags &= ~DEV_ENABLED; | ||
5511 | } | ||
5509 | out: return state == pci_channel_io_perm_failure ? | 5512 | out: return state == pci_channel_io_perm_failure ? |
5510 | PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; | 5513 | PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_NEED_RESET; |
5511 | } | 5514 | } |
@@ -5522,9 +5525,13 @@ static pci_ers_result_t eeh_slot_reset(struct pci_dev *pdev) | |||
5522 | return PCI_ERS_RESULT_RECOVERED; | 5525 | return PCI_ERS_RESULT_RECOVERED; |
5523 | } | 5526 | } |
5524 | 5527 | ||
5525 | if (pci_enable_device(pdev)) { | 5528 | if (!(adap->flags & DEV_ENABLED)) { |
5526 | dev_err(&pdev->dev, "cannot reenable PCI device after reset\n"); | 5529 | if (pci_enable_device(pdev)) { |
5527 | return PCI_ERS_RESULT_DISCONNECT; | 5530 | dev_err(&pdev->dev, "Cannot reenable PCI " |
5531 | "device after reset\n"); | ||
5532 | return PCI_ERS_RESULT_DISCONNECT; | ||
5533 | } | ||
5534 | adap->flags |= DEV_ENABLED; | ||
5528 | } | 5535 | } |
5529 | 5536 | ||
5530 | pci_set_master(pdev); | 5537 | pci_set_master(pdev); |
@@ -5910,6 +5917,9 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
5910 | goto out_disable_device; | 5917 | goto out_disable_device; |
5911 | } | 5918 | } |
5912 | 5919 | ||
5920 | /* PCI device has been enabled */ | ||
5921 | adapter->flags |= DEV_ENABLED; | ||
5922 | |||
5913 | adapter->regs = pci_ioremap_bar(pdev, 0); | 5923 | adapter->regs = pci_ioremap_bar(pdev, 0); |
5914 | if (!adapter->regs) { | 5924 | if (!adapter->regs) { |
5915 | dev_err(&pdev->dev, "cannot map device registers\n"); | 5925 | dev_err(&pdev->dev, "cannot map device registers\n"); |
@@ -6145,7 +6155,10 @@ static void remove_one(struct pci_dev *pdev) | |||
6145 | iounmap(adapter->bar2); | 6155 | iounmap(adapter->bar2); |
6146 | kfree(adapter); | 6156 | kfree(adapter); |
6147 | pci_disable_pcie_error_reporting(pdev); | 6157 | pci_disable_pcie_error_reporting(pdev); |
6148 | pci_disable_device(pdev); | 6158 | if ((adapter->flags & DEV_ENABLED)) { |
6159 | pci_disable_device(pdev); | ||
6160 | adapter->flags &= ~DEV_ENABLED; | ||
6161 | } | ||
6149 | pci_release_regions(pdev); | 6162 | pci_release_regions(pdev); |
6150 | } else | 6163 | } else |
6151 | pci_release_regions(pdev); | 6164 | pci_release_regions(pdev); |