Page MenuHomeFreeBSD

D6717.diff
No OneTemporary

D6717.diff

Index: head/sys/dev/sfxge/common/ef10_ev.c
===================================================================
--- head/sys/dev/sfxge/common/ef10_ev.c
+++ head/sys/dev/sfxge/common/ef10_ev.c
@@ -139,7 +139,8 @@
__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 @@
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 @@
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 @@
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 @@
* 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:
Index: head/sys/dev/sfxge/common/ef10_nic.c
===================================================================
--- head/sys/dev/sfxge/common/ef10_nic.c
+++ head/sys/dev/sfxge/common/ef10_nic.c
@@ -1025,6 +1025,13 @@
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
Index: head/sys/dev/sfxge/common/efx.h
===================================================================
--- head/sys/dev/sfxge/common/efx.h
+++ head/sys/dev/sfxge/common/efx.h
@@ -1148,6 +1148,7 @@
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;

File Metadata

Mime Type
text/plain
Expires
Sat, Dec 21, 6:28 PM (20 h, 14 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15544851
Default Alt Text
D6717.diff (7 KB)

Event Timeline