Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 5 Jun 2016 06:37:54 +0000 (UTC)
From:      Andrew Rybchenko <arybchik@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r301427 - head/sys/dev/sfxge/common
Message-ID:  <201606050637.u556bsSj052161@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: arybchik
Date: Sun Jun  5 06:37:54 2016
New Revision: 301427
URL: https://svnweb.freebsd.org/changeset/base/301427

Log:
  sfxge(4): allow firmware to auto-configure event queues on Medford
  
  On Medford, licenses are required to enable RX and event cut through and to
  disable RX batching. To avoid the need for the driver to make decisions based on
  the licensing state, the MC_CMD_INIT_EVQ has been extended to allow us to leave
  the decision to the firmware. If the adapter is licensed for low-latency use,
  the firmware will choose the optimal settings for latency, otherwise it will use
  the best settings for throughput.
  
  For Huntington we still need to choose the settings ourselves.
  
  Submitted by:   Mark Spender <mspender at solarflare.com>
  Sponsored by:   Solarflare Communications, Inc.
  MFC after:      1 week
  Differential Revision:  https://reviews.freebsd.org/D6717

Modified:
  head/sys/dev/sfxge/common/ef10_ev.c
  head/sys/dev/sfxge/common/ef10_nic.c
  head/sys/dev/sfxge/common/efx.h

