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

Zbigniew Bodek zbb at FreeBSD.org
Tue May 30 11:58:53 UTC 2017


Author: zbb
Date: Tue May 30 11:58:51 2017
New Revision: 319200
URL: https://svnweb.freebsd.org/changeset/base/319200

Log:
  Move ENA's hw stats updating routine to separate task
  
  Initially, stats were being updated each time OS was requesting for
  the first statistic.
  To read statistics from hw, condvar was used. cv_timedwait cannot be
  called when unsleepable lock is held, and this happens when FreeBSD
  is requesting statistic.
  Seperate task is reading statistics from NIC each 1 second.
  
  Submitted by:   Michal Krawczyk <mk at semihalf.com>
  Obtained from:  Semihalf
  Sponsored by:   Amazon.com Inc.
  Differential revision: https://reviews.freebsd.org/D10926

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

Modified: head/sys/dev/ena/ena.c
==============================================================================
--- head/sys/dev/ena/ena.c	Tue May 30 11:56:54 2017	(r319199)
+++ head/sys/dev/ena/ena.c	Tue May 30 11:58:51 2017	(r319200)
@@ -141,6 +141,7 @@ static void	ena_free_irqs(struct ena_adapter*);
 static void	ena_disable_msix(struct ena_adapter *);
 static void	ena_unmask_all_io_irqs(struct ena_adapter *);
 static int	ena_rss_configure(struct ena_adapter *);
+static void	ena_update_hw_stats(void *, int);
 static int	ena_up_complete(struct ena_adapter *);
 static int	ena_up(struct ena_adapter *);
 static void	ena_down(struct ena_adapter *);
@@ -2058,6 +2059,25 @@ static int ena_rss_configure(struct ena_adapter *adapt
 	return 0;
 }
 
+static void
+ena_update_hw_stats(void *arg, int pending)
+{
+	struct ena_adapter *adapter = arg;
+	int rc;
+
+	for (;;) {
+		if (!adapter->up)
+			return;
+
+		rc = ena_update_stats_counters(adapter);
+		if (rc)
+			ena_trace(ENA_WARNING,
+			    "Error updating stats counters, rc = %d", rc);
+
+		pause("ena update hw stats", hz);
+	}
+}
+
 static int
 ena_up_complete(struct ena_adapter *adapter)
 {
@@ -2141,6 +2161,8 @@ ena_up(struct ena_adapter *adapter)
 		callout_reset_sbt(&adapter->timer_service, SBT_1S, SBT_1S,
 		    ena_timer_service, (void *)adapter, 0);
 
+		taskqueue_enqueue(adapter->stats_tq, &adapter->stats_task);
+
 		adapter->up = true;
 	}
 
@@ -2193,24 +2215,8 @@ ena_get_counter(if_t ifp, ift_counter cnt)
 {
 	struct ena_adapter *adapter;
 	struct ena_hw_stats *stats;
-	int rc;
 
 	adapter = if_getsoftc(ifp);
-
-	/*
-	 * Update only when asking for first counter and interface is up.
-	 * Usually asks for all statistics in sequence.
-	 */
-	if (adapter->up) {
-		if (cnt == 0) {
-			rc = ena_update_stats_counters(adapter);
-			if (rc) {
-				ena_trace(ENA_WARNING,
-				    "Error updating stats counters, rc = %d",
-				    rc);
-			}
-		}
-	}
 	stats = &adapter->hw_stats;
 
 	switch (cnt) {
@@ -2501,6 +2507,10 @@ ena_down(struct ena_adapter *adapter)
 		if_setdrvflagbits(adapter->ifp, IFF_DRV_OACTIVE,
 		    IFF_DRV_RUNNING);
 
+		/* Drain task responsible for updating hw stats */
+		while (taskqueue_cancel(adapter->stats_tq, &adapter->stats_task, NULL))
+			taskqueue_drain(adapter->stats_tq, &adapter->stats_task);
+
 		ena_free_io_irq(adapter);
 
 		ena_destroy_all_io_queues(adapter);
@@ -3616,6 +3626,18 @@ ena_attach(device_t pdev)
 	taskqueue_start_threads(&adapter->reset_tq, 1, PI_NET,
 	    "%s rstq", device_get_nameunit(adapter->pdev));
 
+	/* Initialize task queue responsible for updating hw stats */
+	TASK_INIT(&adapter->stats_task, 0, ena_update_hw_stats, adapter);
+	adapter->stats_tq = taskqueue_create_fast("ena_stats_update",
+	    M_WAITOK | M_ZERO, taskqueue_thread_enqueue, &adapter->stats_tq);
+	if (adapter->stats_tq == NULL) {
+		device_printf(adapter->pdev,
+		    "Unable to create taskqueue for updating hw stats\n");
+		goto err_stats_tq;
+	}
+	taskqueue_start_threads(&adapter->stats_tq, 1, PI_REALTIME,
+	    "%s stats tq", device_get_nameunit(adapter->pdev));
+
 	/* Initialize statistics */
 	ena_alloc_counters((counter_u64_t *)&adapter->dev_stats,
 	    sizeof(struct ena_stats_dev));
@@ -3628,6 +3650,8 @@ ena_attach(device_t pdev)
 	adapter->running = true;
 	return (0);
 
+err_stats_tq:
+	taskqueue_free(adapter->reset_tq);
 err_reset_tq:
 	ena_free_mgmnt_irq(adapter);
 	ena_disable_msix(adapter);
@@ -3682,6 +3706,8 @@ ena_detach(device_t pdev)
 	sx_xlock(&adapter->ioctl_sx);
 	ena_down(adapter);
 	sx_unlock(&adapter->ioctl_sx);
+
+	taskqueue_free(adapter->stats_tq);
 
 	if (adapter->ifp != NULL) {
 		ether_ifdetach(adapter->ifp);

Modified: head/sys/dev/ena/ena.h
==============================================================================
--- head/sys/dev/ena/ena.h	Tue May 30 11:56:54 2017	(r319199)
+++ head/sys/dev/ena/ena.h	Tue May 30 11:58:51 2017	(r319200)
@@ -403,6 +403,10 @@ struct ena_adapter {
 	uint32_t missing_tx_max_queues;
 	uint32_t missing_tx_threshold;
 
+	/* Task updating hw stats */
+	struct task stats_task;
+	struct taskqueue *stats_tq;
+
 	/* Statistics */
 	struct ena_stats_dev dev_stats;
 	struct ena_hw_stats hw_stats;


More information about the svn-src-head mailing list