svn commit: r361525 - head/sys/dev/ena

Marcin Wojtas mw at FreeBSD.org
Tue May 26 15:57:04 UTC 2020


Author: mw
Date: Tue May 26 15:57:02 2020
New Revision: 361525
URL: https://svnweb.freebsd.org/changeset/base/361525

Log:
  Add sysctl node for ENA IO queues number adjustment
  
  By default, in ena_attach() the driver attempts to acquire
  ena_adapter::max_num_io_queues MSI-X vectors for the purpose of IO
  queues, however this is not guaranteed. The number of vectors acquired
  depends also on system resources availability.
  
  Regardless of that, enable the number of effectively used IO queues to
  be further limited through the sysctl node.
  
  Example: Assumming that there are 8 IO queues configured by default, the
  command
  
  $ sysctl dev.ena.0.io_queues_nb=4
  
  will reduce the number of available IO queues to 4. Similarly, the value
  can be also increased up to maximum supported value. A value higher than
  maximum supported number of IO queues is ignored. Zero is ignored too.
  
  Submitted by:  Maciej Bielski <mba at semihalf.com>
  Obtained from: Semihalf
  Sponsored by:  Amazon, Inc.

Modified:
  head/sys/dev/ena/ena.c
  head/sys/dev/ena/ena.h
  head/sys/dev/ena/ena_sysctl.c

Modified: head/sys/dev/ena/ena.c
==============================================================================
--- head/sys/dev/ena/ena.c	Tue May 26 15:54:32 2020	(r361524)
+++ head/sys/dev/ena/ena.c	Tue May 26 15:57:02 2020	(r361525)
@@ -1239,6 +1239,61 @@ ena_update_queue_size(struct ena_adapter *adapter, uin
 }
 
 static void
+ena_update_io_rings(struct ena_adapter *adapter, uint32_t num)
+{
+	ena_free_all_io_rings_resources(adapter);
+	/* Force indirection table to be reinitialized */
+	ena_com_rss_destroy(adapter->ena_dev);
+
+	adapter->num_io_queues = num;
+	ena_init_io_rings(adapter);
+}
+
+/* Caller should sanitize new_num */
+int
+ena_update_io_queue_nb(struct ena_adapter *adapter, uint32_t new_num)
+{
+	uint32_t old_num;
+	int rc = 0;
+	bool dev_was_up;
+
+	ENA_LOCK_LOCK(adapter);
+
+	dev_was_up = ENA_FLAG_ISSET(ENA_FLAG_DEV_UP, adapter);
+	old_num = adapter->num_io_queues;
+	ena_down(adapter);
+
+	ena_update_io_rings(adapter, new_num);
+
+	if (dev_was_up) {
+		rc = ena_up(adapter);
+		if (unlikely(rc != 0)) {
+			device_printf(adapter->pdev,
+			    "Failed to configure device with %u IO queues. "
+			    "Reverting to previous value: %u\n",
+			    new_num, old_num);
+
+			ena_update_io_rings(adapter, old_num);
+
+			rc = ena_up(adapter);
+			if (unlikely(rc != 0)) {
+				device_printf(adapter->pdev,
+				    "Failed to revert to previous setup IO "
+				    "queues. Triggering device reset.\n");
+				ENA_FLAG_SET_ATOMIC(
+				    ENA_FLAG_DEV_UP_BEFORE_RESET, adapter);
+				ena_trigger_reset(adapter,
+				    ENA_REGS_RESET_OS_TRIGGER);
+			}
+		}
+	}
+
+	ENA_LOCK_UNLOCK(adapter);
+
+	return (rc);
+}
+
+static void
 ena_free_rx_bufs(struct ena_adapter *adapter, unsigned int qid)
 {
 	struct ena_ring *rx_ring = &adapter->rx_ring[qid];
@@ -1865,6 +1920,18 @@ ena_rss_configure(struct ena_adapter *adapter)
 	struct ena_com_dev *ena_dev = adapter->ena_dev;
 	int rc;
 
+	/* In case the RSS table was destroyed */
+	if (!ena_dev->rss.tbl_log_size) {
+		rc = ena_rss_init_default(adapter);
+		if (unlikely((rc != 0) && (rc != EOPNOTSUPP))) {
+			device_printf(adapter->pdev,
+			    "WARNING: RSS was not properly re-initialized,"
+			    " it will affect bandwidth\n");
+			ENA_FLAG_CLEAR_ATOMIC(ENA_FLAG_RSS_ACTIVE, adapter);
+			return (rc);
+		}
+	}
+
 	/* Set indirect table */
 	rc = ena_com_indirect_table_set(ena_dev);
 	if (unlikely((rc != 0) && (rc != EOPNOTSUPP)))
@@ -1890,8 +1957,11 @@ ena_up_complete(struct ena_adapter *adapter)
 
 	if (likely(ENA_FLAG_ISSET(ENA_FLAG_RSS_ACTIVE, adapter))) {
 		rc = ena_rss_configure(adapter);
-		if (rc != 0)
+		if (rc != 0) {
+			device_printf(adapter->pdev,
+			    "Failed to configure RSS\n");
 			return (rc);
+		}
 	}
 
 	rc = ena_change_mtu(adapter->ifp, adapter->ifp->if_mtu);

Modified: head/sys/dev/ena/ena.h
==============================================================================
--- head/sys/dev/ena/ena.h	Tue May 26 15:54:32 2020	(r361524)
+++ head/sys/dev/ena/ena.h	Tue May 26 15:57:02 2020	(r361525)
@@ -501,6 +501,7 @@ int	ena_update_buf_ring_size(struct ena_adapter *adapt
     uint32_t new_buf_ring_size);
 int	ena_update_queue_size(struct ena_adapter *adapter, uint32_t new_tx_size,
     uint32_t new_rx_size);
+int	ena_update_io_queue_nb(struct ena_adapter *adapter, uint32_t new_num);
 
 static inline void
 ena_trigger_reset(struct ena_adapter *adapter,

Modified: head/sys/dev/ena/ena_sysctl.c
==============================================================================
--- head/sys/dev/ena/ena_sysctl.c	Tue May 26 15:54:32 2020	(r361524)
+++ head/sys/dev/ena/ena_sysctl.c	Tue May 26 15:57:02 2020	(r361525)
@@ -37,6 +37,7 @@ static void	ena_sysctl_add_stats(struct ena_adapter *)
 static void	ena_sysctl_add_tuneables(struct ena_adapter *);
 static int	ena_sysctl_buf_ring_size(SYSCTL_HANDLER_ARGS);
 static int	ena_sysctl_rx_queue_size(SYSCTL_HANDLER_ARGS);
+static int	ena_sysctl_io_queues_nb(SYSCTL_HANDLER_ARGS);
 
 static SYSCTL_NODE(_hw, OID_AUTO, ena, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
     "ENA driver parameters");
@@ -316,6 +317,11 @@ ena_sysctl_add_tuneables(struct ena_adapter *adapter)
 	    CTLTYPE_U32 | CTLFLAG_RW | CTLFLAG_MPSAFE, adapter, 0,
 	    ena_sysctl_rx_queue_size, "I",
 	    "Size of the Rx ring. The size should be a power of 2.");
+
+	/* Tuneable number of IO queues */
+	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "io_queues_nb",
+	    CTLTYPE_U32 | CTLFLAG_RW | CTLFLAG_MPSAFE, adapter, 0,
+	    ena_sysctl_io_queues_nb, "I", "Number of IO queues.");
 }
 
 
