[v3,46/60] common/sfc_efx/base: add Xilinx capabilities table lookup
diff mbox series

Message ID 1600949555-28043-47-git-send-email-arybchenko@solarflare.com
State Accepted
Delegated to: Ferruh Yigit
Headers show
Series
  • common/sfc_efx: support Riverhead NIC family
Related show

Checks

Context Check Description
ci/checkpatch warning coding style issues

Commit Message

Andrew Rybchenko Sept. 24, 2020, 12:12 p.m. UTC
From: Igor Romanov <igor.romanov@oktetlabs.ru>

APIs for searching a capability in a Xilinx capabilities table and
reading table entries are needed for function control window lookup
to get the bar index and offset of the window.

Signed-off-by: Igor Romanov <igor.romanov@oktetlabs.ru>
Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
---
 drivers/common/sfc_efx/base/efx_impl.h   | 15 ++++++
 drivers/common/sfc_efx/base/efx_pci.c    | 61 ++++++++++++++++++++++++
 drivers/common/sfc_efx/base/rhead_impl.h |  7 +++
 drivers/common/sfc_efx/base/rhead_nic.c  | 50 +++++++++++++++++++
 drivers/common/sfc_efx/base/rhead_pci.c  | 51 +++++++++++++++++++-
 5 files changed, 183 insertions(+), 1 deletion(-)

Patch
diff mbox series

diff --git a/drivers/common/sfc_efx/base/efx_impl.h b/drivers/common/sfc_efx/base/efx_impl.h
index 422f97c5ca..dfe5f1fecf 100644
--- a/drivers/common/sfc_efx/base/efx_impl.h
+++ b/drivers/common/sfc_efx/base/efx_impl.h
@@ -1617,6 +1617,21 @@  efx_pci_read_ext_cap_xilinx_table(
 	__out				unsigned int *barp,
 	__out				efsys_dma_addr_t *offsetp);
 
+/*
+ * Find a capability with specified format_id in a Xilinx capabilities table.
+ * Searching is started from provided offset, taking skip_first into account.
+ * If search succeeds, found capability is in modified offset.
+ *
+ * Returns ENOENT if an entry with specified format id is not found.
+ */
+LIBEFX_INTERNAL
+extern	__checkReturn			efx_rc_t
+efx_pci_xilinx_cap_tbl_find(
+	__in				efsys_bar_t *esbp,
+	__in				uint32_t format_id,
+	__in				boolean_t skip_first,
+	__inout				efsys_dma_addr_t *entry_offsetp);
+
 #endif /* EFSYS_OPT_PCI */
 
 #ifdef	__cplusplus
diff --git a/drivers/common/sfc_efx/base/efx_pci.c b/drivers/common/sfc_efx/base/efx_pci.c
index 8707220849..bdf995cf84 100644
--- a/drivers/common/sfc_efx/base/efx_pci.c
+++ b/drivers/common/sfc_efx/base/efx_pci.c
@@ -299,4 +299,65 @@  efx_pci_read_ext_cap_xilinx_table(
 	return (rc);
 }
 
