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 | 80 | ||||
| -rw-r--r-- | drivers/net/qlge/qlge_mpi.c | 25 |
3 files changed, 68 insertions, 38 deletions
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index e7285f01bd04..c2383adcd527 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h | |||
| @@ -95,6 +95,7 @@ enum { | |||
| 95 | 95 | ||
| 96 | /* Misc. stuff */ | 96 | /* Misc. stuff */ |
| 97 | MAILBOX_COUNT = 16, | 97 | MAILBOX_COUNT = 16, |
| 98 | MAILBOX_TIMEOUT = 5, | ||
| 98 | 99 | ||
| 99 | PROC_ADDR_RDY = (1 << 31), | 100 | PROC_ADDR_RDY = (1 << 31), |
| 100 | PROC_ADDR_R = (1 << 30), | 101 | PROC_ADDR_R = (1 << 30), |
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 48b45df85ec9..a2fc70a0d0cc 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c | |||
| @@ -3916,6 +3916,9 @@ static int __devinit ql_init_device(struct pci_dev *pdev, | |||
| 3916 | goto err_out; | 3916 | goto err_out; |
| 3917 | } | 3917 | } |
| 3918 | 3918 | ||
| 3919 | /* Set PCIe reset type for EEH to fundamental. */ | ||
| 3920 | pdev->needs_freset = 1; | ||
| 3921 | pci_save_state(pdev); | ||
| 3919 | qdev->reg_base = | 3922 | qdev->reg_base = |
| 3920 | ioremap_nocache(pci_resource_start(pdev, 1), | 3923 | ioremap_nocache(pci_resource_start(pdev, 1), |
| 3921 | pci_resource_len(pdev, 1)); | 3924 | pci_resource_len(pdev, 1)); |
| @@ -4070,6 +4073,33 @@ static void __devexit qlge_remove(struct pci_dev *pdev) | |||
| 4070 | free_netdev(ndev); | 4073 | free_netdev(ndev); |
| 4071 | } | 4074 | } |
| 4072 | 4075 | ||
| 4076 | /* Clean up resources without touching hardware. */ | ||
| 4077 | static void ql_eeh_close(struct net_device *ndev) | ||
| 4078 | { | ||
| 4079 | int i; | ||
| 4080 | struct ql_adapter *qdev = netdev_priv(ndev); | ||
| 4081 | |||
| 4082 | if (netif_carrier_ok(ndev)) { | ||
| 4083 | netif_carrier_off(ndev); | ||
| 4084 | netif_stop_queue(ndev); | ||
| 4085 | } | ||
| 4086 | |||
| 4087 | if (test_bit(QL_ADAPTER_UP, &qdev->flags)) | ||
| 4088 | cancel_delayed_work_sync(&qdev->asic_reset_work); | ||
| 4089 | cancel_delayed_work_sync(&qdev->mpi_reset_work); | ||
| 4090 | cancel_delayed_work_sync(&qdev->mpi_work); | ||
| 4091 | cancel_delayed_work_sync(&qdev->mpi_idc_work); | ||
| 4092 | cancel_delayed_work_sync(&qdev->mpi_port_cfg_work); | ||
| 4093 | |||
| 4094 | for (i = 0; i < qdev->rss_ring_count; i++) | ||
| 4095 | netif_napi_del(&qdev->rx_ring[i].napi); | ||
| 4096 | |||
| 4097 | clear_bit(QL_ADAPTER_UP, &qdev->flags); | ||
| 4098 | ql_tx_ring_clean(qdev); | ||
| 4099 | ql_free_rx_buffers(qdev); | ||
| 4100 | ql_release_adapter_resources(qdev); | ||
| 4101 | } | ||
| 4102 | |||
| 4073 | /* | 4103 | /* |
| 4074 | * This callback is called by the PCI subsystem whenever | 4104 | * This callback is called by the PCI subsystem whenever |
| 4075 | * a PCI bus error is detected. | 4105 | * a PCI bus error is detected. |
| @@ -4078,17 +4108,21 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev, | |||
| 4078 | enum pci_channel_state state) | 4108 | enum pci_channel_state state) |
| 4079 | { | 4109 | { |
| 4080 | struct net_device *ndev = pci_get_drvdata(pdev); | 4110 | struct net_device *ndev = pci_get_drvdata(pdev); |
| 4081 | struct ql_adapter *qdev = netdev_priv(ndev); | ||
| 4082 | |||
| 4083 | netif_device_detach(ndev); | ||
| 4084 | 4111 | ||
| 4085 | if (state == pci_channel_io_perm_failure) | 4112 | switch (state) { |
| 4113 | case pci_channel_io_normal: | ||
| 4114 | return PCI_ERS_RESULT_CAN_RECOVER; | ||
| 4115 | case pci_channel_io_frozen: | ||
| 4116 | netif_device_detach(ndev); | ||
| 4117 | if (netif_running(ndev)) | ||
| 4118 | ql_eeh_close(ndev); | ||
| 4119 | pci_disable_device(pdev); | ||
| 4120 | return PCI_ERS_RESULT_NEED_RESET; | ||
| 4121 | case pci_channel_io_perm_failure: | ||
| 4122 | dev_err(&pdev->dev, | ||
| 4123 | "%s: pci_channel_io_perm_failure.\n", __func__); | ||
| 4086 | return PCI_ERS_RESULT_DISCONNECT; | 4124 | return PCI_ERS_RESULT_DISCONNECT; |
| 4087 | 4125 | } | |
| 4088 | if (netif_running(ndev)) | ||
| 4089 | ql_adapter_down(qdev); | ||
| 4090 | |||
| 4091 | pci_disable_device(pdev); | ||
| 4092 | 4126 | ||
| 4093 | /* Request a slot reset. */ | 4127 | /* Request a slot reset. */ |
| 4094 | return PCI_ERS_RESULT_NEED_RESET; | 4128 | return PCI_ERS_RESULT_NEED_RESET; |
| @@ -4105,25 +4139,15 @@ static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev) | |||
| 4105 | struct net_device *ndev = pci_get_drvdata(pdev); | 4139 | struct net_device *ndev = pci_get_drvdata(pdev); |
| 4106 | struct ql_adapter *qdev = netdev_priv(ndev); | 4140 | struct ql_adapter *qdev = netdev_priv(ndev); |
| 4107 | 4141 | ||
| 4142 | pdev->error_state = pci_channel_io_normal; | ||
| 4143 | |||
| 4144 | pci_restore_state(pdev); | ||
| 4108 | if (pci_enable_device(pdev)) { | 4145 | if (pci_enable_device(pdev)) { |
| 4109 | QPRINTK(qdev, IFUP, ERR, | 4146 | QPRINTK(qdev, IFUP, ERR, |
| 4110 | "Cannot re-enable PCI device after reset.\n"); | 4147 | "Cannot re-enable PCI device after reset.\n"); |
| 4111 | return PCI_ERS_RESULT_DISCONNECT; | 4148 | return PCI_ERS_RESULT_DISCONNECT; |
| 4112 | } | 4149 | } |
| 4113 | |||
| 4114 | pci_set_master(pdev); | 4150 | pci_set_master(pdev); |
| 4115 | |||
| 4116 | netif_carrier_off(ndev); | ||
| 4117 | ql_adapter_reset(qdev); | ||
| 4118 | |||
| 4119 | /* Make sure the EEPROM is good */ | ||
| 4120 | memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len); | ||
| 4121 | |||
| 4122 | if (!is_valid_ether_addr(ndev->perm_addr)) { | ||
| 4123 | QPRINTK(qdev, IFUP, ERR, "After reset, invalid MAC address.\n"); | ||
| 4124 | return PCI_ERS_RESULT_DISCONNECT; | ||
| 4125 | } | ||
| 4126 | |||
| 4127 | return PCI_ERS_RESULT_RECOVERED; | 4151 | return PCI_ERS_RESULT_RECOVERED; |
| 4128 | } | 4152 | } |
| 4129 | 4153 | ||
| @@ -4131,17 +4155,21 @@ static void qlge_io_resume(struct pci_dev *pdev) | |||
| 4131 | { | 4155 | { |
| 4132 | struct net_device *ndev = pci_get_drvdata(pdev); | 4156 | struct net_device *ndev = pci_get_drvdata(pdev); |
| 4133 | struct ql_adapter *qdev = netdev_priv(ndev); | 4157 | struct ql_adapter *qdev = netdev_priv(ndev); |
| 4158 | int err = 0; | ||
| 4134 | 4159 | ||
| 4135 | pci_set_master(pdev); | 4160 | if (ql_adapter_reset(qdev)) |
| 4136 | 4161 | QPRINTK(qdev, DRV, ERR, "reset FAILED!\n"); | |
| 4137 | if (netif_running(ndev)) { | 4162 | if (netif_running(ndev)) { |
| 4138 | if (ql_adapter_up(qdev)) { | 4163 | err = qlge_open(ndev); |
| 4164 | if (err) { | ||
| 4139 | QPRINTK(qdev, IFUP, ERR, | 4165 | QPRINTK(qdev, IFUP, ERR, |
| 4140 | "Device initialization failed after reset.\n"); | 4166 | "Device initialization failed after reset.\n"); |
| 4141 | return; | 4167 | return; |
| 4142 | } | 4168 | } |
| 4169 | } else { | ||
| 4170 | QPRINTK(qdev, IFUP, ERR, | ||
| 4171 | "Device was not running prior to EEH.\n"); | ||
| 4143 | } | 4172 | } |
| 4144 | |||
| 4145 | netif_device_attach(ndev); | 4173 | netif_device_attach(ndev); |
| 4146 | } | 4174 | } |
| 4147 | 4175 | ||
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c index 99e58e3f8e22..aec05f266107 100644 --- a/drivers/net/qlge/qlge_mpi.c +++ b/drivers/net/qlge/qlge_mpi.c | |||
| @@ -470,7 +470,8 @@ end: | |||
| 470 | */ | 470 | */ |
| 471 | static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) | 471 | static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) |
| 472 | { | 472 | { |
| 473 | int status, count; | 473 | int status; |
| 474 | unsigned long count; | ||
| 474 | 475 | ||
| 475 | 476 | ||
| 476 | /* Begin polled mode for MPI */ | 477 | /* Begin polled mode for MPI */ |
| @@ -491,14 +492,14 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) | |||
| 491 | /* Wait for the command to complete. We loop | 492 | /* Wait for the command to complete. We loop |
| 492 | * here because some AEN might arrive while | 493 | * here because some AEN might arrive while |
| 493 | * we're waiting for the mailbox command to | 494 | * we're waiting for the mailbox command to |
| 494 | * complete. If more than 5 arrive then we can | 495 | * complete. If more than 5 seconds expire we can |
| 495 | * assume something is wrong. */ | 496 | * assume something is wrong. */ |
| 496 | count = 5; | 497 | count = jiffies + HZ * MAILBOX_TIMEOUT; |
| 497 | do { | 498 | do { |
| 498 | /* Wait for the interrupt to come in. */ | 499 | /* Wait for the interrupt to come in. */ |
| 499 | status = ql_wait_mbx_cmd_cmplt(qdev); | 500 | status = ql_wait_mbx_cmd_cmplt(qdev); |
| 500 | if (status) | 501 | if (status) |
| 501 | goto end; | 502 | continue; |
| 502 | 503 | ||
| 503 | /* Process the event. If it's an AEN, it | 504 | /* Process the event. If it's an AEN, it |
| 504 | * will be handled in-line or a worker | 505 | * will be handled in-line or a worker |
| @@ -517,15 +518,15 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) | |||
| 517 | MB_CMD_STS_GOOD) || | 518 | MB_CMD_STS_GOOD) || |
| 518 | ((mbcp->mbox_out[0] & 0x0000f000) == | 519 | ((mbcp->mbox_out[0] & 0x0000f000) == |
| 519 | MB_CMD_STS_INTRMDT)) | 520 | MB_CMD_STS_INTRMDT)) |
| 520 | break; | 521 | goto done; |
| 521 | } while (--count); | 522 | } while (time_before(jiffies, count)); |
| 522 | 523 | ||
| 523 | if (!count) { | 524 | QPRINTK(qdev, DRV, ERR, |
| 524 | QPRINTK(qdev, DRV, ERR, | 525 | "Timed out waiting for mailbox complete.\n"); |
| 525 | "Timed out waiting for mailbox complete.\n"); | 526 | status = -ETIMEDOUT; |
| 526 | status = -ETIMEDOUT; | 527 | goto end; |
| 527 | goto end; | 528 | |
| 528 | } | 529 | done: |
| 529 | 530 | ||
| 530 | /* Now we can clear the interrupt condition | 531 | /* Now we can clear the interrupt condition |
| 531 | * and look at our status. | 532 | * and look at our status. |