@@ -399,6 +405,58 @@ ena_sysctl_rx_queue_size(SYSCTL_HANDLER_ARGS)
 		device_printf(adapter->pdev,
 		    "New Rx queue size is the same as already used: %u\n",
 		    adapter->rx_ring_size);
+	}
+
+	return (error);
+}
+
+/*
+ * Change number of effectively used IO queues adapter->num_io_queues
+ */
+static int
+ena_sysctl_io_queues_nb(SYSCTL_HANDLER_ARGS)
+{
+	struct ena_adapter *adapter = arg1;
+	uint32_t tmp = 0;
+	int error;
+
+	error = sysctl_wire_old_buffer(req, sizeof(tmp));
+	if (error == 0) {
+		tmp = adapter->num_io_queues;
+		error = sysctl_handle_int(oidp, &tmp, 0, req);
+	}
+	if (error != 0 || req->newptr == NULL)
+		return (error);
+
+	if (tmp == 0) {
+		device_printf(adapter->pdev,
+		    "Requested number of IO queues is zero\n");
+		return (EINVAL);
+	}
+
+	/*
+	 * The adapter::max_num_io_queues is the HW capability. The system
+	 * resources availability may potentially be a tighter limit. Therefore
+	 * the relation `adapter::max_num_io_queues >= adapter::msix_vecs`
+	 * always holds true, while the `adapter::msix_vecs` is variable across
+	 * device reset (`ena_destroy_device()` + `ena_restore_device()`).
+	 */
+	if (tmp > (adapter->msix_vecs - ENA_ADMIN_MSIX_VEC)) {
+		device_printf(adapter->pdev,
+		    "Requested number of IO queues is higher than maximum "
+		    "allowed (%u)\n", adapter->msix_vecs - ENA_ADMIN_MSIX_VEC);
+		return (EINVAL);
+	}
+	if (tmp == adapter->num_io_queues) {
+		device_printf(adapter->pdev,
+		    "Requested number of IO queues is equal to current value "
+		    "(%u)\n", adapter->num_io_queues);
+	} else {
+		device_printf(adapter->pdev,
+		    "Requested new number of IO queues: %u, current value: "
+		    "%u\n", tmp, adapter->num_io_queues);
+
+		error = ena_update_io_queue_nb(adapter, tmp);
 	}
 
 	return (error);


More information about the svn-src-all mailing list