+	__checkReturn			efx_rc_t
+efx_pci_xilinx_cap_tbl_find(
+	__in				efsys_bar_t *esbp,
+	__in				uint32_t format_id,
+	__in				boolean_t skip_first,
+	__inout				efsys_dma_addr_t *entry_offsetp)
+{
+	efsys_dma_addr_t offset = *entry_offsetp;
+	boolean_t skip = skip_first;
+	efx_qword_t header;
+	uint32_t format;
+	uint32_t last;
+	efx_rc_t rc;
+
+	if (entry_offsetp == NULL) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	rc = ENOENT;
+	/*
+	 * SF-119689-TC Riverhead Host Interface section 4.2.2.
+	 * describes the following discovery steps.
+	 */
+	do {
+		/*
+		 * Xilinx Capabilities Table requires 32bit aligned reads.
+		 * See SF-119689-TC section 4.2.2 "Discovery Steps".
+		 */
+		EFSYS_BAR_READD(esbp, offset +
+				(EFX_LOW_BIT(ESF_GZ_CFGBAR_ENTRY_FORMAT) / 8),
+				&header.eq_dword[0], B_FALSE);
+		EFSYS_BAR_READD(esbp, offset +
+				(EFX_LOW_BIT(ESF_GZ_CFGBAR_ENTRY_SIZE) / 8),
+				&header.eq_dword[1], B_FALSE);
+
+		format = EFX_QWORD_FIELD32(header, ESF_GZ_CFGBAR_ENTRY_FORMAT);
+		last = EFX_QWORD_FIELD32(header, ESF_GZ_CFGBAR_ENTRY_LAST);
+
+		if (skip == B_FALSE && format == format_id) {
+			*entry_offsetp = offset;
+			rc = 0;
+			break;
+		}
+
+		offset += EFX_QWORD_FIELD32(header, ESF_GZ_CFGBAR_ENTRY_SIZE);
+		skip = B_FALSE;
+	} while (last == B_FALSE);
+
+	/*
+	 * Returns 0 if found otherwise ENOENT indicating that
+	 * search finished correctly.
+	 */
+	return (rc);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+	return (rc);
+}
+
 #endif /* EFSYS_OPT_PCI */
diff --git a/drivers/common/sfc_efx/base/rhead_impl.h b/drivers/common/sfc_efx/base/rhead_impl.h
index c62cf8c2c6..91347c335a 100644
--- a/drivers/common/sfc_efx/base/rhead_impl.h
+++ b/drivers/common/sfc_efx/base/rhead_impl.h
@@ -451,6 +451,13 @@  rhead_pci_nic_membar_lookup(
 
 #endif /* EFSYS_OPT_PCI */
 
+LIBEFX_INTERNAL
+extern	__checkReturn			efx_rc_t
+rhead_nic_xilinx_cap_tbl_read_ef100_locator(
+	__in				efsys_bar_t *esbp,
+	__in				efsys_dma_addr_t offset,
+	__out				efx_bar_region_t *ebrp);
+
 #ifdef	__cplusplus
 }
 #endif
