diff options
author | Netanel Belgazal | 2017-06-23 10:21:51 +0200 |
---|---|---|
committer | David S. Miller | 2017-06-23 20:15:08 +0200 |
commit | 82ef30f13be0b4fea70a9c6215f7cff40bb3be63 (patch) | |
tree | 32dbf61aef621214c0162b326c8e61cb27176ec0 /drivers/net/ethernet/amazon/ena/ena_netdev.c | |
parent | net: ena: change return value for unsupported features unsupported return value (diff) | |
download | kernel-qcow2-linux-82ef30f13be0b4fea70a9c6215f7cff40bb3be63.tar.gz kernel-qcow2-linux-82ef30f13be0b4fea70a9c6215f7cff40bb3be63.tar.xz kernel-qcow2-linux-82ef30f13be0b4fea70a9c6215f7cff40bb3be63.zip |
net: ena: add hardware hints capability to the driver
With this patch, ENA device can update the ena driver about
the desired timeout values:
These values are part of the "hardware hints" which are transmitted
to the driver as Asynchronous event through ENA async
event notification queue.
In case the ENA device does not support this capability,
the driver will use its own default values.
Signed-off-by: Netanel Belgazal <netanel@amazon.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/amazon/ena/ena_netdev.c')
-rw-r--r-- | drivers/net/ethernet/amazon/ena/ena_netdev.c | 66 |
1 files changed, 61 insertions, 5 deletions
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 8d4f65ea985c..1ee06e11654c 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -2577,7 +2577,7 @@ static int check_missing_comp_in_queue(struct ena_adapter *adapter, tx_buf = &tx_ring->tx_buffer_info[i]; last_jiffies = tx_buf->last_jiffies; if (unlikely(last_jiffies && - time_is_before_jiffies(last_jiffies + TX_TIMEOUT))) { + time_is_before_jiffies(last_jiffies + adapter->missing_tx_completion_to))) { if (!tx_buf->print_once) netif_notice(adapter, tx_err, adapter->netdev, "Found a Tx that wasn't completed on time, qid %d, index %d.\n", @@ -2586,10 +2586,11 @@ static int check_missing_comp_in_queue(struct ena_adapter *adapter, tx_buf->print_once = 1; missed_tx++; - if (unlikely(missed_tx > MAX_NUM_OF_TIMEOUTED_PACKETS)) { + if (unlikely(missed_tx > adapter->missing_tx_completion_threshold)) { netif_err(adapter, tx_err, adapter->netdev, "The number of lost tx completions is above the threshold (%d > %d). Reset the device\n", - missed_tx, MAX_NUM_OF_TIMEOUTED_PACKETS); + missed_tx, + adapter->missing_tx_completion_threshold); set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags); return -EIO; } @@ -2613,6 +2614,9 @@ static void check_for_missing_tx_completions(struct ena_adapter *adapter) if (test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags)) return; + if (adapter->missing_tx_completion_to == ENA_HW_HINTS_NO_TIMEOUT) + return; + budget = ENA_MONITORED_TX_QUEUES; for (i = adapter->last_monitored_tx_qid; i < adapter->num_queues; i++) { @@ -2690,8 +2694,11 @@ static void check_for_missing_keep_alive(struct ena_adapter *adapter) if (!adapter->wd_state) return; - keep_alive_expired = round_jiffies(adapter->last_keep_alive_jiffies - + ENA_DEVICE_KALIVE_TIMEOUT); + if (adapter->keep_alive_timeout == ENA_HW_HINTS_NO_TIMEOUT) + return; + + keep_alive_expired = round_jiffies(adapter->last_keep_alive_jiffies + + adapter->keep_alive_timeout); if (unlikely(time_is_before_jiffies(keep_alive_expired))) { netif_err(adapter, drv, adapter->netdev, "Keep alive watchdog timeout.\n"); @@ -2714,6 +2721,44 @@ static void check_for_admin_com_state(struct ena_adapter *adapter) } } +static void ena_update_hints(struct ena_adapter *adapter, + struct ena_admin_ena_hw_hints *hints) +{ + struct net_device *netdev = adapter->netdev; + + if (hints->admin_completion_tx_timeout) + adapter->ena_dev->admin_queue.completion_timeout = + hints->admin_completion_tx_timeout * 1000; + + if (hints->mmio_read_timeout) + /* convert to usec */ + adapter->ena_dev->mmio_read.reg_read_to = + hints->mmio_read_timeout * 1000; + + if (hints->missed_tx_completion_count_threshold_to_reset) + adapter->missing_tx_completion_threshold = + hints->missed_tx_completion_count_threshold_to_reset; + + if (hints->missing_tx_completion_timeout) { + if (hints->missing_tx_completion_timeout == ENA_HW_HINTS_NO_TIMEOUT) + adapter->missing_tx_completion_to = ENA_HW_HINTS_NO_TIMEOUT; + else + adapter->missing_tx_completion_to = + msecs_to_jiffies(hints->missing_tx_completion_timeout); + } + + if (hints->netdev_wd_timeout) + netdev->watchdog_timeo = msecs_to_jiffies(hints->netdev_wd_timeout); + + if (hints->driver_watchdog_timeout) { + if (hints->driver_watchdog_timeout == ENA_HW_HINTS_NO_TIMEOUT) + adapter->keep_alive_timeout = ENA_HW_HINTS_NO_TIMEOUT; + else + adapter->keep_alive_timeout = + msecs_to_jiffies(hints->driver_watchdog_timeout); + } +} + static void ena_update_host_info(struct ena_admin_host_info *host_info, struct net_device *netdev) { @@ -3136,6 +3181,11 @@ static int ena_probe(struct pci_dev *pdev, const struct pci_device_id *ent) INIT_WORK(&adapter->reset_task, ena_fw_reset_device); adapter->last_keep_alive_jiffies = jiffies; + adapter->keep_alive_timeout = ENA_DEVICE_KALIVE_TIMEOUT; + adapter->missing_tx_completion_to = TX_TIMEOUT; + adapter->missing_tx_completion_threshold = MAX_NUM_OF_TIMEOUTED_PACKETS; + + ena_update_hints(adapter, &get_feat_ctx.hw_hints); setup_timer(&adapter->timer_service, ena_timer_service, (unsigned long)adapter); @@ -3337,6 +3387,7 @@ static void ena_notification(void *adapter_data, struct ena_admin_aenq_entry *aenq_e) { struct ena_adapter *adapter = (struct ena_adapter *)adapter_data; + struct ena_admin_ena_hw_hints *hints; WARN(aenq_e->aenq_common_desc.group != ENA_ADMIN_NOTIFICATION, "Invalid group(%x) expected %x\n", @@ -3354,6 +3405,11 @@ static void ena_notification(void *adapter_data, case ENA_ADMIN_RESUME: queue_work(ena_wq, &adapter->resume_io_task); break; + case ENA_ADMIN_UPDATE_HINTS: + hints = (struct ena_admin_ena_hw_hints *) + (&aenq_e->inline_data_w4); + ena_update_hints(adapter, hints); + break; default: netif_err(adapter, drv, adapter->netdev, "Invalid aenq notification link state %d\n", |