From d2d2c3731474614bff5cf47a605e59e847882f5d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 27 Feb 2009 13:07:33 +0000 Subject: sfc: Add support for QT2025C PHY This is a new PHY supporting SFP+ modules, used in the SFN4112F reference design. It is similar to the QT2022C2 and shares much of its support code. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/falcon.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/sfc/falcon.c') diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index d5378e60fcd..9e2f0f0d47a 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -2249,6 +2249,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: -- cgit v1.2.3-70-g09d2 From 8c870379d2db81a11ede65e9fd9774e4e6efe84a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 4 Mar 2009 09:53:02 +0000 Subject: sfc: Clear I2C adapter structure in falcon_remove_nic() i2c_del_adapter() leaves dangling pointers in the structure. If we retry the NIC probe and pass the structure to i2c_add_adapter() again it will lead to an oops unless we clear it first. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/falcon.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/net/sfc/falcon.c') diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 9e2f0f0d47a..efd121c42a2 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -3114,8 +3114,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); -- cgit v1.2.3-70-g09d2 From 4720bc6cfe70b606cf62a244c7a5391e59923e45 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 4 Mar 2009 10:01:15 +0000 Subject: sfc: Fix search for flush completion events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When flushing queues we disable normal interrupt and event handling and poll event queue 0 looking for flush completions. Unfortunately the flush event polling loop fails to move past any other type of event. This problem has not been observed in production hardware but appears to be a possibility. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/falcon.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'drivers/net/sfc/falcon.c') diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index efd121c42a2..82c10f4de1b 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1187,31 +1187,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 +1223,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 -- cgit v1.2.3-70-g09d2 From 2c3c3d02f28801d7ad2da4952b2c7ca6621ef221 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 4 Mar 2009 10:01:57 +0000 Subject: sfc: Improve NIC internal error recovery Make the error count a per-NIC variable. Reset this the count after an hour if it has not reached the critical value. Set the critical value back to 5. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/falcon.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'drivers/net/sfc/falcon.c') diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 82c10f4de1b..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 */ @@ -1374,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); @@ -1401,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 { -- cgit v1.2.3-70-g09d2 From a9de9a74c69f75e9456cd6b45ecab44ff4c81d04 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 20 Mar 2009 13:26:41 +0000 Subject: sfc: Work around unreliable legacy interrupt status In rare cases, reading the legacy interrupt status register can acknowledge an event queue whose attention flag has not yet been set in the register. Until we service this event queue it will not generate any more interrupts. Therefore, as a secondary check, poll the next slot in each active event queue whose flag is not set. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/falcon.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'drivers/net/sfc/falcon.c') diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 2ae51fd6f9c..92ea6147b3f 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1435,6 +1435,7 @@ static irqreturn_t falcon_legacy_interrupt_b0(int irq, void *dev_id) { struct efx_nic *efx = dev_id; efx_oword_t *int_ker = efx->irq_status.addr; + irqreturn_t result = IRQ_NONE; struct efx_channel *channel; efx_dword_t reg; u32 queues; @@ -1449,23 +1450,24 @@ static irqreturn_t falcon_legacy_interrupt_b0(int irq, void *dev_id) if (unlikely(syserr)) return falcon_fatal_interrupt(efx); - if (queues == 0) - return IRQ_NONE; - - efx->last_irq_cpu = raw_smp_processor_id(); - EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n", - irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg)); - /* Schedule processing of any interrupting queues */ - channel = &efx->channel[0]; - while (queues) { - if (queues & 0x01) + efx_for_each_channel(channel, efx) { + if ((queues & 1) || + falcon_event_present( + falcon_event(channel, channel->eventq_read_ptr))) { efx_schedule_channel(channel); - channel++; + result = IRQ_HANDLED; + } queues >>= 1; } - return IRQ_HANDLED; + if (result == IRQ_HANDLED) { + efx->last_irq_cpu = raw_smp_processor_id(); + EFX_TRACE(efx, "IRQ %d on CPU %d status " EFX_DWORD_FMT "\n", + irq, raw_smp_processor_id(), EFX_DWORD_VAL(reg)); + } + + return result; } -- cgit v1.2.3-70-g09d2 From 28c4605826ab24d04102231fc1f3e8577bec376d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 20 Mar 2009 13:26:55 +0000 Subject: sfc: Remove unused private PCI register definitions Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/falcon.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers/net/sfc/falcon.c') diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 92ea6147b3f..f42fc60d1df 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -155,13 +155,6 @@ MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold"); /* Dummy SRAM size code */ #define SRM_NB_BSZ_ONCHIP_ONLY (-1) -/* Be nice if these (or equiv.) were in linux/pci_regs.h, but they're not. */ -#define PCI_EXP_DEVCAP_PWR_VAL_LBN 18 -#define PCI_EXP_DEVCAP_PWR_SCL_LBN 26 -#define PCI_EXP_DEVCTL_PAYLOAD_LBN 5 -#define PCI_EXP_LNKSTA_LNK_WID 0x3f0 -#define PCI_EXP_LNKSTA_LNK_WID_LBN 4 - #define FALCON_IS_DUAL_FUNC(efx) \ (falcon_rev(efx) < FALCON_REV_B0) -- cgit v1.2.3-70-g09d2 From 6fb70fd1b57707a5c7b9fb167b7790b2cba13f04 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Fri, 20 Mar 2009 13:30:37 +0000 Subject: sfc: Implement adaptive IRQ moderation Calculate a score for each 1000 IRQs: - TX completions are worth 1 point - RX completions are worth 4 if merged using LRO or 2 otherwise Reduce moderation if the score is less than 10000, down to a minimum of 5 us. Increase moderation if the score is more than 20000, up to the specified maximum. Signed-off-by: Ben Hutchings Signed-off-by: David S. Miller --- drivers/net/sfc/efx.c | 46 ++++++++++++++++++++++++++++++++++++++++++-- drivers/net/sfc/efx.h | 2 +- drivers/net/sfc/ethtool.c | 19 ++++++------------ drivers/net/sfc/falcon.c | 16 ++++++++++----- drivers/net/sfc/falcon.h | 2 ++ drivers/net/sfc/net_driver.h | 9 +++++++++ 6 files changed, 73 insertions(+), 21 deletions(-) (limited to 'drivers/net/sfc/falcon.c') diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 8fa68d82c02..6eff9ca6c6c 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -133,6 +133,16 @@ static int phy_flash_cfg; module_param(phy_flash_cfg, int, 0644); MODULE_PARM_DESC(phy_flash_cfg, "Set PHYs into reflash mode initially"); +static unsigned irq_adapt_low_thresh = 10000; +module_param(irq_adapt_low_thresh, uint, 0644); +MODULE_PARM_DESC(irq_adapt_low_thresh, + "Threshold score for reducing IRQ moderation"); + +static unsigned irq_adapt_high_thresh = 20000; +module_param(irq_adapt_high_thresh, uint, 0644); +MODULE_PARM_DESC(irq_adapt_high_thresh, + "Threshold score for increasing IRQ moderation"); + /************************************************************************** * * Utility functions and prototypes @@ -223,6 +233,35 @@ static int efx_poll(struct napi_struct *napi, int budget) rx_packets = efx_process_channel(channel, budget); if (rx_packets < budget) { + struct efx_nic *efx = channel->efx; + + if (channel->used_flags & EFX_USED_BY_RX && + efx->irq_rx_adaptive && + unlikely(++channel->irq_count == 1000)) { + unsigned old_irq_moderation = channel->irq_moderation; + + if (unlikely(channel->irq_mod_score < + irq_adapt_low_thresh)) { + channel->irq_moderation = + max_t(int, + channel->irq_moderation - + FALCON_IRQ_MOD_RESOLUTION, + FALCON_IRQ_MOD_RESOLUTION); + } else if (unlikely(channel->irq_mod_score > + irq_adapt_high_thresh)) { + channel->irq_moderation = + min(channel->irq_moderation + + FALCON_IRQ_MOD_RESOLUTION, + efx->irq_rx_moderation); + } + + if (channel->irq_moderation != old_irq_moderation) + falcon_set_int_moderation(channel); + + channel->irq_count = 0; + channel->irq_mod_score = 0; + } + /* There is no race here; although napi_disable() will * only wait for napi_complete(), this isn't a problem * since efx_channel_processed() will have no effect if @@ -991,7 +1030,7 @@ static int efx_probe_nic(struct efx_nic *efx) efx_set_channels(efx); /* Initialise the interrupt moderation settings */ - efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec); + efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true); return 0; } @@ -1188,7 +1227,8 @@ void efx_flush_queues(struct efx_nic *efx) **************************************************************************/ /* Set interrupt moderation parameters */ -void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs) +void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs, + bool rx_adaptive) { struct efx_tx_queue *tx_queue; struct efx_rx_queue *rx_queue; @@ -1198,6 +1238,8 @@ void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, int rx_usecs) efx_for_each_tx_queue(tx_queue, efx) tx_queue->channel->irq_moderation = tx_usecs; + efx->irq_rx_adaptive = rx_adaptive; + efx->irq_rx_moderation = rx_usecs; efx_for_each_rx_queue(rx_queue, efx) rx_queue->channel->irq_moderation = rx_usecs; } diff --git a/drivers/net/sfc/efx.h b/drivers/net/sfc/efx.h index 8bde1d2a21d..da157aa74b8 100644 --- a/drivers/net/sfc/efx.h +++ b/drivers/net/sfc/efx.h @@ -52,7 +52,7 @@ extern void efx_schedule_reset(struct efx_nic *efx, enum reset_type type); extern void efx_suspend(struct efx_nic *efx); extern void efx_resume(struct efx_nic *efx); extern void efx_init_irq_moderation(struct efx_nic *efx, int tx_usecs, - int rx_usecs); + int rx_usecs, bool rx_adaptive); extern int efx_request_power(struct efx_nic *efx, int mw, const char *name); extern void efx_hex_dump(const u8 *, unsigned int, const char *); diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index 589d1329296..64309f4e8b1 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -604,7 +604,6 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev, { struct efx_nic *efx = netdev_priv(net_dev); struct efx_tx_queue *tx_queue; - struct efx_rx_queue *rx_queue; struct efx_channel *channel; memset(coalesce, 0, sizeof(*coalesce)); @@ -622,14 +621,8 @@ static int efx_ethtool_get_coalesce(struct net_device *net_dev, } } - /* Find lowest IRQ moderation across all used RX queues */ - coalesce->rx_coalesce_usecs_irq = ~((u32) 0); - efx_for_each_rx_queue(rx_queue, efx) { - channel = rx_queue->channel; - if (channel->irq_moderation < coalesce->rx_coalesce_usecs_irq) - coalesce->rx_coalesce_usecs_irq = - channel->irq_moderation; - } + coalesce->use_adaptive_rx_coalesce = efx->irq_rx_adaptive; + coalesce->rx_coalesce_usecs_irq = efx->irq_rx_moderation; return 0; } @@ -643,10 +636,9 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev, struct efx_nic *efx = netdev_priv(net_dev); struct efx_channel *channel; struct efx_tx_queue *tx_queue; - unsigned tx_usecs, rx_usecs; + unsigned tx_usecs, rx_usecs, adaptive; - if (coalesce->use_adaptive_rx_coalesce || - coalesce->use_adaptive_tx_coalesce) + if (coalesce->use_adaptive_tx_coalesce) return -EOPNOTSUPP; if (coalesce->rx_coalesce_usecs || coalesce->tx_coalesce_usecs) { @@ -657,6 +649,7 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev, rx_usecs = coalesce->rx_coalesce_usecs_irq; tx_usecs = coalesce->tx_coalesce_usecs_irq; + adaptive = coalesce->use_adaptive_rx_coalesce; /* If the channel is shared only allow RX parameters to be set */ efx_for_each_tx_queue(tx_queue, efx) { @@ -668,7 +661,7 @@ static int efx_ethtool_set_coalesce(struct net_device *net_dev, } } - efx_init_irq_moderation(efx, tx_usecs, rx_usecs); + efx_init_irq_moderation(efx, tx_usecs, rx_usecs, adaptive); /* Reset channel to pick up new moderation value. Note that * this may change the value of the irq_moderation field diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index f42fc60d1df..23a1b148d5b 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -729,6 +729,9 @@ static void falcon_handle_tx_event(struct efx_channel *channel, tx_ev_desc_ptr = EFX_QWORD_FIELD(*event, TX_EV_DESC_PTR); tx_ev_q_label = EFX_QWORD_FIELD(*event, TX_EV_Q_LABEL); tx_queue = &efx->tx_queue[tx_ev_q_label]; + channel->irq_mod_score += + (tx_ev_desc_ptr - tx_queue->read_count) & + efx->type->txd_ring_mask; efx_xmit_done(tx_queue, tx_ev_desc_ptr); } else if (EFX_QWORD_FIELD(*event, TX_EV_WQ_FF_FULL)) { /* Rewrite the FIFO write pointer */ @@ -898,6 +901,8 @@ static void falcon_handle_rx_event(struct efx_channel *channel, discard = true; } + channel->irq_mod_score += 2; + /* Handle received packet */ efx_rx_packet(rx_queue, rx_ev_desc_ptr, rx_ev_byte_cnt, checksummed, discard); @@ -1075,14 +1080,15 @@ void falcon_set_int_moderation(struct efx_channel *channel) * program is based at 0. So actual interrupt moderation * achieved is ((x + 1) * res). */ - unsigned int res = 5; - channel->irq_moderation -= (channel->irq_moderation % res); - if (channel->irq_moderation < res) - channel->irq_moderation = res; + channel->irq_moderation -= (channel->irq_moderation % + FALCON_IRQ_MOD_RESOLUTION); + if (channel->irq_moderation < FALCON_IRQ_MOD_RESOLUTION) + channel->irq_moderation = FALCON_IRQ_MOD_RESOLUTION; EFX_POPULATE_DWORD_2(timer_cmd, TIMER_MODE, TIMER_MODE_INT_HLDOFF, TIMER_VAL, - (channel->irq_moderation / res) - 1); + channel->irq_moderation / + FALCON_IRQ_MOD_RESOLUTION - 1); } else { EFX_POPULATE_DWORD_2(timer_cmd, TIMER_MODE, TIMER_MODE_DIS, diff --git a/drivers/net/sfc/falcon.h b/drivers/net/sfc/falcon.h index 7869c3d7438..77f2e0db7ca 100644 --- a/drivers/net/sfc/falcon.h +++ b/drivers/net/sfc/falcon.h @@ -85,6 +85,8 @@ extern void falcon_set_int_moderation(struct efx_channel *channel); extern void falcon_disable_interrupts(struct efx_nic *efx); extern void falcon_fini_interrupt(struct efx_nic *efx); +#define FALCON_IRQ_MOD_RESOLUTION 5 + /* Global Resources */ extern int falcon_probe_nic(struct efx_nic *efx); extern int falcon_probe_resources(struct efx_nic *efx); diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index b81fc727dff..e169e5dcd1e 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -336,6 +336,8 @@ enum efx_rx_alloc_method { * @eventq_read_ptr: Event queue read pointer * @last_eventq_read_ptr: Last event queue read pointer value. * @eventq_magic: Event queue magic value for driver-generated test events + * @irq_count: Number of IRQs since last adaptive moderation decision + * @irq_mod_score: IRQ moderation score * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors * and diagnostic counters * @rx_alloc_push_pages: RX allocation method currently in use for pushing @@ -364,6 +366,9 @@ struct efx_channel { unsigned int last_eventq_read_ptr; unsigned int eventq_magic; + unsigned int irq_count; + unsigned int irq_mod_score; + int rx_alloc_level; int rx_alloc_push_pages; @@ -703,6 +708,8 @@ union efx_multicast_hash { * @membase: Memory BAR value * @biu_lock: BIU (bus interface unit) lock * @interrupt_mode: Interrupt mode + * @irq_rx_adaptive: Adaptive IRQ moderation enabled for RX event queues + * @irq_rx_moderation: IRQ moderation time for RX event queues * @i2c_adap: I2C adapter * @board_info: Board-level information * @state: Device state flag. Serialised by the rtnl_lock. @@ -784,6 +791,8 @@ struct efx_nic { void __iomem *membase; spinlock_t biu_lock; enum efx_int_mode interrupt_mode; + bool irq_rx_adaptive; + unsigned int irq_rx_moderation; struct i2c_adapter i2c_adap; struct efx_board board_info; -- cgit v1.2.3-70-g09d2