LCOV - code coverage report
Current view: top level - drivers/common/sfc_efx/base - efx_pci.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 89 0.0 %
Date: 2024-02-14 00:53:57 Functions: 0 5 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 52 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *
       3                 :            :  * Copyright(c) 2019-2021 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_PCI
      11                 :            : 
      12                 :            :         __checkReturn                   efx_rc_t
      13                 :          0 : 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)
      17                 :            : {
      18                 :            :         efx_dword_t hdr;
      19                 :            :         efx_rc_t rc = 0;
      20                 :            :         size_t next;
      21                 :            : 
      22         [ #  # ]:          0 :         if (offsetp == NULL) {
      23                 :            :                 rc = EINVAL;
      24                 :          0 :                 goto fail1;
      25                 :            :         }
      26                 :            : 
      27         [ #  # ]:          0 :         if (*offsetp == 0) {
      28                 :          0 :                 *offsetp = ESE_GZ_PCI_BASE_CONFIG_SPACE_SIZE;
      29                 :            :         } else {
      30                 :          0 :                 rc = epop->epo_config_readd(espcp, *offsetp +
      31                 :            :                                 (EFX_LOW_BIT(ESF_GZ_PCI_EXPRESS_XCAP_ID) / 8),
      32                 :            :                                 &hdr);
      33         [ #  # ]:          0 :                 if (rc != 0) {
      34                 :            :                         rc = EIO;
      35                 :          0 :                         goto fail2;
      36                 :            :                 }
      37                 :            : 
      38                 :          0 :                 next = EFX_DWORD_FIELD(hdr, ESF_GZ_PCI_EXPRESS_XCAP_NEXT);
      39         [ #  # ]:          0 :                 if (next < ESE_GZ_PCI_BASE_CONFIG_SPACE_SIZE)
      40                 :            :                         rc = ENOENT;
      41                 :            :                 else
      42                 :          0 :                         *offsetp = next;
      43                 :            :         }
      44                 :            : 
      45                 :            :         /*
      46                 :            :          * Returns 0 if the next capability is present otherwise ENOENT
      47                 :            :          * indicating that the function finished correctly.
      48                 :            :          */
      49                 :            :         return (rc);
      50                 :            : 
      51                 :            : fail2:
      52                 :            :         EFSYS_PROBE(fail2);
      53                 :            : fail1:
      54                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
      55                 :            : 
      56                 :            :         return (rc);
      57                 :            : }
      58                 :            : 
      59                 :            :         __checkReturn                   efx_rc_t
      60                 :          0 : efx_pci_config_find_next_ext_cap(
      61                 :            :         __in                            efsys_pci_config_t *espcp,
      62                 :            :         __in                            const efx_pci_ops_t *epop,
      63                 :            :         __in                            uint16_t cap_id,
      64                 :            :         __inout                         size_t *offsetp)
      65                 :            : {
      66                 :            :         efx_dword_t hdr;
      67                 :            :         size_t position;
      68                 :            :         efx_rc_t rc;
      69                 :            : 
      70         [ #  # ]:          0 :         if (offsetp == NULL) {
      71                 :            :                 rc = EINVAL;
      72                 :          0 :                 goto fail1;
      73                 :            :         }
      74                 :            : 
      75                 :          0 :         position = *offsetp;
      76                 :            : 
      77                 :            :         while (1) {
      78                 :          0 :                 rc = efx_pci_config_next_ext_cap(espcp, epop, &position);
      79         [ #  # ]:          0 :                 if (rc != 0) {
      80         [ #  # ]:          0 :                         if (rc == ENOENT)
      81                 :            :                                 break;
      82                 :            :                         else
      83                 :          0 :                                 goto fail2;
      84                 :            :                 }
      85                 :            : 
      86                 :          0 :                 rc = epop->epo_config_readd(espcp, position +
      87                 :            :                                 (EFX_LOW_BIT(ESF_GZ_PCI_EXPRESS_XCAP_ID) / 8),
      88                 :            :                                 &hdr);
      89         [ #  # ]:          0 :                 if (rc != 0) {
      90                 :            :                         rc = EIO;
      91                 :          0 :                         goto fail3;
      92                 :            :                 }
      93                 :            : 
      94         [ #  # ]:          0 :                 if (EFX_DWORD_FIELD(hdr, ESF_GZ_PCI_EXPRESS_XCAP_ID) ==
      95                 :            :                     cap_id) {
      96                 :          0 :                         *offsetp = position;
      97                 :            :                         rc = 0;
      98                 :          0 :                         break;
      99                 :            :                 }
     100                 :            :         }
     101                 :            : 
     102                 :            :         /*
     103                 :            :          * Returns 0 if found otherwise ENOENT indicating that search finished
     104                 :            :          * correctly.
     105                 :            :          */
     106                 :            :         return (rc);
     107                 :            : 
     108                 :            : fail3:
     109                 :            :         EFSYS_PROBE(fail3);
     110                 :            : fail2:
     111                 :            :         EFSYS_PROBE(fail2);
     112                 :            : fail1:
     113                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     114                 :            : 
     115                 :            :         return (rc);
     116                 :            : }
     117                 :            : 
     118                 :            :         __checkReturn                   efx_rc_t
     119                 :          0 : 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)
     125                 :            : {
     126                 :            :         size_t cap_offset;
     127                 :            :         efx_rc_t rc;
     128                 :            : 
     129         [ #  # ]:          0 :         if (pci_cap_offsetp == NULL) {
     130                 :            :                 rc = EINVAL;
     131                 :          0 :                 goto fail1;
     132                 :            :         }
     133                 :            : 
     134                 :          0 :         cap_offset = *pci_cap_offsetp;
     135                 :            : 
     136                 :            :         while (1) {
     137                 :            :                 unsigned int tbl_bar;
     138                 :            :                 efsys_dma_addr_t tbl_offset;
     139                 :            : 
     140                 :          0 :                 rc = efx_pci_config_find_next_ext_cap(espcp, epop,
     141                 :            :                                 ESE_GZ_PCI_EXPRESS_XCAP_ID_VNDR, &cap_offset);
     142         [ #  # ]:          0 :                 if (rc != 0) {
     143         [ #  # ]:          0 :                         if (rc == ENOENT)
     144                 :            :                                 break;
     145                 :            :                         else
     146                 :          0 :                                 goto fail2;
     147                 :            :                 }
     148                 :            : 
     149                 :            :                 /*
     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
     153                 :            :                  * not the locator.
     154                 :            :                  */
     155                 :          0 :                 rc = efx_pci_read_ext_cap_xilinx_table(espcp, epop, cap_offset,
     156                 :            :                                                        &tbl_bar, &tbl_offset);
     157         [ #  # ]:          0 :                 if (rc == 0) {
     158                 :          0 :                         *xilinx_tbl_barp = tbl_bar;
     159                 :          0 :                         *xilinx_tbl_offsetp = tbl_offset;
     160                 :          0 :                         *pci_cap_offsetp = cap_offset;
     161                 :          0 :                         break;
     162                 :            :                 } else {
     163         [ #  # ]:          0 :                         if (rc == ENOENT)
     164                 :          0 :                                 continue;
     165                 :            :                         else
     166                 :          0 :                                 goto fail3;
     167                 :            :                 }
     168                 :            :         }
     169                 :            : 
     170                 :            :         /*
     171                 :            :          * Returns 0 if found otherwise ENOENT indicating that search finished
     172                 :            :          * correctly.
     173                 :            :          */
     174                 :          0 :         return (rc);
     175                 :            : 
     176                 :            : fail3:
     177                 :            :         EFSYS_PROBE(fail3);
     178                 :            : fail2:
     179                 :            :         EFSYS_PROBE(fail2);
     180                 :            : fail1:
     181                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     182                 :            : 
     183                 :            :         return (rc);
     184                 :            : }
     185                 :            : 
     186                 :            :         __checkReturn                   efx_rc_t
     187                 :          0 : 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)
     193                 :            : {
     194                 :          0 :         size_t vsec_offset = cap_offset + ESE_GZ_PCI_EXPRESS_XCAP_HDR_SIZE;
     195                 :            :         efx_dword_t cap_hdr;
     196                 :            :         efx_oword_t vsec;
     197                 :            :         uint32_t vsec_len;
     198                 :            :         uint32_t vsec_id;
     199                 :            :         uint32_t vsec_rev;
     200                 :            :         uint32_t offset_low;
     201                 :            :         uint32_t offset_high = 0;
     202                 :            :         unsigned int bar;
     203                 :            :         efsys_dma_addr_t offset;
     204                 :            :         efx_rc_t rc;
     205                 :            : 
     206                 :          0 :         rc = epop->epo_config_readd(espcp, cap_offset +
     207                 :            :                                (EFX_LOW_BIT(ESF_GZ_PCI_EXPRESS_XCAP_ID) / 8),
     208                 :            :                                &cap_hdr);
     209         [ #  # ]:          0 :         if (rc != 0) {
     210                 :            :                 rc = EIO;
     211                 :          0 :                 goto fail1;
     212                 :            :         }
     213                 :            : 
     214         [ #  # ]:          0 :         if (EFX_DWORD_FIELD(cap_hdr, ESF_GZ_PCI_EXPRESS_XCAP_VER) !=
     215                 :            :             ESE_GZ_PCI_EXPRESS_XCAP_VER_VSEC) {
     216                 :            :                 rc = EINVAL;
     217                 :          0 :                 goto fail2;
     218                 :            :         }
     219                 :            : 
     220                 :          0 :         rc = epop->epo_config_readd(espcp, vsec_offset +
     221                 :            :                                (EFX_LOW_BIT(ESF_GZ_VSEC_ID) / 8),
     222                 :            :                                &vsec.eo_dword[0]);
     223         [ #  # ]:          0 :         if (rc != 0) {
     224                 :            :                 rc = EIO;
     225                 :          0 :                 goto fail3;
     226                 :            :         }
     227                 :            : 
     228                 :          0 :         vsec_len = EFX_OWORD_FIELD32(vsec, ESF_GZ_VSEC_LEN);
     229                 :          0 :         vsec_id = EFX_OWORD_FIELD32(vsec, ESF_GZ_VSEC_ID);
     230                 :          0 :         vsec_rev = EFX_OWORD_FIELD32(vsec, ESF_GZ_VSEC_VER);
     231                 :            : 
     232                 :            :         /*
     233                 :            :          * Condition of the vendor-specific extended PCI capability not being
     234                 :            :          * a Xilinx capabilities table locator.
     235                 :            :          */
     236         [ #  # ]:          0 :         if (vsec_id != ESE_GZ_XILINX_VSEC_ID) {
     237                 :            :                 rc = ENOENT;
     238                 :          0 :                 goto fail4;
     239                 :            :         }
     240                 :            : 
     241                 :          0 :         if (vsec_rev != ESE_GZ_VSEC_VER_XIL_CFGBAR ||
     242         [ #  # ]:          0 :             vsec_len < ESE_GZ_VSEC_LEN_MIN) {
     243                 :            :                 rc = EINVAL;
     244                 :          0 :                 goto fail5;
     245                 :            :         }
     246                 :            : 
     247                 :          0 :         rc = epop->epo_config_readd(espcp, vsec_offset +
     248                 :            :                                (EFX_LOW_BIT(ESF_GZ_VSEC_TBL_BAR) / 8),
     249                 :            :                                &vsec.eo_dword[1]);
     250         [ #  # ]:          0 :         if (rc != 0) {
     251                 :            :                 rc = EIO;
     252                 :          0 :                 goto fail6;
     253                 :            :         }
     254                 :            : 
     255                 :          0 :         bar = EFX_OWORD_FIELD32(vsec, ESF_GZ_VSEC_TBL_BAR);
     256                 :            :         offset_low = EFX_OWORD_FIELD32(vsec, ESF_GZ_VSEC_TBL_OFF_LO);
     257                 :            : 
     258         [ #  # ]:          0 :         if (vsec_len >= ESE_GZ_VSEC_LEN_HIGH_OFFT) {
     259                 :          0 :                 rc = epop->epo_config_readd(espcp, vsec_offset +
     260                 :            :                                 (EFX_LOW_BIT(ESF_GZ_VSEC_TBL_OFF_HI) / 8),
     261                 :            :                                 &vsec.eo_dword[2]);
     262         [ #  # ]:          0 :                 if (rc != 0) {
     263                 :            :                         rc = EIO;
     264                 :          0 :                         goto fail7;
     265                 :            :                 }
     266                 :            : 
     267                 :          0 :                 offset_high = EFX_OWORD_FIELD32(vsec, ESF_GZ_VSEC_TBL_OFF_HI);
     268                 :            :         }
     269                 :            : 
     270                 :            :         /* High bits of low offset are discarded by the shift */
     271                 :          0 :         offset = offset_low << ESE_GZ_VSEC_TBL_OFF_LO_BYTES_SHIFT;
     272                 :            : 
     273                 :            :         /*
     274                 :            :          * Avoid the 'left shift count >= width of type' warning on systems
     275                 :            :          * without uint64_t support.
     276                 :            :          */
     277                 :            : #if EFSYS_HAS_UINT64
     278                 :          0 :         offset |= (uint64_t)offset_high << ESE_GZ_VSEC_TBL_OFF_HI_BYTES_SHIFT;
     279                 :            : #else
     280                 :            :         _NOTE(ARGUNUSED(offset_high))
     281                 :            : #endif
     282                 :            : 
     283                 :          0 :         *offsetp = offset;
     284                 :          0 :         *barp = bar;
     285                 :            : 
     286                 :          0 :         return (0);
     287                 :            : 
     288                 :            : fail7:
     289                 :            :         EFSYS_PROBE(fail7);
     290                 :            : fail6:
     291                 :            :         EFSYS_PROBE(fail6);
     292                 :            : fail5:
     293                 :            :         EFSYS_PROBE(fail5);
     294                 :            : fail4:
     295                 :            :         EFSYS_PROBE(fail4);
     296                 :            : fail3:
     297                 :            :         EFSYS_PROBE(fail3);
     298                 :            : fail2:
     299                 :            :         EFSYS_PROBE(fail2);
     300                 :            : fail1:
     301                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     302                 :            : 
     303                 :            :         return (rc);
     304                 :            : }
     305                 :            : 
     306                 :            :         __checkReturn                   efx_rc_t
     307                 :          0 : 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)
     312                 :            : {
     313                 :            :         efsys_dma_addr_t offset;
     314                 :            :         boolean_t skip = skip_first;
     315                 :            :         efx_qword_t header;
     316                 :            :         uint32_t format;
     317                 :            :         uint32_t last;
     318                 :            :         efx_rc_t rc;
     319                 :            : 
     320         [ #  # ]:          0 :         if (entry_offsetp == NULL) {
     321                 :            :                 rc = EINVAL;
     322                 :          0 :                 goto fail1;
     323                 :            :         }
     324                 :            : 
     325                 :          0 :         offset = *entry_offsetp;
     326                 :            :         rc = ENOENT;
     327                 :            :         /*
     328                 :            :          * SF-119689-TC Riverhead Host Interface section 4.2.2.
     329                 :            :          * describes the following discovery steps.
     330                 :            :          */
     331                 :            :         do {
     332                 :            :                 /*
     333                 :            :                  * Xilinx Capabilities Table requires 32bit aligned reads.
     334                 :            :                  * See SF-119689-TC section 4.2.2 "Discovery Steps".
     335                 :            :                  */
     336         [ #  # ]:          0 :                 EFSYS_BAR_READD(esbp, offset +
     337                 :            :                                 (EFX_LOW_BIT(ESF_GZ_CFGBAR_ENTRY_FORMAT) / 8),
     338                 :            :                                 &header.eq_dword[0], B_FALSE);
     339                 :          0 :                 EFSYS_BAR_READD(esbp, offset +
     340                 :            :                                 (EFX_LOW_BIT(ESF_GZ_CFGBAR_ENTRY_SIZE) / 8),
     341                 :            :                                 &header.eq_dword[1], B_FALSE);
     342                 :            : 
     343                 :          0 :                 format = EFX_QWORD_FIELD32(header, ESF_GZ_CFGBAR_ENTRY_FORMAT);
     344                 :          0 :                 last = EFX_QWORD_FIELD32(header, ESF_GZ_CFGBAR_ENTRY_LAST);
     345                 :            : 
     346         [ #  # ]:          0 :                 if (skip == B_FALSE && format == format_id) {
     347                 :          0 :                         *entry_offsetp = offset;
     348                 :            :                         rc = 0;
     349                 :          0 :                         break;
     350                 :            :                 }
     351                 :            : 
     352                 :          0 :                 offset += EFX_QWORD_FIELD32(header, ESF_GZ_CFGBAR_ENTRY_SIZE);
     353                 :            :                 skip = B_FALSE;
     354         [ #  # ]:          0 :         } while (last == B_FALSE);
     355                 :            : 
     356                 :            :         /*
     357                 :            :          * Returns 0 if found otherwise ENOENT indicating that
     358                 :            :          * search finished correctly.
     359                 :            :          */
     360                 :            :         return (rc);
     361                 :            : 
     362                 :            : fail1:
     363                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     364                 :            : 
     365                 :          0 :         return (rc);
     366                 :            : }
     367                 :            : 
     368                 :            : #endif /* EFSYS_OPT_PCI */

Generated by: LCOV version 1.14