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

Marcin Wojtas mw at FreeBSD.org
Tue May 26 15:50:31 UTC 2020


Author: mw
Date: Tue May 26 15:50:30 2020
New Revision: 361523
URL: https://svnweb.freebsd.org/changeset/base/361523

Log:
  Rework ENA Tx buffer ring size reconfiguration
  
  This method has been aligned with the way how the Rx queue size is being
  updated - so it's now done synchronously instead of resetting the
  device.
  
  Moreover, the input parameter is now being validated if it's a power of
  2. Without this, it can cause kernel panic.
  
  Submitted by:  Michal Krawczyk <mk 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:48:27 2020	(r361522)
+++ head/sys/dev/ena/ena.c	Tue May 26 15:50:30 2020	(r361523)
@@ -1135,6 +1135,55 @@ ena_refill_rx_bufs(struct ena_ring *rx_ring, uint32_t 
 }
 
 int
+ena_update_buf_ring_size(struct ena_adapter *adapter,
+    uint32_t new_buf_ring_size)
+{
+	uint32_t old_buf_ring_size;
+	int rc = 0;
+	bool dev_was_up;
+
+	ENA_LOCK_LOCK(adapter);
+
+	old_buf_ring_size = adapter->buf_ring_size;
+	adapter->buf_ring_size = new_buf_ring_size;
+
+	dev_was_up = ENA_FLAG_ISSET(ENA_FLAG_DEV_UP, adapter);
+	ena_down(adapter);
+
+	/* Reconfigure buf ring for all Tx rings. */
+	ena_free_all_io_rings_resources(adapter);
+	ena_init_io_rings_advanced(adapter);
+	if (dev_was_up) {
+		/*
+		 * If ena_up() fails, it's not because of recent buf_ring size
+		 * changes. Because of that, we just want to revert old drbr
+		 * value and trigger the reset because something else had to
+		 * go wrong.
+		 */
+		rc = ena_up(adapter);
+		if (unlikely(rc != 0)) {
+			device_printf(adapter->pdev,
+			    "Failed to configure device after setting new drbr size: %u. Reverting old value: %u and triggering the reset\n",
+			    new_buf_ring_size, old_buf_ring_size);
+
+			/* Revert old size and trigger the reset */
+			adapter->buf_ring_size = old_buf_ring_size;
+			ena_free_all_io_rings_resources(adapter);
+			ena_init_io_rings_advanced(adapter);
+
+			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);
+}
+
+int
 ena_update_queue_size(struct ena_adapter *adapter, uint32_t new_tx_size,
     uint32_t new_rx_size)
 {

Modified: head/sys/dev/ena/ena.h
==============================================================================
--- head/sys/dev/ena/ena.h	Tue May 26 15:48:27 2020	(r361522)
+++ head/sys/dev/ena/ena.h	Tue May 26 15:50:30 2020	(r361523)
@@ -426,7 +426,7 @@ struct ena_adapter {
 
 	uint32_t tx_offload_cap;
 
-	uint16_t buf_ring_size;
+	uint32_t buf_ring_size;
 
 	/* RSS*/
 	uint8_t	rss_ind_tbl[ENA_RX_RSS_TABLE_SIZE];
@@ -497,6 +497,8 @@ void	ena_down(struct ena_adapter *adapter);
 int	ena_restore_device(struct ena_adapter *adapter);
 void	ena_destroy_device(struct ena_adapter *adapter, bool graceful);
 int	ena_refill_rx_bufs(struct ena_ring *rx_ring, uint32_t num);
+int	ena_update_buf_ring_size(struct ena_adapter *adapter,
+    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);
 

Modified: head/sys/dev/ena/ena_sysctl.c
==============================================================================
--- head/sys/dev/ena/ena_sysctl.c	Tue May 26 15:48:27 2020	(r361522)
+++ head/sys/dev/ena/ena_sysctl.c	Tue May 26 15:50:30 2020	(r361523)
@@ -307,8 +307,9 @@ ena_sysctl_add_tuneables(struct ena_adapter *adapter)
 
 	/* Tuneable number of buffers in the buf-ring (drbr) */
 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "buf_ring_size",
-	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT, adapter, 0,
-	    ena_sysctl_buf_ring_size, "I", "Size of the bufring");
+	    CTLTYPE_U32 | CTLFLAG_RW | CTLFLAG_MPSAFE, adapter, 0,
+	    ena_sysctl_buf_ring_size, "I",
+	    "Size of the Tx buffer ring (drbr).");
 
 	/* Tuneable number of the Rx ring size */
 	SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rx_queue_size",
@@ -322,31 +323,38 @@ static int
 ena_sysctl_buf_ring_size(SYSCTL_HANDLER_ARGS)
 {
 	struct ena_adapter *adapter = arg1;
-	int val;
+	uint32_t val;
 	int error;
 
 	val = 0;
-	error = sysctl_wire_old_buffer(req, sizeof(int));
+	error = sysctl_wire_old_buffer(req, sizeof(val));
 	if (error == 0) {
 		val = adapter->buf_ring_size;
 		error = sysctl_handle_int(oidp, &val, 0, req);
 	}
 	if (error != 0 || req->newptr == NULL)
 		return (error);
-	if (val < 0)
+
+	if (!powerof2(val) || val == 0) {
+		device_printf(adapter->pdev,
+		    "Requested new Tx buffer ring size (%u) is not a power of 2\n",
+		    val);
 		return (EINVAL);
+	}
 
-	device_printf(adapter->pdev,
-	    "Requested new buf ring size: %d. Old size: %d\n",
-	    val, adapter->buf_ring_size);
-
 	if (val != adapter->buf_ring_size) {
-		adapter->buf_ring_size = val;
-		adapter->reset_reason = ENA_REGS_RESET_OS_TRIGGER;
-		ENA_FLAG_SET_ATOMIC(ENA_FLAG_TRIGGER_RESET, adapter);
+		device_printf(adapter->pdev,
+		    "Requested new Tx buffer ring size: %d. Old size: %d\n",
+		    val, adapter->buf_ring_size);
+
+		error = ena_update_buf_ring_size(adapter, val);
+	} else {
+		device_printf(adapter->pdev,
+		    "New Tx buffer ring size is the same as already used: %u\n",
+		    adapter->buf_ring_size);
 	}
 
-	return (0);
+	return (error);
 }
 
 static int


More information about the svn-src-all mailing list