/* SPDX-License-Identifier: BSD-3-Clause
*
- * Copyright(c) 2019-2020 Xilinx, Inc.
+ * Copyright(c) 2019-2021 Xilinx, Inc.
* Copyright(c) 2019 Solarflare Communications Inc.
*/
__checkReturn efx_rc_t
efx_pci_config_next_ext_cap(
__in efsys_pci_config_t *espcp,
+ __in const efx_pci_ops_t *epop,
__inout size_t *offsetp)
{
efx_dword_t hdr;
if (*offsetp == 0) {
*offsetp = ESE_GZ_PCI_BASE_CONFIG_SPACE_SIZE;
} else {
- EFSYS_PCI_CONFIG_READD(espcp, *offsetp +
+ rc = epop->epo_config_readd(espcp, *offsetp +
(EFX_LOW_BIT(ESF_GZ_PCI_EXPRESS_XCAP_ID) / 8),
- &hdr, &rc);
+ &hdr);
if (rc != 0) {
rc = EIO;
goto fail2;
__checkReturn efx_rc_t
efx_pci_config_find_next_ext_cap(
__in efsys_pci_config_t *espcp,
+ __in const efx_pci_ops_t *epop,
__in uint16_t cap_id,
__inout size_t *offsetp)
{
position = *offsetp;
while (1) {
- rc = efx_pci_config_next_ext_cap(espcp, &position);
+ rc = efx_pci_config_next_ext_cap(espcp, epop, &position);
if (rc != 0) {
if (rc == ENOENT)
break;
goto fail2;
}
- EFSYS_PCI_CONFIG_READD(espcp, position +
+ rc = epop->epo_config_readd(espcp, position +
(EFX_LOW_BIT(ESF_GZ_PCI_EXPRESS_XCAP_ID) / 8),
- &hdr, &rc);
+ &hdr);
if (rc != 0) {
rc = EIO;
goto fail3;
__checkReturn efx_rc_t
efx_pci_find_next_xilinx_cap_table(
__in efsys_pci_config_t *espcp,
+ __in const efx_pci_ops_t *epop,
__inout size_t *pci_cap_offsetp,
__out unsigned int *xilinx_tbl_barp,
__out efsys_dma_addr_t *xilinx_tbl_offsetp)
unsigned int tbl_bar;
efsys_dma_addr_t tbl_offset;
- rc = efx_pci_config_find_next_ext_cap(espcp,
+ rc = efx_pci_config_find_next_ext_cap(espcp, epop,
ESE_GZ_PCI_EXPRESS_XCAP_ID_VNDR, &cap_offset);
if (rc != 0) {
if (rc == ENOENT)
* locator. Try to read it and skip it if the capability is
* not the locator.
*/
- rc = efx_pci_read_ext_cap_xilinx_table(espcp, cap_offset,
+ rc = efx_pci_read_ext_cap_xilinx_table(espcp, epop, cap_offset,
&tbl_bar, &tbl_offset);
if (rc == 0) {
*xilinx_tbl_barp = tbl_bar;
__checkReturn efx_rc_t
efx_pci_read_ext_cap_xilinx_table(
__in efsys_pci_config_t *espcp,
+ __in const efx_pci_ops_t *epop,
__in size_t cap_offset,
__out unsigned int *barp,
__out efsys_dma_addr_t *offsetp)
efsys_dma_addr_t offset;
efx_rc_t rc;
- EFSYS_PCI_CONFIG_READD(espcp, cap_offset +
+ rc = epop->epo_config_readd(espcp, cap_offset +
(EFX_LOW_BIT(ESF_GZ_PCI_EXPRESS_XCAP_ID) / 8),
- &cap_hdr, &rc);
+ &cap_hdr);
if (rc != 0) {
rc = EIO;
goto fail1;
goto fail2;
}
- EFSYS_PCI_CONFIG_READD(espcp, vsec_offset +
+ rc = epop->epo_config_readd(espcp, vsec_offset +
(EFX_LOW_BIT(ESF_GZ_VSEC_ID) / 8),
- &vsec.eo_dword[0], &rc);
+ &vsec.eo_dword[0]);
if (rc != 0) {
rc = EIO;
goto fail3;
goto fail5;
}
- EFSYS_PCI_CONFIG_READD(espcp, vsec_offset +
+ rc = epop->epo_config_readd(espcp, vsec_offset +
(EFX_LOW_BIT(ESF_GZ_VSEC_TBL_BAR) / 8),
- &vsec.eo_dword[1], &rc);
+ &vsec.eo_dword[1]);
if (rc != 0) {
rc = EIO;
goto fail6;
offset_low = EFX_OWORD_FIELD32(vsec, ESF_GZ_VSEC_TBL_OFF_LO);
if (vsec_len >= ESE_GZ_VSEC_LEN_HIGH_OFFT) {
- EFSYS_PCI_CONFIG_READD(espcp, vsec_offset +
+ rc = epop->epo_config_readd(espcp, vsec_offset +
(EFX_LOW_BIT(ESF_GZ_VSEC_TBL_OFF_HI) / 8),
- &vsec.eo_dword[2], &rc);
+ &vsec.eo_dword[2]);
if (rc != 0) {
rc = EIO;
goto fail7;
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;
+ 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;
+ }
+
+ offset = *entry_offsetp;
+ 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 */