diff options
Diffstat (limited to 'drivers/net/sfc/falcon.c')
-rw-r--r-- | drivers/net/sfc/falcon.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index d5378e60fcd..2ae51fd6f9c 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -39,11 +39,16 @@ * @next_buffer_table: First available buffer table id * @pci_dev2: The secondary PCI device if present * @i2c_data: Operations and state for I2C bit-bashing algorithm + * @int_error_count: Number of internal errors seen recently + * @int_error_expire: Time at which error count will be expired */ struct falcon_nic_data { unsigned next_buffer_table; struct pci_dev *pci_dev2; struct i2c_algo_bit_data i2c_data; + + unsigned int_error_count; + unsigned long int_error_expire; }; /************************************************************************** @@ -119,8 +124,12 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold"); #define FALCON_EVQ_SIZE 4096 #define FALCON_EVQ_MASK (FALCON_EVQ_SIZE - 1) -/* Max number of internal errors. After this resets will not be performed */ -#define FALCON_MAX_INT_ERRORS 4 +/* If FALCON_MAX_INT_ERRORS internal errors occur within + * FALCON_INT_ERROR_EXPIRE seconds, we consider the NIC broken and + * disable it. + */ +#define FALCON_INT_ERROR_EXPIRE 3600 +#define FALCON_MAX_INT_ERRORS 5 /* We poll for events every FLUSH_INTERVAL ms, and check FLUSH_POLL_COUNT times */ @@ -1187,31 +1196,29 @@ static void falcon_poll_flush_events(struct efx_nic *efx) struct efx_channel *channel = &efx->channel[0]; struct efx_tx_queue *tx_queue; struct efx_rx_queue *rx_queue; - unsigned int read_ptr, i; + unsigned int read_ptr = channel->eventq_read_ptr; + unsigned int end_ptr = (read_ptr - 1) & FALCON_EVQ_MASK; - read_ptr = channel->eventq_read_ptr; - for (i = 0; i < FALCON_EVQ_SIZE; ++i) { + do { efx_qword_t *event = falcon_event(channel, read_ptr); int ev_code, ev_sub_code, ev_queue; bool ev_failed; + if (!falcon_event_present(event)) break; ev_code = EFX_QWORD_FIELD(*event, EV_CODE); - if (ev_code != DRIVER_EV_DECODE) - continue; - ev_sub_code = EFX_QWORD_FIELD(*event, DRIVER_EV_SUB_CODE); - switch (ev_sub_code) { - case TX_DESCQ_FLS_DONE_EV_DECODE: + if (ev_code == DRIVER_EV_DECODE && + ev_sub_code == TX_DESCQ_FLS_DONE_EV_DECODE) { ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_TX_DESCQ_ID); if (ev_queue < EFX_TX_QUEUE_COUNT) { tx_queue = efx->tx_queue + ev_queue; tx_queue->flushed = true; } - break; - case RX_DESCQ_FLS_DONE_EV_DECODE: + } else if (ev_code == DRIVER_EV_DECODE && + ev_sub_code == RX_DESCQ_FLS_DONE_EV_DECODE) { ev_queue = EFX_QWORD_FIELD(*event, DRIVER_EV_RX_DESCQ_ID); ev_failed = EFX_QWORD_FIELD(*event, @@ -1225,11 +1232,10 @@ static void falcon_poll_flush_events(struct efx_nic *efx) else rx_queue->flushed = true; } - break; } read_ptr = (read_ptr + 1) & FALCON_EVQ_MASK; - } + } while (read_ptr != end_ptr); } /* Handle tx and rx flushes at the same time, since they run in @@ -1377,7 +1383,6 @@ static irqreturn_t falcon_fatal_interrupt(struct efx_nic *efx) efx_oword_t *int_ker = efx->irq_status.addr; efx_oword_t fatal_intr; int error, mem_perr; - static int n_int_errors; falcon_read(efx, &fatal_intr, FATAL_INTR_REG_KER); error = EFX_OWORD_FIELD(fatal_intr, INT_KER_ERROR); @@ -1404,7 +1409,14 @@ static irqreturn_t falcon_fatal_interrupt(struct efx_nic *efx) pci_clear_master(nic_data->pci_dev2); falcon_disable_interrupts(efx); - if (++n_int_errors < FALCON_MAX_INT_ERRORS) { + /* Count errors and reset or disable the NIC accordingly */ + if (nic_data->int_error_count == 0 || + time_after(jiffies, nic_data->int_error_expire)) { + nic_data->int_error_count = 0; + nic_data->int_error_expire = + jiffies + FALCON_INT_ERROR_EXPIRE * HZ; + } + if (++nic_data->int_error_count < FALCON_MAX_INT_ERRORS) { EFX_ERR(efx, "SYSTEM ERROR - reset scheduled\n"); efx_schedule_reset(efx, RESET_TYPE_INT_ERROR); } else { @@ -2249,6 +2261,7 @@ static int falcon_probe_phy(struct efx_nic *efx) efx->phy_op = &falcon_sft9001_phy_ops; break; case PHY_TYPE_QT2022C2: + case PHY_TYPE_QT2025C: efx->phy_op = &falcon_xfp_phy_ops; break; default: @@ -3113,8 +3126,10 @@ void falcon_remove_nic(struct efx_nic *efx) struct falcon_nic_data *nic_data = efx->nic_data; int rc; + /* Remove I2C adapter and clear it in preparation for a retry */ rc = i2c_del_adapter(&efx->i2c_adap); BUG_ON(rc); + memset(&efx->i2c_adap, 0, sizeof(efx->i2c_adap)); falcon_remove_spi_devices(efx); falcon_free_buffer(efx, &efx->irq_status); |