LCOV - code coverage report
Current view: top level - drivers/common/sfc_efx/base - efx_tunnel.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 190 0.0 %
Date: 2024-04-01 19:00:53 Functions: 0 12 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 126 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) 2007-2019 Solarflare Communications Inc.
       5                 :            :  */
       6                 :            : 
       7                 :            : #include "efx.h"
       8                 :            : #include "efx_impl.h"
       9                 :            : 
      10                 :            : /*
      11                 :            :  * State diagram of the UDP tunnel table entries
      12                 :            :  * (efx_tunnel_udp_entry_state_t and busy flag):
      13                 :            :  *
      14                 :            :  *                             +---------+
      15                 :            :  *                    +--------| APPLIED |<-------+
      16                 :            :  *                    |        +---------+        |
      17                 :            :  *                    |                           |
      18                 :            :  *                    |                efx_tunnel_reconfigure (end)
      19                 :            :  *   efx_tunnel_config_udp_remove                 |
      20                 :            :  *                    |                    +------------+
      21                 :            :  *                    v                    | BUSY ADDED |
      22                 :            :  *               +---------+               +------------+
      23                 :            :  *               | REMOVED |                      ^
      24                 :            :  *               +---------+                      |
      25                 :            :  *                    |               efx_tunnel_reconfigure (begin)
      26                 :            :  *  efx_tunnel_reconfigure (begin)                |
      27                 :            :  *                    |                           |
      28                 :            :  *                    v                     +-----------+
      29                 :            :  *            +--------------+              |   ADDED   |<---------+
      30                 :            :  *            | BUSY REMOVED |              +-----------+          |
      31                 :            :  *            +--------------+                    |                |
      32                 :            :  *                    |              efx_tunnel_config_udp_remove  |
      33                 :            :  *  efx_tunnel_reconfigure (end)                  |                |
      34                 :            :  *                    |                           |                |
      35                 :            :  *                    |        +---------+        |                |
      36                 :            :  *                    |        |+-------+|        |                |
      37                 :            :  *                    +------->|| empty ||<-------+                |
      38                 :            :  *                             |+-------+|                         |
      39                 :            :  *                             +---------+        efx_tunnel_config_udp_add
      40                 :            :  *                                  |                              |
      41                 :            :  *                                  +------------------------------+
      42                 :            :  *
      43                 :            :  * Note that there is no BUSY APPLIED state since removing an applied entry
      44                 :            :  * should not be blocked by ongoing reconfiguration in another thread -
      45                 :            :  * reconfiguration will remove only busy entries.
      46                 :            :  */
      47                 :            : 
      48                 :            : #if EFSYS_OPT_TUNNEL
      49                 :            : 
      50                 :            : #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
      51                 :            : static  __checkReturn   boolean_t
      52                 :            : ef10_udp_encap_supported(
      53                 :            :         __in            efx_nic_t *enp);
      54                 :            : 
      55                 :            : static  __checkReturn   efx_rc_t
      56                 :            : ef10_tunnel_reconfigure(
      57                 :            :         __in            efx_nic_t *enp);
      58                 :            : 
      59                 :            : static                  void
      60                 :            : ef10_tunnel_fini(
      61                 :            :         __in            efx_nic_t *enp);
      62                 :            : #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
      63                 :            : 
      64                 :            : #if EFSYS_OPT_SIENA || EFSYS_OPT_HUNTINGTON
      65                 :            : static const efx_tunnel_ops_t   __efx_tunnel_dummy_ops = {
      66                 :            :         NULL,   /* eto_reconfigure */
      67                 :            :         NULL,   /* eto_fini */
      68                 :            : };
      69                 :            : #endif /* EFSYS_OPT_SIENA || EFSYS_OPT_HUNTINGTON */
      70                 :            : 
      71                 :            : #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
      72                 :            : static const efx_tunnel_ops_t   __efx_tunnel_ef10_ops = {
      73                 :            :         ef10_tunnel_reconfigure,        /* eto_reconfigure */
      74                 :            :         ef10_tunnel_fini,               /* eto_fini */
      75                 :            : };
      76                 :            : #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
      77                 :            : 
      78                 :            : #if EFSYS_OPT_RIVERHEAD
      79                 :            : static const efx_tunnel_ops_t   __efx_tunnel_rhead_ops = {
      80                 :            :         rhead_tunnel_reconfigure,       /* eto_reconfigure */
      81                 :            :         rhead_tunnel_fini,              /* eto_fini */
      82                 :            : };
      83                 :            : #endif /* EFSYS_OPT_RIVERHEAD */
      84                 :            : 
      85                 :            : /* Indicates that an entry is to be set */
      86                 :            : static  __checkReturn           boolean_t
      87                 :          0 : ef10_entry_staged(
      88                 :            :         __in                    efx_tunnel_udp_entry_t *entry)
      89                 :            : {
      90   [ #  #  #  # ]:          0 :         switch (entry->etue_state) {
      91                 :          0 :         case EFX_TUNNEL_UDP_ENTRY_ADDED:
      92                 :          0 :                 return (entry->etue_busy);
      93                 :          0 :         case EFX_TUNNEL_UDP_ENTRY_REMOVED:
      94                 :          0 :                 return (!entry->etue_busy);
      95                 :            :         case EFX_TUNNEL_UDP_ENTRY_APPLIED:
      96                 :            :                 return (B_TRUE);
      97                 :            :         default:
      98                 :          0 :                 EFSYS_ASSERT(0);
      99                 :            :                 return (B_FALSE);
     100                 :            :         }
     101                 :            : }
     102                 :            : 
     103                 :            : static  __checkReturn           efx_rc_t
     104                 :          0 : efx_mcdi_set_tunnel_encap_udp_ports(
     105                 :            :         __in                    efx_nic_t *enp,
     106                 :            :         __in                    efx_tunnel_cfg_t *etcp,
     107                 :            :         __in                    boolean_t unloading,
     108                 :            :         __out                   boolean_t *resetting)
     109                 :            : {
     110                 :            :         efx_mcdi_req_t req;
     111                 :          0 :         EFX_MCDI_DECLARE_BUF(payload,
     112                 :            :                 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LENMAX,
     113                 :            :                 MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN);
     114                 :            :         efx_word_t flags;
     115                 :            :         efx_rc_t rc;
     116                 :            :         unsigned int i;
     117                 :            :         unsigned int entries_num;
     118                 :            :         unsigned int entry;
     119                 :            : 
     120                 :            :         entries_num = 0;
     121         [ #  # ]:          0 :         if (etcp != NULL) {
     122         [ #  # ]:          0 :                 for (i = 0; i < etcp->etc_udp_entries_num; i++) {
     123         [ #  # ]:          0 :                         if (ef10_entry_staged(&etcp->etc_udp_entries[i]) !=
     124                 :            :                             B_FALSE) {
     125                 :          0 :                                 entries_num++;
     126                 :            :                         }
     127                 :            :                 }
     128                 :            :         }
     129                 :            : 
     130                 :          0 :         req.emr_cmd = MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS;
     131                 :          0 :         req.emr_in_buf = payload;
     132                 :          0 :         req.emr_in_length =
     133                 :          0 :             MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_LEN(entries_num);
     134                 :          0 :         req.emr_out_buf = payload;
     135                 :          0 :         req.emr_out_length = MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN;
     136                 :            : 
     137                 :          0 :         EFX_POPULATE_WORD_1(flags,
     138                 :            :             MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_UNLOADING,
     139                 :            :             (unloading == B_TRUE) ? 1 : 0);
     140                 :          0 :         MCDI_IN_SET_WORD(req, SET_TUNNEL_ENCAP_UDP_PORTS_IN_FLAGS,
     141                 :            :             EFX_WORD_FIELD(flags, EFX_WORD_0));
     142                 :            : 
     143                 :          0 :         MCDI_IN_SET_WORD(req, SET_TUNNEL_ENCAP_UDP_PORTS_IN_NUM_ENTRIES,
     144                 :            :             entries_num);
     145                 :            : 
     146         [ #  # ]:          0 :         for (i = 0, entry = 0; entry < entries_num; ++entry, ++i) {
     147                 :            :                 uint16_t mcdi_udp_protocol;
     148                 :            : 
     149         [ #  # ]:          0 :                 while (ef10_entry_staged(&etcp->etc_udp_entries[i]) == B_FALSE)
     150                 :          0 :                         i++;
     151                 :            : 
     152      [ #  #  # ]:          0 :                 switch (etcp->etc_udp_entries[i].etue_protocol) {
     153                 :            :                 case EFX_TUNNEL_PROTOCOL_VXLAN:
     154                 :            :                         mcdi_udp_protocol = TUNNEL_ENCAP_UDP_PORT_ENTRY_VXLAN;
     155                 :            :                         break;
     156                 :          0 :                 case EFX_TUNNEL_PROTOCOL_GENEVE:
     157                 :            :                         mcdi_udp_protocol = TUNNEL_ENCAP_UDP_PORT_ENTRY_GENEVE;
     158                 :          0 :                         break;
     159                 :          0 :                 default:
     160                 :            :                         rc = EINVAL;
     161                 :          0 :                         goto fail1;
     162                 :            :                 }
     163                 :            : 
     164                 :            :                 /*
     165                 :            :                  * UDP port is MCDI native little-endian in the request
     166                 :            :                  * and EFX_POPULATE_DWORD cares about conversion from
     167                 :            :                  * host/CPU byte order to little-endian.
     168                 :            :                  */
     169                 :            :                 EFX_STATIC_ASSERT(sizeof (efx_dword_t) ==
     170                 :            :                     TUNNEL_ENCAP_UDP_PORT_ENTRY_LEN);
     171                 :          0 :                 EFX_POPULATE_DWORD_2(
     172                 :            :                     MCDI_IN2(req, efx_dword_t,
     173                 :            :                         SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES)[entry],
     174                 :            :                     TUNNEL_ENCAP_UDP_PORT_ENTRY_UDP_PORT,
     175                 :            :                     etcp->etc_udp_entries[i].etue_port,
     176                 :            :                     TUNNEL_ENCAP_UDP_PORT_ENTRY_PROTOCOL,
     177                 :            :                     mcdi_udp_protocol);
     178                 :            :         }
     179                 :            : 
     180                 :          0 :         efx_mcdi_execute(enp, &req);
     181                 :            : 
     182         [ #  # ]:          0 :         if (req.emr_rc != 0) {
     183                 :            :                 rc = req.emr_rc;
     184                 :          0 :                 goto fail2;
     185                 :            :         }
     186                 :            : 
     187         [ #  # ]:          0 :         if (req.emr_out_length_used !=
     188                 :            :             MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_OUT_LEN) {
     189                 :            :                 rc = EMSGSIZE;
     190                 :          0 :                 goto fail3;
     191                 :            :         }
     192                 :            : 
     193                 :          0 :         *resetting = MCDI_OUT_WORD_FIELD(req,
     194                 :            :             SET_TUNNEL_ENCAP_UDP_PORTS_OUT_FLAGS,
     195                 :            :             SET_TUNNEL_ENCAP_UDP_PORTS_OUT_RESETTING);
     196                 :            : 
     197                 :          0 :         return (0);
     198                 :            : 
     199                 :            : fail3:
     200                 :            :         EFSYS_PROBE(fail3);
     201                 :            : 
     202                 :            : fail2:
     203                 :            :         EFSYS_PROBE(fail2);
     204                 :            : 
     205                 :            : fail1:
     206                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     207                 :            : 
     208                 :            :         return (rc);
     209                 :            : }
     210                 :            : 
     211                 :            :         __checkReturn   efx_rc_t
     212                 :          0 : efx_tunnel_init(
     213                 :            :         __in            efx_nic_t *enp)
     214                 :            : {
     215                 :            :         efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
     216                 :            :         const efx_tunnel_ops_t *etop;
     217                 :            :         efx_rc_t rc;
     218                 :            : 
     219         [ #  # ]:          0 :         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
     220         [ #  # ]:          0 :         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
     221         [ #  # ]:          0 :         EFSYS_ASSERT(!(enp->en_mod_flags & EFX_MOD_TUNNEL));
     222                 :            : 
     223                 :            :         EFX_STATIC_ASSERT(EFX_TUNNEL_MAXNENTRIES ==
     224                 :            :             MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS_IN_ENTRIES_MAXNUM);
     225                 :            : 
     226   [ #  #  #  #  :          0 :         switch (enp->en_family) {
                      # ]
     227                 :            : #if EFSYS_OPT_SIENA
     228                 :            :         case EFX_FAMILY_SIENA:
     229                 :            :                 etop = &__efx_tunnel_dummy_ops;
     230                 :            :                 break;
     231                 :            : #endif /* EFSYS_OPT_SIENA */
     232                 :            : 
     233                 :            : #if EFSYS_OPT_HUNTINGTON
     234                 :            :         case EFX_FAMILY_HUNTINGTON:
     235                 :            :                 etop = &__efx_tunnel_dummy_ops;
     236                 :            :                 break;
     237                 :            : #endif /* EFSYS_OPT_HUNTINGTON */
     238                 :            : 
     239                 :            : #if EFSYS_OPT_MEDFORD
     240                 :          0 :         case EFX_FAMILY_MEDFORD:
     241                 :            :                 etop = &__efx_tunnel_ef10_ops;
     242                 :          0 :                 break;
     243                 :            : #endif /* EFSYS_OPT_MEDFORD */
     244                 :            : 
     245                 :            : #if EFSYS_OPT_MEDFORD2
     246                 :          0 :         case EFX_FAMILY_MEDFORD2:
     247                 :            :                 etop = &__efx_tunnel_ef10_ops;
     248                 :          0 :                 break;
     249                 :            : #endif /* EFSYS_OPT_MEDFORD2 */
     250                 :            : 
     251                 :            : #if EFSYS_OPT_RIVERHEAD
     252                 :          0 :         case EFX_FAMILY_RIVERHEAD:
     253                 :            :                 etop = &__efx_tunnel_rhead_ops;
     254                 :          0 :                 break;
     255                 :            : #endif /* EFSYS_OPT_RIVERHEAD */
     256                 :            : 
     257                 :            :         default:
     258                 :          0 :                 EFSYS_ASSERT(0);
     259                 :            :                 rc = ENOTSUP;
     260                 :            :                 goto fail1;
     261                 :            :         }
     262                 :            : 
     263                 :          0 :         memset(etcp->etc_udp_entries, 0, sizeof (etcp->etc_udp_entries));
     264                 :          0 :         etcp->etc_udp_entries_num = 0;
     265                 :            : 
     266                 :          0 :         enp->en_etop = etop;
     267                 :          0 :         enp->en_mod_flags |= EFX_MOD_TUNNEL;
     268                 :            : 
     269                 :            :         return (0);
     270                 :            : 
     271                 :            : fail1:
     272                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     273                 :            : 
     274                 :            :         enp->en_etop = NULL;
     275                 :            :         enp->en_mod_flags &= ~EFX_MOD_TUNNEL;
     276                 :            : 
     277                 :            :         return (rc);
     278                 :            : }
     279                 :            : 
     280                 :            :                         void
     281                 :          0 : efx_tunnel_fini(
     282                 :            :         __in            efx_nic_t *enp)
     283                 :            : {
     284         [ #  # ]:          0 :         EFSYS_ASSERT3U(enp->en_magic, ==, EFX_NIC_MAGIC);
     285         [ #  # ]:          0 :         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_PROBE);
     286         [ #  # ]:          0 :         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
     287                 :            : 
     288         [ #  # ]:          0 :         if (enp->en_etop->eto_fini != NULL)
     289                 :          0 :                 enp->en_etop->eto_fini(enp);
     290                 :            : 
     291                 :          0 :         enp->en_etop = NULL;
     292                 :          0 :         enp->en_mod_flags &= ~EFX_MOD_TUNNEL;
     293                 :          0 : }
     294                 :            : 
     295                 :            : static  __checkReturn   efx_rc_t
     296                 :            : efx_tunnel_config_find_udp_tunnel_entry(
     297                 :            :         __in            efx_tunnel_cfg_t *etcp,
     298                 :            :         __in            uint16_t port,
     299                 :            :         __out           unsigned int *entryp)
     300                 :            : {
     301                 :            :         unsigned int i;
     302                 :            : 
     303   [ #  #  #  # ]:          0 :         for (i = 0; i < etcp->etc_udp_entries_num; ++i) {
     304                 :            :                 efx_tunnel_udp_entry_t *p = &etcp->etc_udp_entries[i];
     305                 :            : 
     306   [ #  #  #  # ]:          0 :                 if (p->etue_port == port &&
     307   [ #  #  #  # ]:          0 :                     p->etue_state != EFX_TUNNEL_UDP_ENTRY_REMOVED) {
     308                 :            :                         *entryp = i;
     309                 :            :                         return (0);
     310                 :            :                 }
     311                 :            :         }
     312                 :            : 
     313                 :            :         return (ENOENT);
     314                 :            : }
     315                 :            : 
     316                 :            :         __checkReturn   efx_rc_t
     317                 :          0 : efx_tunnel_config_udp_add(
     318                 :            :         __in            efx_nic_t *enp,
     319                 :            :         __in            uint16_t port /* host/cpu-endian */,
     320                 :            :         __in            efx_tunnel_protocol_t protocol)
     321                 :            : {
     322                 :            :         const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
     323                 :            :         efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
     324                 :            :         efsys_lock_state_t state;
     325                 :            :         efx_rc_t rc;
     326                 :            :         unsigned int entry;
     327                 :            : 
     328         [ #  # ]:          0 :         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
     329                 :            : 
     330         [ #  # ]:          0 :         if (protocol >= EFX_TUNNEL_NPROTOS) {
     331                 :            :                 rc = EINVAL;
     332                 :          0 :                 goto fail1;
     333                 :            :         }
     334                 :            : 
     335                 :          0 :         if ((encp->enc_tunnel_encapsulations_supported &
     336         [ #  # ]:          0 :             (1u << protocol)) == 0) {
     337                 :            :                 rc = ENOTSUP;
     338                 :          0 :                 goto fail2;
     339                 :            :         }
     340                 :            : 
     341                 :          0 :         EFSYS_LOCK(enp->en_eslp, state);
     342                 :            : 
     343                 :            :         rc = efx_tunnel_config_find_udp_tunnel_entry(etcp, port, &entry);
     344                 :            :         if (rc == 0) {
     345                 :            :                 rc = EEXIST;
     346                 :          0 :                 goto fail3;
     347                 :            :         }
     348                 :            : 
     349                 :          0 :         if (etcp->etc_udp_entries_num ==
     350         [ #  # ]:          0 :             encp->enc_tunnel_config_udp_entries_max) {
     351                 :            :                 rc = ENOSPC;
     352                 :          0 :                 goto fail4;
     353                 :            :         }
     354                 :            : 
     355                 :          0 :         etcp->etc_udp_entries[etcp->etc_udp_entries_num].etue_port = port;
     356                 :          0 :         etcp->etc_udp_entries[etcp->etc_udp_entries_num].etue_protocol =
     357                 :            :             protocol;
     358                 :          0 :         etcp->etc_udp_entries[etcp->etc_udp_entries_num].etue_state =
     359                 :            :             EFX_TUNNEL_UDP_ENTRY_ADDED;
     360                 :            : 
     361                 :          0 :         etcp->etc_udp_entries_num++;
     362                 :            : 
     363                 :          0 :         EFSYS_UNLOCK(enp->en_eslp, state);
     364                 :            : 
     365                 :          0 :         return (0);
     366                 :            : 
     367                 :            : fail4:
     368                 :            :         EFSYS_PROBE(fail4);
     369                 :            : 
     370                 :          0 : fail3:
     371                 :            :         EFSYS_PROBE(fail3);
     372                 :          0 :         EFSYS_UNLOCK(enp->en_eslp, state);
     373                 :            : 
     374                 :            : fail2:
     375                 :            :         EFSYS_PROBE(fail2);
     376                 :            : 
     377                 :            : fail1:
     378                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     379                 :            : 
     380                 :            :         return (rc);
     381                 :            : }
     382                 :            : 
     383                 :            : /*
     384                 :            :  * Returns the index of the entry after the deleted one,
     385                 :            :  * or one past the last entry.
     386                 :            :  */
     387                 :            : static                  unsigned int
     388                 :          0 : efx_tunnel_config_udp_do_remove(
     389                 :            :         __in            efx_tunnel_cfg_t *etcp,
     390                 :            :         __in            unsigned int entry)
     391                 :            : {
     392         [ #  # ]:          0 :         EFSYS_ASSERT3U(etcp->etc_udp_entries_num, >, 0);
     393                 :          0 :         etcp->etc_udp_entries_num--;
     394                 :            : 
     395         [ #  # ]:          0 :         if (entry < etcp->etc_udp_entries_num) {
     396                 :          0 :                 memmove(&etcp->etc_udp_entries[entry],
     397                 :          0 :                     &etcp->etc_udp_entries[entry + 1],
     398                 :          0 :                     (etcp->etc_udp_entries_num - entry) *
     399                 :            :                     sizeof (etcp->etc_udp_entries[0]));
     400                 :            :         }
     401                 :            : 
     402                 :          0 :         memset(&etcp->etc_udp_entries[etcp->etc_udp_entries_num], 0,
     403                 :            :             sizeof (etcp->etc_udp_entries[0]));
     404                 :            : 
     405                 :          0 :         return (entry);
     406                 :            : }
     407                 :            : 
     408                 :            : /*
     409                 :            :  * Returns the index of the entry after the specified one,
     410                 :            :  * or one past the last entry. The index is correct whether
     411                 :            :  * the specified entry was removed or not.
     412                 :            :  */
     413                 :            : static                  unsigned int
     414                 :          0 : efx_tunnel_config_udp_remove_prepare(
     415                 :            :         __in            efx_tunnel_cfg_t *etcp,
     416                 :            :         __in            unsigned int entry)
     417                 :            : {
     418                 :          0 :         unsigned int next = entry + 1;
     419                 :            : 
     420   [ #  #  #  # ]:          0 :         switch (etcp->etc_udp_entries[entry].etue_state) {
     421                 :          0 :         case EFX_TUNNEL_UDP_ENTRY_ADDED:
     422                 :          0 :                 next = efx_tunnel_config_udp_do_remove(etcp, entry);
     423                 :          0 :                 break;
     424                 :            :         case EFX_TUNNEL_UDP_ENTRY_REMOVED:
     425                 :            :                 break;
     426                 :          0 :         case EFX_TUNNEL_UDP_ENTRY_APPLIED:
     427                 :          0 :                 etcp->etc_udp_entries[entry].etue_state =
     428                 :            :                     EFX_TUNNEL_UDP_ENTRY_REMOVED;
     429                 :          0 :                 break;
     430                 :            :         default:
     431                 :          0 :                 EFSYS_ASSERT(0);
     432                 :            :                 break;
     433                 :            :         }
     434                 :            : 
     435                 :          0 :         return (next);
     436                 :            : }
     437                 :            : 
     438                 :            :         __checkReturn   efx_rc_t
     439                 :          0 : efx_tunnel_config_udp_remove(
     440                 :            :         __in            efx_nic_t *enp,
     441                 :            :         __in            uint16_t port /* host/cpu-endian */,
     442                 :            :         __in            efx_tunnel_protocol_t protocol)
     443                 :            : {
     444                 :          0 :         efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
     445                 :            :         efsys_lock_state_t state;
     446                 :            :         unsigned int entry;
     447                 :            :         efx_rc_t rc;
     448                 :            : 
     449         [ #  # ]:          0 :         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
     450                 :            : 
     451                 :          0 :         EFSYS_LOCK(enp->en_eslp, state);
     452                 :            : 
     453                 :            :         rc = efx_tunnel_config_find_udp_tunnel_entry(etcp, port, &entry);
     454                 :            :         if (rc != 0)
     455                 :          0 :                 goto fail1;
     456                 :            : 
     457         [ #  # ]:          0 :         if (etcp->etc_udp_entries[entry].etue_busy != B_FALSE) {
     458                 :            :                 rc = EBUSY;
     459                 :          0 :                 goto fail2;
     460                 :            :         }
     461                 :            : 
     462         [ #  # ]:          0 :         if (etcp->etc_udp_entries[entry].etue_protocol != protocol) {
     463                 :            :                 rc = EINVAL;
     464                 :          0 :                 goto fail3;
     465                 :            :         }
     466                 :            : 
     467                 :          0 :         (void) efx_tunnel_config_udp_remove_prepare(etcp, entry);
     468                 :            : 
     469                 :          0 :         EFSYS_UNLOCK(enp->en_eslp, state);
     470                 :            : 
     471                 :          0 :         return (0);
     472                 :            : 
     473                 :            : fail3:
     474                 :            :         EFSYS_PROBE(fail3);
     475                 :            : 
     476                 :          0 : fail2:
     477                 :            :         EFSYS_PROBE(fail2);
     478                 :            : 
     479                 :          0 : fail1:
     480                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     481                 :          0 :         EFSYS_UNLOCK(enp->en_eslp, state);
     482                 :            : 
     483                 :          0 :         return (rc);
     484                 :            : }
     485                 :            : 
     486                 :            : static                  boolean_t
     487                 :            : efx_tunnel_table_all_available(
     488                 :            :         __in                    efx_tunnel_cfg_t *etcp)
     489                 :            : {
     490                 :            :         unsigned int i;
     491                 :            : 
     492   [ #  #  #  # ]:          0 :         for (i = 0; i < etcp->etc_udp_entries_num; i++) {
     493   [ #  #  #  # ]:          0 :                 if (etcp->etc_udp_entries[i].etue_busy != B_FALSE)
     494                 :            :                         return (B_FALSE);
     495                 :            :         }
     496                 :            : 
     497                 :            :         return (B_TRUE);
     498                 :            : }
     499                 :            : 
     500                 :            :         __checkReturn   efx_rc_t
     501                 :          0 : efx_tunnel_config_clear(
     502                 :            :         __in                    efx_nic_t *enp)
     503                 :            : {
     504                 :          0 :         efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
     505                 :            :         efsys_lock_state_t state;
     506                 :            :         unsigned int i;
     507                 :            :         efx_rc_t rc;
     508                 :            : 
     509         [ #  # ]:          0 :         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
     510                 :            : 
     511                 :          0 :         EFSYS_LOCK(enp->en_eslp, state);
     512                 :            : 
     513         [ #  # ]:          0 :         if (efx_tunnel_table_all_available(etcp) == B_FALSE) {
     514                 :            :                 rc = EBUSY;
     515                 :          0 :                 goto fail1;
     516                 :            :         }
     517                 :            : 
     518                 :            :         i = 0;
     519         [ #  # ]:          0 :         while (i < etcp->etc_udp_entries_num)
     520                 :          0 :                 i = efx_tunnel_config_udp_remove_prepare(etcp, i);
     521                 :            : 
     522                 :          0 :         EFSYS_UNLOCK(enp->en_eslp, state);
     523                 :            : 
     524                 :          0 :         return (0);
     525                 :            : 
     526                 :            : fail1:
     527                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     528                 :          0 :         EFSYS_UNLOCK(enp->en_eslp, state);
     529                 :            : 
     530                 :          0 :         return (rc);
     531                 :            : }
     532                 :            : 
     533                 :            :         __checkReturn   efx_rc_t
     534                 :          0 : efx_tunnel_reconfigure(
     535                 :            :         __in            efx_nic_t *enp)
     536                 :            : {
     537                 :          0 :         const efx_tunnel_ops_t *etop = enp->en_etop;
     538                 :          0 :         efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
     539                 :            :         efx_tunnel_udp_entry_t *entry;
     540                 :            :         boolean_t locked = B_FALSE;
     541                 :            :         efsys_lock_state_t state;
     542                 :            :         boolean_t resetting;
     543                 :            :         unsigned int i;
     544                 :            :         efx_rc_t rc;
     545                 :            : 
     546         [ #  # ]:          0 :         EFSYS_ASSERT3U(enp->en_mod_flags, &, EFX_MOD_TUNNEL);
     547                 :            : 
     548         [ #  # ]:          0 :         if (etop->eto_reconfigure == NULL) {
     549                 :            :                 rc = ENOTSUP;
     550                 :          0 :                 goto fail1;
     551                 :            :         }
     552                 :            : 
     553                 :          0 :         EFSYS_LOCK(enp->en_eslp, state);
     554                 :            :         locked = B_TRUE;
     555                 :            : 
     556         [ #  # ]:          0 :         if (efx_tunnel_table_all_available(etcp) == B_FALSE) {
     557                 :            :                 rc = EBUSY;
     558                 :          0 :                 goto fail2;
     559                 :            :         }
     560                 :            : 
     561         [ #  # ]:          0 :         for (i = 0; i < etcp->etc_udp_entries_num; i++) {
     562                 :            :                 entry = &etcp->etc_udp_entries[i];
     563         [ #  # ]:          0 :                 if (entry->etue_state != EFX_TUNNEL_UDP_ENTRY_APPLIED)
     564                 :          0 :                         entry->etue_busy = B_TRUE;
     565                 :            :         }
     566                 :            : 
     567                 :          0 :         EFSYS_UNLOCK(enp->en_eslp, state);
     568                 :            :         locked = B_FALSE;
     569                 :            : 
     570                 :          0 :         rc = enp->en_etop->eto_reconfigure(enp);
     571         [ #  # ]:          0 :         if (rc != 0 && rc != EAGAIN)
     572                 :          0 :                 goto fail3;
     573                 :            : 
     574                 :            :         resetting = (rc == EAGAIN) ? B_TRUE : B_FALSE;
     575                 :            : 
     576                 :          0 :         EFSYS_LOCK(enp->en_eslp, state);
     577                 :            :         locked = B_TRUE;
     578                 :            : 
     579                 :            :         /*
     580                 :            :          * Delete entries marked for removal since they are no longer
     581                 :            :          * needed after successful NIC-specific reconfiguration.
     582                 :            :          * Added entries become applied because they are installed in
     583                 :            :          * the hardware.
     584                 :            :          */
     585                 :            : 
     586                 :            :         i = 0;
     587         [ #  # ]:          0 :         while (i < etcp->etc_udp_entries_num) {
     588                 :          0 :                 unsigned int next = i + 1;
     589                 :            : 
     590                 :            :                 entry = &etcp->etc_udp_entries[i];
     591         [ #  # ]:          0 :                 if (entry->etue_busy != B_FALSE) {
     592                 :          0 :                         entry->etue_busy = B_FALSE;
     593                 :            : 
     594   [ #  #  #  # ]:          0 :                         switch (entry->etue_state) {
     595                 :            :                         case EFX_TUNNEL_UDP_ENTRY_APPLIED:
     596                 :            :                                 break;
     597                 :          0 :                         case EFX_TUNNEL_UDP_ENTRY_ADDED:
     598                 :          0 :                                 entry->etue_state =
     599                 :            :                                     EFX_TUNNEL_UDP_ENTRY_APPLIED;
     600                 :          0 :                                 break;
     601                 :          0 :                         case EFX_TUNNEL_UDP_ENTRY_REMOVED:
     602                 :          0 :                                 next = efx_tunnel_config_udp_do_remove(etcp, i);
     603                 :          0 :                                 break;
     604                 :            :                         default:
     605                 :          0 :                                 EFSYS_ASSERT(0);
     606                 :            :                                 break;
     607                 :            :                         }
     608                 :            :                 }
     609                 :            : 
     610                 :            :                 i = next;
     611                 :            :         }
     612                 :            : 
     613                 :          0 :         EFSYS_UNLOCK(enp->en_eslp, state);
     614                 :            :         locked = B_FALSE;
     615                 :            : 
     616         [ #  # ]:          0 :         return ((resetting == B_FALSE) ? 0 : EAGAIN);
     617                 :            : 
     618                 :            : fail3:
     619                 :            :         EFSYS_PROBE(fail3);
     620                 :            : 
     621                 :            :         EFSYS_ASSERT(locked == B_FALSE);
     622                 :          0 :         EFSYS_LOCK(enp->en_eslp, state);
     623                 :            : 
     624         [ #  # ]:          0 :         for (i = 0; i < etcp->etc_udp_entries_num; i++)
     625                 :          0 :                 etcp->etc_udp_entries[i].etue_busy = B_FALSE;
     626                 :            : 
     627                 :          0 :         EFSYS_UNLOCK(enp->en_eslp, state);
     628                 :            : 
     629                 :            : fail2:
     630                 :            :         EFSYS_PROBE(fail2);
     631                 :            : 
     632                 :            : fail1:
     633                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     634                 :            :         if (locked)
     635                 :          0 :                 EFSYS_UNLOCK(enp->en_eslp, state);
     636                 :            : 
     637                 :            :         return (rc);
     638                 :            : }
     639                 :            : 
     640                 :            : #if EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2
     641                 :            : static  __checkReturn           boolean_t
     642                 :            : ef10_udp_encap_supported(
     643                 :            :         __in            efx_nic_t *enp)
     644                 :            : {
     645                 :            :         const efx_nic_cfg_t *encp = &enp->en_nic_cfg;
     646                 :            :         uint32_t udp_tunnels_mask = 0;
     647                 :            : 
     648                 :            :         udp_tunnels_mask |= (1u << EFX_TUNNEL_PROTOCOL_VXLAN);
     649                 :            :         udp_tunnels_mask |= (1u << EFX_TUNNEL_PROTOCOL_GENEVE);
     650                 :            : 
     651                 :          0 :         return ((encp->enc_tunnel_encapsulations_supported &
     652                 :            :             udp_tunnels_mask) == 0 ? B_FALSE : B_TRUE);
     653                 :            : }
     654                 :            : 
     655                 :            : static  __checkReturn   efx_rc_t
     656                 :          0 : ef10_tunnel_reconfigure(
     657                 :            :         __in            efx_nic_t *enp)
     658                 :            : {
     659                 :          0 :         efx_tunnel_cfg_t *etcp = &enp->en_tunnel_cfg;
     660                 :            :         efx_rc_t rc;
     661                 :          0 :         boolean_t resetting = B_FALSE;
     662                 :            :         efsys_lock_state_t state;
     663                 :            :         efx_tunnel_cfg_t etc;
     664                 :            : 
     665                 :          0 :         EFSYS_LOCK(enp->en_eslp, state);
     666                 :            :         memcpy(&etc, etcp, sizeof (etc));
     667                 :          0 :         EFSYS_UNLOCK(enp->en_eslp, state);
     668                 :            : 
     669         [ #  # ]:          0 :         if (ef10_udp_encap_supported(enp) == B_FALSE) {
     670                 :            :                 /*
     671                 :            :                  * It is OK to apply empty UDP tunnel ports when UDP
     672                 :            :                  * tunnel encapsulations are not supported - just nothing
     673                 :            :                  * should be done.
     674                 :            :                  */
     675         [ #  # ]:          0 :                 if (etc.etc_udp_entries_num == 0)
     676                 :            :                         return (0);
     677                 :            :                 rc = ENOTSUP;
     678                 :          0 :                 goto fail1;
     679                 :            :         } else {
     680                 :            :                 /*
     681                 :            :                  * All PCI functions can see a reset upon the
     682                 :            :                  * MCDI request completion
     683                 :            :                  */
     684                 :          0 :                 rc = efx_mcdi_set_tunnel_encap_udp_ports(enp, &etc, B_FALSE,
     685                 :            :                     &resetting);
     686         [ #  # ]:          0 :                 if (rc != 0) {
     687                 :            :                         /*
     688                 :            :                          * Do not fail if the access is denied when no
     689                 :            :                          * tunnel encap UDP ports are configured.
     690                 :            :                          */
     691   [ #  #  #  # ]:          0 :                         if (rc != EACCES || etc.etc_udp_entries_num != 0)
     692                 :          0 :                                 goto fail2;
     693                 :            :                 }
     694                 :            : 
     695                 :            :                 /*
     696                 :            :                  * Although the caller should be able to handle MC reboot,
     697                 :            :                  * it might come in handy to report the impending reboot
     698                 :            :                  * by returning EAGAIN
     699                 :            :                  */
     700         [ #  # ]:          0 :                 return ((resetting) ? EAGAIN : 0);
     701                 :            :         }
     702                 :            : fail2:
     703                 :            :         EFSYS_PROBE(fail2);
     704                 :            : 
     705                 :            : fail1:
     706                 :            :         EFSYS_PROBE1(fail1, efx_rc_t, rc);
     707                 :            : 
     708                 :            :         return (rc);
     709                 :            : }
     710                 :            : 
     711                 :            : static                  void
     712                 :          0 : ef10_tunnel_fini(
     713                 :            :         __in            efx_nic_t *enp)
     714                 :            : {
     715                 :            :         boolean_t resetting;
     716                 :            : 
     717         [ #  # ]:          0 :         if (ef10_udp_encap_supported(enp) != B_FALSE) {
     718                 :            :                 /*
     719                 :            :                  * The UNLOADING flag allows the MC to suppress the datapath
     720                 :            :                  * reset if it was set on the last call to
     721                 :            :                  * MC_CMD_SET_TUNNEL_ENCAP_UDP_PORTS by all functions
     722                 :            :                  */
     723                 :          0 :                 (void) efx_mcdi_set_tunnel_encap_udp_ports(enp, NULL, B_TRUE,
     724                 :            :                     &resetting);
     725                 :            :         }
     726                 :          0 : }
     727                 :            : #endif /* EFSYS_OPT_MEDFORD || EFSYS_OPT_MEDFORD2 */
     728                 :            : 
     729                 :            : #endif /* EFSYS_OPT_TUNNEL */

Generated by: LCOV version 1.14