diff options
Diffstat (limited to 'drivers/net/qlge')
-rw-r--r-- | drivers/net/qlge/qlge.h | 1 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_main.c | 78 | ||||
-rw-r--r-- | drivers/net/qlge/qlge_mpi.c | 23 |
3 files changed, 65 insertions, 37 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index 4b954e13c007..73c7fd2badcd 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h | |||
@@ -97,6 +97,7 @@ enum { | |||
97 | 97 | ||
98 | /* Misc. stuff */ | 98 | /* Misc. stuff */ |
99 | MAILBOX_COUNT = 16, | 99 | MAILBOX_COUNT = 16, |
100 | MAILBOX_TIMEOUT = 5, | ||
100 | 101 | ||
101 | PROC_ADDR_RDY = (1 << 31), | 102 | PROC_ADDR_RDY = (1 << 31), |
102 | PROC_ADDR_R = (1 << 30), | 103 | PROC_ADDR_R = (1 << 30), |
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index dd0ea0277550..42ad811ec313 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c | |||
@@ -4101,6 +4101,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev, | |||
4101 | goto err_out; | 4101 | goto err_out; |
4102 | } | 4102 | } |
4103 | 4103 | ||
4104 | pci_save_state(pdev); | ||
4104 | qdev->reg_base = | 4105 | qdev->reg_base = |
4105 | ioremap_nocache(pci_resource_start(pdev, 1), | 4106 | ioremap_nocache(pci_resource_start(pdev, 1), |
4106 | pci_resource_len(pdev, 1)); | 4107 | pci_resource_len(pdev, 1)); |
@@ -4255,6 +4256,33 @@ static void __devexit qlge_remove(struct pci_dev *pdev) | |||
4255 | free_netdev(ndev); | 4256 | free_netdev(ndev); |
4256 | } | 4257 | } |
4257 | 4258 | ||
4259 | /* Clean up resources without touching hardware. */ | ||
4260 | static void ql_eeh_close(struct net_device *ndev) | ||
4261 | { | ||
4262 | int i; | ||
4263 | struct ql_adapter *qdev = netdev_priv(ndev); | ||
4264 | |||
4265 | if (netif_carrier_ok(ndev)) { | ||
4266 | netif_carrier_off(ndev); | ||
4267 | netif_stop_queue(ndev); | ||
4268 | } | ||
4269 | |||
4270 | if (test_bit(QL_ADAPTER_UP, &qdev->flags)) | ||
4271 | cancel_delayed_work_sync(&qdev->asic_reset_work); | ||
4272 | cancel_delayed_work_sync(&qdev->mpi_reset_work); | ||
4273 | cancel_delayed_work_sync(&qdev->mpi_work); | ||
4274 | cancel_delayed_work_sync(&qdev->mpi_idc_work); | ||
4275 | cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); | ||
4276 | |||
4277 | for (i = 0; i < qdev->rss_ring_count; i++) | ||
4278 | netif_napi_del(&qdev->rx_ring[i].napi); | ||
4279 | |||
4280 | clear_bit(QL_ADAPTER_UP, &qdev->flags); | ||
4281 | ql_tx_ring_clean(qdev); | ||
4282 | ql_free_rx_buffers(qdev); | ||
4283 | ql_release_adapter_resources(qdev); | ||
4284 | } | ||
4285 | |||
4258 | /* | 4286 | /* |
4259 | * This callback is called by the PCI subsystem whenever | 4287 | * This callback is called by the PCI subsystem whenever |
4260 | * a PCI bus error is detected. | 4288 | * a PCI bus error is detected. |
@@ -4263,17 +4291,21 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, | |||
4263 | enum pci_channel_state state) | 4291 | enum pci_channel_state state) |
4264 | { | 4292 | { |
4265 | struct net_device *ndev = pci_get_drvdata(pdev); | 4293 | struct net_device *ndev = pci_get_drvdata(pdev); |
4266 | struct ql_adapter *qdev = netdev_priv(ndev); | ||
4267 | |||
4268 | netif_device_detach(ndev); | ||
4269 | 4294 | ||
4270 | if (state == pci_channel_io_perm_failure) | 4295 | switch (state) { |
4296 | case pci_channel_io_normal: | ||
4297 | return PCI_ERS_RESULT_CAN_RECOVER; | ||
4298 | case pci_channel_io_frozen: | ||
4299 | netif_device_detach(ndev); | ||
4300 | if (netif_running(ndev)) | ||
4301 | ql_eeh_close(ndev); | ||
4302 | pci_disable_device(pdev); | ||
4303 | return PCI_ERS_RESULT_NEED_RESET; | ||
4304 | case pci_channel_io_perm_failure: | ||
4305 | dev_err(&pdev->dev, | ||
4306 | "%s: pci_channel_io_perm_failure.\n", __func__); | ||
4271 | return PCI_ERS_RESULT_DISCONNECT; | 4307 | return PCI_ERS_RESULT_DISCONNECT; |
4272 | 4308 | } | |
4273 | if (netif_running(ndev)) | ||
4274 | ql_adapter_down(qdev); | ||
4275 | |||
4276 | pci_disable_device(pdev); | ||
4277 | 4309 | ||
4278 | /* Request a slot reset. */ | 4310 | /* Request a slot reset. */ |
4279 | return PCI_ERS_RESULT_NEED_RESET; | 4311 | return PCI_ERS_RESULT_NEED_RESET; |
@@ -4290,25 +4322,15 @@ static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev) | |||
4290 | struct net_device *ndev = pci_get_drvdata(pdev); | 4322 | struct net_device *ndev = pci_get_drvdata(pdev); |
4291 | struct ql_adapter *qdev = netdev_priv(ndev); | 4323 | struct ql_adapter *qdev = netdev_priv(ndev); |
4292 | 4324 | ||
4325 | pdev->error_state = pci_channel_io_normal; | ||
4326 | |||
4327 | pci_restore_state(pdev); | ||
4293 | if (pci_enable_device(pdev)) { | 4328 | if (pci_enable_device(pdev)) { |
4294 | QPRINTK(qdev, IFUP, ERR, | 4329 | QPRINTK(qdev, IFUP, ERR, |
4295 | "Cannot re-enable PCI device after reset.\n"); | 4330 | "Cannot re-enable PCI device after reset.\n"); |
4296 | return PCI_ERS_RESULT_DISCONNECT; | 4331 | return PCI_ERS_RESULT_DISCONNECT; |
4297 | } | 4332 | } |
4298 | |||
4299 | pci_set_master(pdev); | 4333 | pci_set_master(pdev); |
4300 | |||
4301 | netif_carrier_off(ndev); | ||
4302 | ql_adapter_reset(qdev); | ||
4303 | |||
4304 | /* Make sure the EEPROM is good */ | ||
4305 | memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); | ||
4306 | |||
4307 | if (!is_valid_ether_addr(ndev->perm_addr)) { | ||
4308 | QPRINTK(qdev, IFUP, ERR, "After reset, invalid MAC address.\n"); | ||
4309 | return PCI_ERS_RESULT_DISCONNECT; | ||
4310 | } | ||
4311 | |||
4312 | return PCI_ERS_RESULT_RECOVERED; | 4334 | return PCI_ERS_RESULT_RECOVERED; |
4313 | } | 4335 | } |
4314 | 4336 | ||
@@ -4316,17 +4338,21 @@ static void qlge_io_resume(struct pci_dev *pdev) | |||
4316 | { | 4338 | { |
4317 | struct net_device *ndev = pci_get_drvdata(pdev); | 4339 | struct net_device *ndev = pci_get_drvdata(pdev); |
4318 | struct ql_adapter *qdev = netdev_priv(ndev); | 4340 | struct ql_adapter *qdev = netdev_priv(ndev); |
4341 | int err = 0; | ||
4319 | 4342 | ||
4320 | pci_set_master(pdev); | 4343 | if (ql_adapter_reset(qdev)) |
4321 | 4344 | QPRINTK(qdev, DRV, ERR, "reset FAILED!\n"); | |
4322 | if (netif_running(ndev)) { | 4345 | if (netif_running(ndev)) { |
4323 | if (ql_adapter_up(qdev)) { | 4346 | err = qlge_open(ndev); |
4347 | if (err) { | ||
4324 | QPRINTK(qdev, IFUP, ERR, | 4348 | QPRINTK(qdev, IFUP, ERR, |
4325 | "Device initialization failed after reset.\n"); | 4349 | "Device initialization failed after reset.\n"); |
4326 | return; | 4350 | return; |
4327 | } | 4351 | } |
4352 | } else { | ||
4353 | QPRINTK(qdev, IFUP, ERR, | ||
4354 | "Device was not running prior to EEH.\n"); | ||
4328 | } | 4355 | } |
4329 | |||
4330 | netif_device_attach(ndev); | 4356 | netif_device_attach(ndev); |
4331 | } | 4357 | } |
4332 | 4358 | ||
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 80b68539c5aa..bac7b86f2129 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c | |||
@@ -454,7 +454,8 @@ end: | |||
454 | */ | 454 | */ |
455 | static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) | 455 | static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) |
456 | { | 456 | { |
457 | int status, count; | 457 | int status; |
458 | unsigned long count; | ||
458 | 459 | ||
459 | 460 | ||
460 | /* Begin polled mode for MPI */ | 461 | /* Begin polled mode for MPI */ |
@@ -475,9 +476,9 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) | |||
475 | /* Wait for the command to complete. We loop | 476 | /* Wait for the command to complete. We loop |
476 | * here because some AEN might arrive while | 477 | * here because some AEN might arrive while |
477 | * we're waiting for the mailbox command to | 478 | * we're waiting for the mailbox command to |
478 | * complete. If more than 5 arrive then we can | 479 | * complete. If more than 5 seconds expire we can |
479 | * assume something is wrong. */ | 480 | * assume something is wrong. */ |
480 | count = 5; | 481 | count = jiffies + HZ * MAILBOX_TIMEOUT; |
481 | do { | 482 | do { |
482 | /* Wait for the interrupt to come in. */ | 483 | /* Wait for the interrupt to come in. */ |
483 | status = ql_wait_mbx_cmd_cmplt(qdev); | 484 | status = ql_wait_mbx_cmd_cmplt(qdev); |
@@ -501,15 +502,15 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) | |||
501 | MB_CMD_STS_GOOD) || | 502 | MB_CMD_STS_GOOD) || |
502 | ((mbcp->mbox_out[0] & 0x0000f000) == | 503 | ((mbcp->mbox_out[0] & 0x0000f000) == |
503 | MB_CMD_STS_INTRMDT)) | 504 | MB_CMD_STS_INTRMDT)) |
504 | break; | 505 | goto done; |
505 | } while (--count); | 506 | } while (time_before(jiffies, count)); |
506 | 507 | ||
507 | if (!count) { | 508 | QPRINTK(qdev, DRV, ERR, |
508 | QPRINTK(qdev, DRV, ERR, | 509 | "Timed out waiting for mailbox complete.\n"); |
509 | "Timed out waiting for mailbox complete.\n"); | 510 | status = -ETIMEDOUT; |
510 | status = -ETIMEDOUT; | 511 | goto end; |
511 | goto end; | 512 | |
512 | } | 513 | done: |
513 | 514 | ||
514 | /* Now we can clear the interrupt condition | 515 | /* Now we can clear the interrupt condition |
515 | * and look at our status. | 516 | * and look at our status. |