1 /* SPDX-License-Identifier: BSD-3-Clause
3 * Copyright(c) 2019-2021 Xilinx, Inc.
4 * Copyright(c) 2019 Solarflare Communications Inc.
12 __checkReturn efx_rc_t
13 efx_pci_config_next_ext_cap(
14 __in efsys_pci_config_t *espcp,
15 __in const efx_pci_ops_t *epop,
16 __inout size_t *offsetp)
22 if (offsetp == NULL) {
28 *offsetp = ESE_GZ_PCI_BASE_CONFIG_SPACE_SIZE;
30 rc = epop->epo_config_readd(espcp, *offsetp +
31 (EFX_LOW_BIT(ESF_GZ_PCI_EXPRESS_XCAP_ID) / 8),
38 next = EFX_DWORD_FIELD(hdr, ESF_GZ_PCI_EXPRESS_XCAP_NEXT);
39 if (next < ESE_GZ_PCI_BASE_CONFIG_SPACE_SIZE)
46 * Returns 0 if the next capability is present otherwise ENOENT
47 * indicating that the function finished correctly.
54 EFSYS_PROBE1(fail1, efx_rc_t, rc);
59 __checkReturn efx_rc_t
60 efx_pci_config_find_next_ext_cap(
61 __in efsys_pci_config_t *espcp,
62 __in const efx_pci_ops_t *epop,
64 __inout size_t *offsetp)
70 if (offsetp == NULL) {
78 rc = efx_pci_config_next_ext_cap(espcp, epop, &position);
86 rc = epop->epo_config_readd(espcp, position +
87 (EFX_LOW_BIT(ESF_GZ_PCI_EXPRESS_XCAP_ID) / 8),
94 if (EFX_DWORD_FIELD(hdr, ESF_GZ_PCI_EXPRESS_XCAP_ID) ==
103 * Returns 0 if found otherwise ENOENT indicating that search finished
113 EFSYS_PROBE1(fail1, efx_rc_t, rc);
118 __checkReturn efx_rc_t
119 efx_pci_find_next_xilinx_cap_table(
120 __in efsys_pci_config_t *espcp,
121 __in const efx_pci_ops_t *epop,
122 __inout size_t *pci_cap_offsetp,
123 __out unsigned int *xilinx_tbl_barp,
124 __out efsys_dma_addr_t *xilinx_tbl_offsetp)
129 if (pci_cap_offsetp == NULL) {
134 cap_offset = *pci_cap_offsetp;
137 unsigned int tbl_bar;
138 efsys_dma_addr_t tbl_offset;
140 rc = efx_pci_config_find_next_ext_cap(espcp, epop,
141 ESE_GZ_PCI_EXPRESS_XCAP_ID_VNDR, &cap_offset);
150 * The found extended PCI capability is a vendor-specific
151 * capability, but not necessarily a Xilinx capabilities table
152 * locator. Try to read it and skip it if the capability is
155 rc = efx_pci_read_ext_cap_xilinx_table(espcp, epop, cap_offset,
156 &tbl_bar, &tbl_offset);
158 *xilinx_tbl_barp = tbl_bar;
159 *xilinx_tbl_offsetp = tbl_offset;
160 *pci_cap_offsetp = cap_offset;
171 * Returns 0 if found otherwise ENOENT indicating that search finished
181 EFSYS_PROBE1(fail1, efx_rc_t, rc);
186 __checkReturn efx_rc_t
187 efx_pci_read_ext_cap_xilinx_table(
188 __in efsys_pci_config_t *espcp,
189 __in const efx_pci_ops_t *epop,
190 __in size_t cap_offset,
191 __out unsigned int *barp,
192 __out efsys_dma_addr_t *offsetp)
194 size_t vsec_offset = cap_offset + ESE_GZ_PCI_EXPRESS_XCAP_HDR_SIZE;
201 uint32_t offset_high = 0;
203 efsys_dma_addr_t offset;
206 rc = epop->epo_config_readd(espcp, cap_offset +
207 (EFX_LOW_BIT(ESF_GZ_PCI_EXPRESS_XCAP_ID) / 8),
214 if (EFX_DWORD_FIELD(cap_hdr, ESF_GZ_PCI_EXPRESS_XCAP_VER) !=
215 ESE_GZ_PCI_EXPRESS_XCAP_VER_VSEC) {
220 rc = epop->epo_config_readd(espcp, vsec_offset +
221 (EFX_LOW_BIT(ESF_GZ_VSEC_ID) / 8),
228 vsec_len = EFX_OWORD_FIELD32(vsec, ESF_GZ_VSEC_LEN);
229 vsec_id = EFX_OWORD_FIELD32(vsec, ESF_GZ_VSEC_ID);
230 vsec_rev = EFX_OWORD_FIELD32(vsec, ESF_GZ_VSEC_VER);
233 * Condition of the vendor-specific extended PCI capability not being
234 * a Xilinx capabilities table locator.
236 if (vsec_id != ESE_GZ_XILINX_VSEC_ID) {
241 if (vsec_rev != ESE_GZ_VSEC_VER_XIL_CFGBAR ||
242 vsec_len < ESE_GZ_VSEC_LEN_MIN) {
247 rc = epop->epo_config_readd(espcp, vsec_offset +
248 (EFX_LOW_BIT(ESF_GZ_VSEC_TBL_BAR) / 8),
255 bar = EFX_OWORD_FIELD32(vsec, ESF_GZ_VSEC_TBL_BAR);
256 offset_low = EFX_OWORD_FIELD32(vsec, ESF_GZ_VSEC_TBL_OFF_LO);
258 if (vsec_len >= ESE_GZ_VSEC_LEN_HIGH_OFFT) {
259 rc = epop->epo_config_readd(espcp, vsec_offset +
260 (EFX_LOW_BIT(ESF_GZ_VSEC_TBL_OFF_HI) / 8),
267 offset_high = EFX_OWORD_FIELD32(vsec, ESF_GZ_VSEC_TBL_OFF_HI);
270 /* High bits of low offset are discarded by the shift */
271 offset = offset_low << ESE_GZ_VSEC_TBL_OFF_LO_BYTES_SHIFT;
274 * Avoid the 'left shift count >= width of type' warning on systems
275 * without uint64_t support.
278 offset |= (uint64_t)offset_high << ESE_GZ_VSEC_TBL_OFF_HI_BYTES_SHIFT;
280 _NOTE(ARGUNUSED(offset_high))
301 EFSYS_PROBE1(fail1, efx_rc_t, rc);
306 __checkReturn efx_rc_t
307 efx_pci_xilinx_cap_tbl_find(
308 __in efsys_bar_t *esbp,
309 __in uint32_t format_id,
310 __in boolean_t skip_first,
311 __inout efsys_dma_addr_t *entry_offsetp)
313 efsys_dma_addr_t offset;
314 boolean_t skip = skip_first;
320 if (entry_offsetp == NULL) {
325 offset = *entry_offsetp;
328 * SF-119689-TC Riverhead Host Interface section 4.2.2.
329 * describes the following discovery steps.
333 * Xilinx Capabilities Table requires 32bit aligned reads.
334 * See SF-119689-TC section 4.2.2 "Discovery Steps".
336 EFSYS_BAR_READD(esbp, offset +
337 (EFX_LOW_BIT(ESF_GZ_CFGBAR_ENTRY_FORMAT) / 8),
338 &header.eq_dword[0], B_FALSE);
339 EFSYS_BAR_READD(esbp, offset +
340 (EFX_LOW_BIT(ESF_GZ_CFGBAR_ENTRY_SIZE) / 8),
341 &header.eq_dword[1], B_FALSE);
343 format = EFX_QWORD_FIELD32(header, ESF_GZ_CFGBAR_ENTRY_FORMAT);
344 last = EFX_QWORD_FIELD32(header, ESF_GZ_CFGBAR_ENTRY_LAST);
346 if (skip == B_FALSE && format == format_id) {
347 *entry_offsetp = offset;
352 offset += EFX_QWORD_FIELD32(header, ESF_GZ_CFGBAR_ENTRY_SIZE);
354 } while (last == B_FALSE);
357 * Returns 0 if found otherwise ENOENT indicating that
358 * search finished correctly.
363 EFSYS_PROBE1(fail1, efx_rc_t, rc);
368 #endif /* EFSYS_OPT_PCI */