common/sfc_efx/base: add Xilinx capabilities table lookup
[dpdk.git] / drivers / common / sfc_efx / base / rhead_pci.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  * Copyright(c) 2019-2020 Xilinx, Inc.
4  * Copyright(c) 2019 Solarflare Communications Inc.
5  */
6
7 #include "efx.h"
8 #include "efx_impl.h"
9
10 #if EFSYS_OPT_RIVERHEAD && EFSYS_OPT_PCI
11
12 /*
13  * Search for a EF100 resource locator from the given offset of an entry
14  * in a Xilinx capabilities table.
15  */
16 static  __checkReturn                   efx_rc_t
17 rhead_xilinx_cap_tbl_find_ef100_locator(
18         __in                            efsys_bar_t *esbp,
19         __in                            efsys_dma_addr_t tbl_offset,
20         __out                           efx_bar_region_t *ef100_ebrp)
21 {
22         efx_rc_t rc;
23         efsys_dma_addr_t entry_offset = tbl_offset;
24
25         rc = efx_pci_xilinx_cap_tbl_find(esbp, ESE_GZ_CFGBAR_ENTRY_EF100,
26                                            B_FALSE, &entry_offset);
27         if (rc != 0) {
28                 /* EF100 locator not found (ENOENT) or other error */
29                 goto fail1;
30         }
31
32         rc = rhead_nic_xilinx_cap_tbl_read_ef100_locator(esbp, entry_offset,
33                                                          ef100_ebrp);
34         if (rc != 0)
35                 goto fail2;
36
37         return (0);
38
39 fail2:
40         EFSYS_PROBE(fail2);
41 fail1:
42         EFSYS_PROBE1(fail1, efx_rc_t, rc);
43
44         return (rc);
45 }
46
47         __checkReturn                   efx_rc_t
48 rhead_pci_nic_membar_lookup(
49         __in                            efsys_pci_config_t *espcp,
50         __out                           efx_bar_region_t *ebrp)
51 {
52         boolean_t xilinx_tbl_found = B_FALSE;
53         unsigned int xilinx_tbl_bar;
54         efsys_dma_addr_t xilinx_tbl_offset;
55         size_t pci_capa_offset = 0;
56         boolean_t bar_found = B_FALSE;
57         efx_rc_t rc = ENOENT;
58         efsys_bar_t xil_eb;
59
60         /*
61          * SF-119689-TC Riverhead Host Interface section 4.2.2. describes
62          * the following discovery steps.
63          */
64         while (1) {
65                 rc = efx_pci_find_next_xilinx_cap_table(espcp, &pci_capa_offset,
66                                                         &xilinx_tbl_bar,
67                                                         &xilinx_tbl_offset);
68                 if (rc != 0) {
69                         /*
70                          * SF-119689-TC Riverhead Host Interface section 4.2.2.
71                          * defines the following fallbacks for the memory bar
72                          * and the offset when no Xilinx capabilities table is
73                          * found.
74                          */
75                         if (rc == ENOENT && xilinx_tbl_found == B_FALSE) {
76                                 ebrp->ebr_type = EFX_BAR_TYPE_MEM;
77                                 ebrp->ebr_index = EFX_MEM_BAR_RIVERHEAD;
78                                 ebrp->ebr_offset = 0;
79                                 ebrp->ebr_length = 0;
80                                 bar_found = B_TRUE;
81                                 break;
82                         } else {
83                                 goto fail1;
84                         }
85
86                 }
87
88                 xilinx_tbl_found = B_TRUE;
89
90                 EFSYS_PCI_FIND_MEM_BAR(espcp, xilinx_tbl_bar, &xil_eb, &rc);
91                 if (rc != 0)
92                         goto fail2;
93
94                 rc = rhead_xilinx_cap_tbl_find_ef100_locator(&xil_eb,
95                                                              xilinx_tbl_offset,
96                                                              ebrp);
97                 if (rc == 0) {
98                         /* Found valid EF100 locator. */
99                         bar_found = B_TRUE;
100                         break;
101                 } else if (rc != ENOENT) {
102                         /* Table access failed, so terminate search. */
103                         goto fail3;
104                 }
105         }
106
107         if (bar_found == B_FALSE)
108                 goto fail4;
109
110         return (0);
111
112 fail4:
113         EFSYS_PROBE(fail4);
114 fail3:
115         EFSYS_PROBE(fail3);
116 fail2:
117         EFSYS_PROBE(fail2);
118 fail1:
119         EFSYS_PROBE1(fail1, efx_rc_t, rc);
120
121         return (rc);
122 }
123
124 #endif /* EFSYS_OPT_RIVERHEAD && EFSYS_OPT_PCI */