Modified: head/sys/dev/sfxge/common/ef10_ev.c
==============================================================================
--- head/sys/dev/sfxge/common/ef10_ev.c	Sun Jun  5 06:06:55 2016	(r301426)
+++ head/sys/dev/sfxge/common/ef10_ev.c	Sun Jun  5 06:37:54 2016	(r301427)
@@ -139,7 +139,8 @@ efx_mcdi_init_evq(
 	__in		efsys_mem_t *esmp,
 	__in		size_t nevs,
 	__in		uint32_t irq,
-	__in		uint32_t us)
+	__in		uint32_t us,
+	__in		boolean_t low_latency)
 {
 	efx_mcdi_req_t req;
 	uint8_t payload[
@@ -149,7 +150,7 @@ efx_mcdi_init_evq(
 	uint64_t addr;
 	int npages;
 	int i;
-	int supports_rx_batching;
+	int ev_cut_through;
 	efx_rc_t rc;
 
 	npages = EFX_EVQ_NBUFS(nevs);
@@ -170,21 +171,19 @@ efx_mcdi_init_evq(
 	MCDI_IN_SET_DWORD(req, INIT_EVQ_IN_IRQ_NUM, irq);
 
 	/*
-	 * On Huntington RX and TX event batching can only be requested
-	 * together (even if the datapath firmware doesn't actually support RX
-	 * batching).
-	 * Cut through is incompatible with RX batching and so enabling cut
-	 * through disables RX batching (but it does not affect TX batching).
+	 * On Huntington RX and TX event batching can only be requested together
+	 * (even if the datapath firmware doesn't actually support RX
+	 * batching). If event cut through is enabled no RX batching will occur.
 	 *
-	 * So always enable RX and TX event batching, and enable cut through
-	 * if RX event batching isn't supported (i.e. on low latency firmware).
+	 * So always enable RX and TX event batching, and enable event cut
+	 * through if we want low latency operation.
 	 */
-	supports_rx_batching = enp->en_nic_cfg.enc_rx_batching_enabled ? 1 : 0;
+	ev_cut_through = low_latency ? 1 : 0;
 	MCDI_IN_POPULATE_DWORD_6(req, INIT_EVQ_IN_FLAGS,
 	    INIT_EVQ_IN_FLAG_INTERRUPTING, 1,
 	    INIT_EVQ_IN_FLAG_RPTR_DOS, 0,
 	    INIT_EVQ_IN_FLAG_INT_ARMD, 0,
-	    INIT_EVQ_IN_FLAG_CUT_THRU, !supports_rx_batching,
+	    INIT_EVQ_IN_FLAG_CUT_THRU, ev_cut_through,
 	    INIT_EVQ_IN_FLAG_RX_MERGE, 1,
 	    INIT_EVQ_IN_FLAG_TX_MERGE, 1);
 
@@ -250,6 +249,114 @@ fail1:
 	return (rc);
 }
 
+
+static	__checkReturn	efx_rc_t
+efx_mcdi_init_evq_v2(
+	__in		efx_nic_t *enp,
+	__in		unsigned int instance,
+	__in		efsys_mem_t *esmp,
+	__in		size_t nevs,
+	__in		uint32_t irq,
+	__in		uint32_t us)
+{
+	efx_mcdi_req_t req;
+	uint8_t payload[
+		MAX(MC_CMD_INIT_EVQ_V2_IN_LEN(EFX_EVQ_NBUFS(EFX_EVQ_MAXNEVS)),
+		    MC_CMD_INIT_EVQ_V2_OUT_LEN)];
+	efx_qword_t *dma_addr;
+	uint64_t addr;
+	int npages;
+	int i;
+	efx_rc_t rc;
+
+	npages = EFX_EVQ_NBUFS(nevs);
+	if (MC_CMD_INIT_EVQ_V2_IN_LEN(npages) > MC_CMD_INIT_EVQ_V2_IN_LENMAX) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	(void) memset(payload, 0, sizeof (payload));
+	req.emr_cmd = MC_CMD_INIT_EVQ;
+	req.emr_in_buf = payload;
+	req.emr_in_length = MC_CMD_INIT_EVQ_V2_IN_LEN(npages);
+	req.emr_out_buf = payload;
+	req.emr_out_length = MC_CMD_INIT_EVQ_V2_OUT_LEN;
+
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_SIZE, nevs);
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_INSTANCE, instance);
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_IRQ_NUM, irq);
+
+	MCDI_IN_POPULATE_DWORD_4(req, INIT_EVQ_V2_IN_FLAGS,
+	    INIT_EVQ_V2_IN_FLAG_INTERRUPTING, 1,
+	    INIT_EVQ_V2_IN_FLAG_RPTR_DOS, 0,
+	    INIT_EVQ_V2_IN_FLAG_INT_ARMD, 0,
+	    INIT_EVQ_V2_IN_FLAG_TYPE, MC_CMD_INIT_EVQ_V2_IN_FLAG_TYPE_AUTO);
+
+	/* If the value is zero then disable the timer */
+	if (us == 0) {
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_MODE,
+		    MC_CMD_INIT_EVQ_V2_IN_TMR_MODE_DIS);
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_LOAD, 0);
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_RELOAD, 0);
+	} else {
+		unsigned int ticks;
+
+		if ((rc = efx_ev_usecs_to_ticks(enp, us, &ticks)) != 0)
+			goto fail2;
+
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_MODE,
+		    MC_CMD_INIT_EVQ_V2_IN_TMR_INT_HLDOFF);
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_LOAD, ticks);
+		MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_TMR_RELOAD, ticks);
+	}
+
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_COUNT_MODE,
+	    MC_CMD_INIT_EVQ_V2_IN_COUNT_MODE_DIS);
+	MCDI_IN_SET_DWORD(req, INIT_EVQ_V2_IN_COUNT_THRSHLD, 0);
+
+	dma_addr = MCDI_IN2(req, efx_qword_t, INIT_EVQ_V2_IN_DMA_ADDR);
+	addr = EFSYS_MEM_ADDR(esmp);
+
+	for (i = 0; i < npages; i++) {
+		EFX_POPULATE_QWORD_2(*dma_addr,
+		    EFX_DWORD_1, (uint32_t)(addr >> 32),
+		    EFX_DWORD_0, (uint32_t)(addr & 0xffffffff));
+
+		dma_addr++;
+		addr += EFX_BUF_SIZE;
+	}
+
+	efx_mcdi_execute(enp, &req);
+
+	if (req.emr_rc != 0) {
+		rc = req.emr_rc;
+		goto fail3;
+	}
+
+	if (req.emr_out_length_used < MC_CMD_INIT_EVQ_V2_OUT_LEN) {
+		rc = EMSGSIZE;
+		goto fail4;
+	}
+
+	/* NOTE: ignore the returned IRQ param as firmware does not set it. */
+
+	EFSYS_PROBE1(mcdi_evq_flags, uint32_t,
+		    MCDI_OUT_DWORD(req, INIT_EVQ_V2_OUT_FLAGS));
+
+	return (0);
+
+fail4:
+	EFSYS_PROBE(fail4);
+fail3:
+	EFSYS_PROBE(fail3);
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+	return (rc);
+}
+
 static	__checkReturn	efx_rc_t
 efx_mcdi_fini_evq(
 	__in		efx_nic_t *enp,
@@ -348,11 +455,41 @@ ef10_ev_qcreate(
 	 * Interrupts may be raised for events immediately after the queue is
 	 * created. See bug58606.
 	 */
-	if ((rc = efx_mcdi_init_evq(enp, index, esmp, n, irq, us)) != 0)
-		goto fail4;
+
+	if (encp->enc_init_evq_v2_supported) {
+		/*
+		 * On Medford the low latency license is required to enable RX
+		 * and event cut through and to disable RX batching.  We let the
+		 * firmware decide the settings to use. If the adapter has a low
+		 * latency license, it will choose the best settings for low
+		 * latency, otherwise it choose the best settings for
+		 * throughput.
+		 */
+		rc = efx_mcdi_init_evq_v2(enp, index, esmp, n, irq, us);
+		if (rc != 0)
+			goto fail4;
+	} else {
+		/*
+		 * On Huntington we need to specify the settings to use. We
+		 * favour latency if the adapter is running low-latency firmware
+		 * and throughput otherwise, and assume not support RX batching
+		 * implies the adapter is running low-latency firmware.  (This
+		 * is how it's been done since Huntington GA. It doesn't make
+		 * much sense with hindsight as the 'low-latency' firmware
+		 * variant is also best for throughput, and does now support RX
+		 * batching).
+		 */
+		boolean_t low_latency = encp->enc_rx_batching_enabled ? 0 : 1;
+		rc = efx_mcdi_init_evq(enp, index, esmp, n, irq, us,
+				    low_latency);
+		if (rc != 0)
+			goto fail5;
+	}
 
 	return (0);
 
+fail5:
+	EFSYS_PROBE(fail5);
 fail4:
 	EFSYS_PROBE(fail4);
 fail3:

Modified: head/sys/dev/sfxge/common/ef10_nic.c
==============================================================================
--- head/sys/dev/sfxge/common/ef10_nic.c	Sun Jun  5 06:06:55 2016	(r301426)
+++ head/sys/dev/sfxge/common/ef10_nic.c	Sun Jun  5 06:37:54 2016	(r301427)
@@ -1025,6 +1025,13 @@ ef10_get_datapath_caps(
 	encp->enc_enhanced_set_mac_supported =
 		CAP_FLAG(flags, SET_MAC_ENHANCED) ? B_TRUE : B_FALSE;
 
+	/*
+	 * Check if firmware supports version 2 of MC_CMD_INIT_EVQ, which allows
+	 * us to let the firmware choose the settings to use on an EVQ.
+	 */
+	encp->enc_init_evq_v2_supported =
+		CAP_FLAG2(flags2, INIT_EVQ_V2) ? B_TRUE : B_FALSE;
+
 #undef CAP_FLAG
 #undef CAP_FLAG2
 

Modified: head/sys/dev/sfxge/common/efx.h
==============================================================================
--- head/sys/dev/sfxge/common/efx.h	Sun Jun  5 06:06:55 2016	(r301426)
+++ head/sys/dev/sfxge/common/efx.h	Sun Jun  5 06:37:54 2016	(r301427)
@@ -1148,6 +1148,7 @@ typedef struct efx_nic_cfg_s {
 	boolean_t               enc_rx_disable_scatter_supported;
 	boolean_t               enc_allow_set_mac_with_installed_filters;
 	boolean_t		enc_enhanced_set_mac_supported;
+	boolean_t		enc_init_evq_v2_supported;
 	/* External port identifier */
 	uint8_t			enc_external_port;
 	uint32_t		enc_mcdi_max_payload_length;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201606050637.u556bsSj052161>