diff --git a/drivers/common/sfc_efx/base/rhead_nic.c b/drivers/common/sfc_efx/base/rhead_nic.c
index a773a43bcc..787afb37a3 100644
--- a/drivers/common/sfc_efx/base/rhead_nic.c
+++ b/drivers/common/sfc_efx/base/rhead_nic.c
@@ -518,4 +518,54 @@  rhead_nic_register_test(
 
 #endif	/* EFSYS_OPT_DIAG */
 
+	__checkReturn			efx_rc_t
+rhead_nic_xilinx_cap_tbl_read_ef100_locator(
+	__in				efsys_bar_t *esbp,
+	__in				efsys_dma_addr_t offset,
+	__out				efx_bar_region_t *ebrp)
+{
+	efx_oword_t entry;
+	uint32_t rev;
+	uint32_t len;
+	efx_rc_t rc;
+
+	/*
+	 * Xilinx Capabilities Table requires 32bit aligned reads.
+	 * See SF-119689-TC section 4.2.2 "Discovery Steps".
+	 */
+	EFSYS_BAR_READD(esbp, offset +
+			(EFX_LOW_BIT(ESF_GZ_CFGBAR_ENTRY_FORMAT) / 8),
+			&entry.eo_dword[0], B_FALSE);
+	EFSYS_BAR_READD(esbp, offset +
+			(EFX_LOW_BIT(ESF_GZ_CFGBAR_ENTRY_SIZE) / 8),
+			&entry.eo_dword[1], B_FALSE);
+
+	rev = EFX_OWORD_FIELD32(entry, ESF_GZ_CFGBAR_ENTRY_REV);
+	len = EFX_OWORD_FIELD32(entry, ESF_GZ_CFGBAR_ENTRY_SIZE);
+
+	if (rev != ESE_GZ_CFGBAR_ENTRY_REV_EF100 ||
+	    len < ESE_GZ_CFGBAR_ENTRY_SIZE_EF100) {
+		rc = EINVAL;
+		goto fail1;
+	}
+
+	EFSYS_BAR_READD(esbp, offset +
+			(EFX_LOW_BIT(ESF_GZ_CFGBAR_EF100_BAR) / 8),
+			&entry.eo_dword[2], B_FALSE);
+
+	ebrp->ebr_index = EFX_OWORD_FIELD32(entry, ESF_GZ_CFGBAR_EF100_BAR);
+	ebrp->ebr_offset = EFX_OWORD_FIELD32(entry,
+			ESF_GZ_CFGBAR_EF100_FUNC_CTL_WIN_OFF) <<
+			ESE_GZ_EF100_FUNC_CTL_WIN_OFF_SHIFT;
+	ebrp->ebr_type = EFX_BAR_TYPE_MEM;
+	ebrp->ebr_length = 0;
+
+	return (0);
+
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+	return (rc);
+}
+
 #endif	/* EFSYS_OPT_RIVERHEAD */
diff --git a/drivers/common/sfc_efx/base/rhead_pci.c b/drivers/common/sfc_efx/base/rhead_pci.c
index 47e89cf8a2..0a6e72f076 100644
--- a/drivers/common/sfc_efx/base/rhead_pci.c
+++ b/drivers/common/sfc_efx/base/rhead_pci.c
@@ -9,6 +9,41 @@ 
 
 #if EFSYS_OPT_RIVERHEAD && EFSYS_OPT_PCI
 
+/*
+ * Search for a EF100 resource locator from the given offset of an entry
+ * in a Xilinx capabilities table.
+ */
+static	__checkReturn			efx_rc_t
+rhead_xilinx_cap_tbl_find_ef100_locator(
+	__in				efsys_bar_t *esbp,
+	__in				efsys_dma_addr_t tbl_offset,
+	__out				efx_bar_region_t *ef100_ebrp)
+{
+	efx_rc_t rc;
+	efsys_dma_addr_t entry_offset = tbl_offset;
+
+	rc = efx_pci_xilinx_cap_tbl_find(esbp, ESE_GZ_CFGBAR_ENTRY_EF100,
+					   B_FALSE, &entry_offset);
+	if (rc != 0) {
+		/* EF100 locator not found (ENOENT) or other error */
+		goto fail1;
+	}
+
+	rc = rhead_nic_xilinx_cap_tbl_read_ef100_locator(esbp, entry_offset,
+							 ef100_ebrp);
+	if (rc != 0)
+		goto fail2;
+
+	return (0);
+
+fail2:
+	EFSYS_PROBE(fail2);
+fail1:
+	EFSYS_PROBE1(fail1, efx_rc_t, rc);
+
+	return (rc);
+}
+
 	__checkReturn			efx_rc_t
 rhead_pci_nic_membar_lookup(
 	__in				efsys_pci_config_t *espcp,
@@ -55,13 +90,27 @@  rhead_pci_nic_membar_lookup(
 		EFSYS_PCI_FIND_MEM_BAR(espcp, xilinx_tbl_bar, &xil_eb, &rc);
 		if (rc != 0)
 			goto fail2;
+
+		rc = rhead_xilinx_cap_tbl_find_ef100_locator(&xil_eb,
+							     xilinx_tbl_offset,
+							     ebrp);
+		if (rc == 0) {
+			/* Found valid EF100 locator. */
+			bar_found = B_TRUE;
+			break;
+		} else if (rc != ENOENT) {
+			/* Table access failed, so terminate search. */
+			goto fail3;
+		}
 	}
 
 	if (bar_found == B_FALSE)
-		goto fail3;
+		goto fail4;
 
 	return (0);
 
+fail4:
+	EFSYS_PROBE(fail4);
 fail3:
 	EFSYS_PROBE(fail3);
 fail2: