LCOV - code coverage report
Current view: top level - drivers/net/cxgbe - mps_tcam.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 141 0.0 %
Date: 2025-01-02 22:41:34 Functions: 0 11 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 80 0.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2018 Chelsio Communications.
       3                 :            :  * All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "mps_tcam.h"
       7                 :            : 
       8                 :            : static inline bool
       9                 :          0 : match_entry(struct mps_tcam_entry *entry, const u8 *eth_addr, const u8 *mask)
      10                 :            : {
      11         [ #  # ]:          0 :         if (!memcmp(eth_addr, entry->eth_addr, RTE_ETHER_ADDR_LEN) &&
      12         [ #  # ]:          0 :             !memcmp(mask, entry->mask, RTE_ETHER_ADDR_LEN))
      13                 :          0 :                 return true;
      14                 :            :         return false;
      15                 :            : }
      16                 :            : 
      17                 :          0 : static int cxgbe_update_free_idx(struct mpstcam_table *t)
      18                 :            : {
      19                 :          0 :         struct mps_tcam_entry *entry = t->entry;
      20                 :          0 :         u16 i, next = t->free_idx + 1;
      21                 :            : 
      22         [ #  # ]:          0 :         if (entry[t->free_idx].state == MPS_ENTRY_UNUSED)
      23                 :            :                 /* You are already pointing to a free entry !! */
      24                 :            :                 return 0;
      25                 :            : 
      26                 :            :         /* loop, till we don't rollback to same index where we started */
      27         [ #  # ]:          0 :         for (i = next; i != t->free_idx; i++) {
      28         [ #  # ]:          0 :                 if (i == t->size)
      29                 :            :                         /* rollback and search free entry from start */
      30                 :            :                         i = 0;
      31                 :            : 
      32         [ #  # ]:          0 :                 if (entry[i].state == MPS_ENTRY_UNUSED) {
      33                 :          0 :                         t->free_idx = i;
      34                 :          0 :                         return 0;
      35                 :            :                 }
      36                 :            :         }
      37                 :            : 
      38                 :            :         return -1;      /* table is full */
      39                 :            : }
      40                 :            : 
      41                 :            : static struct mps_tcam_entry *
      42                 :          0 : cxgbe_mpstcam_lookup(struct mpstcam_table *t, const u8 *eth_addr,
      43                 :            :                      const u8 *mask)
      44                 :            : {
      45                 :          0 :         struct mps_tcam_entry *entry = t->entry;
      46                 :            :         int i;
      47                 :            : 
      48                 :            :         if (!entry)
      49                 :            :                 return NULL;
      50                 :            : 
      51         [ #  # ]:          0 :         for (i = 0; i < t->size; i++) {
      52         [ #  # ]:          0 :                 if (entry[i].state == MPS_ENTRY_UNUSED ||
      53                 :            :                     entry[i].state == MPS_ENTRY_RAWF)
      54                 :          0 :                         continue;       /* entry is not being used */
      55         [ #  # ]:          0 :                 if (match_entry(&entry[i], eth_addr, mask))
      56                 :          0 :                         return &entry[i];
      57                 :            :         }
      58                 :            : 
      59                 :            :         return NULL;
      60                 :            : }
      61                 :            : 
      62                 :          0 : int cxgbe_mpstcam_alloc(struct port_info *pi, const u8 *eth_addr,
      63                 :            :                         const u8 *mask)
      64                 :            : {
      65                 :          0 :         struct adapter *adap = pi->adapter;
      66                 :          0 :         struct mpstcam_table *mpstcam = adap->mpstcam;
      67                 :            :         struct mps_tcam_entry *entry;
      68                 :            :         int ret;
      69                 :            : 
      70         [ #  # ]:          0 :         if (!adap->mpstcam) {
      71                 :          0 :                 dev_err(adap, "mpstcam table is not available\n");
      72                 :          0 :                 return -EOPNOTSUPP;
      73                 :            :         }
      74                 :            : 
      75                 :            :         /* If entry already present, return it. */
      76                 :          0 :         t4_os_write_lock(&mpstcam->lock);
      77                 :          0 :         entry = cxgbe_mpstcam_lookup(adap->mpstcam, eth_addr, mask);
      78         [ #  # ]:          0 :         if (entry) {
      79                 :          0 :                 rte_atomic_fetch_add_explicit(&entry->refcnt, 1, rte_memory_order_relaxed);
      80                 :            :                 t4_os_write_unlock(&mpstcam->lock);
      81                 :          0 :                 return entry->idx;
      82                 :            :         }
      83                 :            : 
      84         [ #  # ]:          0 :         if (mpstcam->full) {
      85                 :            :                 t4_os_write_unlock(&mpstcam->lock);
      86                 :          0 :                 dev_err(adap, "mps-tcam table is full\n");
      87                 :          0 :                 return -ENOMEM;
      88                 :            :         }
      89                 :            : 
      90                 :          0 :         ret = t4_alloc_raw_mac_filt(adap, pi->viid, eth_addr, mask,
      91                 :          0 :                                     mpstcam->free_idx, 0, pi->port_id, false);
      92         [ #  # ]:          0 :         if (ret <= 0) {
      93                 :            :                 t4_os_write_unlock(&mpstcam->lock);
      94                 :          0 :                 return ret;
      95                 :            :         }
      96                 :            : 
      97                 :            :         /* Fill in the new values */
      98                 :            :         entry = &mpstcam->entry[ret];
      99                 :          0 :         memcpy(entry->eth_addr, eth_addr, RTE_ETHER_ADDR_LEN);
     100                 :          0 :         memcpy(entry->mask, mask, RTE_ETHER_ADDR_LEN);
     101                 :          0 :         rte_atomic_store_explicit(&entry->refcnt, 1, rte_memory_order_relaxed);
     102                 :          0 :         entry->state = MPS_ENTRY_USED;
     103                 :            : 
     104         [ #  # ]:          0 :         if (cxgbe_update_free_idx(mpstcam))
     105                 :          0 :                 mpstcam->full = true;
     106                 :            : 
     107                 :            :         t4_os_write_unlock(&mpstcam->lock);
     108                 :          0 :         return ret;
     109                 :            : }
     110                 :            : 
     111                 :          0 : int cxgbe_mpstcam_modify(struct port_info *pi, int idx, const u8 *addr)
     112                 :            : {
     113                 :          0 :         struct adapter *adap = pi->adapter;
     114                 :          0 :         struct mpstcam_table *mpstcam = adap->mpstcam;
     115                 :            :         struct mps_tcam_entry *entry;
     116                 :            : 
     117         [ #  # ]:          0 :         if (!mpstcam)
     118                 :            :                 return -EOPNOTSUPP;
     119                 :          0 :         t4_os_write_lock(&mpstcam->lock);
     120   [ #  #  #  # ]:          0 :         if (idx != -1 && idx >= mpstcam->size) {
     121                 :            :                 t4_os_write_unlock(&mpstcam->lock);
     122                 :          0 :                 return -EINVAL;
     123                 :            :         }
     124         [ #  # ]:          0 :         if (idx >= 0) {
     125                 :            :                 entry = &mpstcam->entry[idx];
     126                 :            :                 /* user wants to modify an existing entry.
     127                 :            :                  * verify if entry exists
     128                 :            :                  */
     129         [ #  # ]:          0 :                 if (entry->state != MPS_ENTRY_USED) {
     130                 :            :                         t4_os_write_unlock(&mpstcam->lock);
     131                 :          0 :                         return -EINVAL;
     132                 :            :                 }
     133                 :            :         }
     134                 :            : 
     135                 :          0 :         idx = t4_change_mac(adap, adap->mbox, pi->viid, idx, addr, true, true);
     136         [ #  # ]:          0 :         if (idx < 0) {
     137                 :            :                 t4_os_write_unlock(&mpstcam->lock);
     138                 :          0 :                 return idx;
     139                 :            :         }
     140                 :            : 
     141                 :            :         /* idx can now be different from what user provided */
     142                 :            :         entry = &mpstcam->entry[idx];
     143         [ #  # ]:          0 :         memcpy(entry->eth_addr, addr, RTE_ETHER_ADDR_LEN);
     144         [ #  # ]:          0 :         memset(entry->mask, ~0, RTE_ETHER_ADDR_LEN);
     145                 :            :         /* NOTE: we have considered the case that idx returned by t4_change_mac
     146                 :            :          * will be different from the user provided value only if user
     147                 :            :          * provided value is -1
     148                 :            :          */
     149         [ #  # ]:          0 :         if (entry->state == MPS_ENTRY_UNUSED) {
     150                 :          0 :                 rte_atomic_store_explicit(&entry->refcnt, 1, rte_memory_order_relaxed);
     151                 :          0 :                 entry->state = MPS_ENTRY_USED;
     152                 :            :         }
     153                 :            : 
     154         [ #  # ]:          0 :         if (cxgbe_update_free_idx(mpstcam))
     155                 :          0 :                 mpstcam->full = true;
     156                 :            : 
     157                 :            :         t4_os_write_unlock(&mpstcam->lock);
     158                 :          0 :         return idx;
     159                 :            : }
     160                 :            : 
     161                 :            : /**
     162                 :            :  * hold appropriate locks while calling this.
     163                 :            :  */
     164                 :          0 : static inline void reset_mpstcam_entry(struct mps_tcam_entry *entry)
     165                 :            : {
     166                 :          0 :         memset(entry->eth_addr, 0, RTE_ETHER_ADDR_LEN);
     167                 :          0 :         memset(entry->mask, 0, RTE_ETHER_ADDR_LEN);
     168                 :          0 :         rte_atomic_store_explicit(&entry->refcnt, 0, rte_memory_order_relaxed);
     169                 :          0 :         entry->state = MPS_ENTRY_UNUSED;
     170                 :          0 : }
     171                 :            : 
     172                 :            : /**
     173                 :            :  * ret < 0: fatal error
     174                 :            :  * ret = 0: entry removed in h/w
     175                 :            :  * ret > 0: updated refcount.
     176                 :            :  */
     177                 :          0 : int cxgbe_mpstcam_remove(struct port_info *pi, u16 idx)
     178                 :            : {
     179                 :          0 :         struct adapter *adap = pi->adapter;
     180                 :          0 :         struct mpstcam_table *t = adap->mpstcam;
     181                 :            :         struct mps_tcam_entry *entry;
     182                 :            :         int ret;
     183                 :            : 
     184         [ #  # ]:          0 :         if (!t)
     185                 :            :                 return -EOPNOTSUPP;
     186                 :          0 :         t4_os_write_lock(&t->lock);
     187                 :          0 :         entry = &t->entry[idx];
     188         [ #  # ]:          0 :         if (entry->state != MPS_ENTRY_USED) {
     189                 :            :                 t4_os_write_unlock(&t->lock);
     190                 :          0 :                 return -EINVAL;
     191                 :            :         }
     192                 :            : 
     193         [ #  # ]:          0 :         if (rte_atomic_load_explicit(&entry->refcnt, rte_memory_order_relaxed) == 1)
     194                 :          0 :                 ret = t4_free_raw_mac_filt(adap, pi->viid, entry->eth_addr,
     195                 :          0 :                                            entry->mask, idx, 1, pi->port_id,
     196                 :            :                                            false);
     197                 :            :         else
     198                 :          0 :                 ret = rte_atomic_fetch_sub_explicit(&entry->refcnt, 1,
     199                 :          0 :                                                     rte_memory_order_relaxed) - 1;
     200                 :            : 
     201         [ #  # ]:          0 :         if (ret == 0) {
     202                 :          0 :                 reset_mpstcam_entry(entry);
     203                 :          0 :                 t->full = false;     /* We have atleast 1 free entry */
     204                 :          0 :                 cxgbe_update_free_idx(t);
     205                 :            :         }
     206                 :            : 
     207                 :            :         t4_os_write_unlock(&t->lock);
     208                 :          0 :         return ret;
     209                 :            : }
     210                 :            : 
     211                 :          0 : int cxgbe_mpstcam_rawf_enable(struct port_info *pi)
     212                 :            : {
     213                 :          0 :         struct adapter *adap = pi->adapter;
     214                 :            :         struct mps_tcam_entry *entry;
     215                 :            :         struct mpstcam_table *t;
     216                 :            :         u16 rawf_idx;
     217                 :            :         int ret = 0;
     218                 :            : 
     219                 :          0 :         t = adap->mpstcam;
     220   [ #  #  #  # ]:          0 :         if (adap->params.rawf_size == 0 || t == NULL)
     221                 :            :                 return -EOPNOTSUPP;
     222                 :            : 
     223                 :          0 :         t4_os_write_lock(&t->lock);
     224                 :          0 :         rawf_idx = adap->params.rawf_start + pi->port_id;
     225                 :          0 :         entry = &t->entry[rawf_idx];
     226         [ #  # ]:          0 :         if (rte_atomic_load_explicit(&entry->refcnt, rte_memory_order_relaxed) == 1)
     227                 :          0 :                 goto out_unlock;
     228                 :            : 
     229                 :          0 :         ret = t4_alloc_raw_mac_filt(adap, pi->viid, entry->eth_addr,
     230                 :          0 :                                     entry->mask, rawf_idx, 0, pi->port_id,
     231                 :            :                                     false);
     232         [ #  # ]:          0 :         if (ret < 0)
     233                 :          0 :                 goto out_unlock;
     234                 :            : 
     235                 :          0 :         rte_atomic_store_explicit(&entry->refcnt, 1, rte_memory_order_relaxed);
     236                 :            : 
     237                 :          0 : out_unlock:
     238                 :            :         t4_os_write_unlock(&t->lock);
     239                 :          0 :         return ret;
     240                 :            : }
     241                 :            : 
     242                 :          0 : int cxgbe_mpstcam_rawf_disable(struct port_info *pi)
     243                 :            : {
     244                 :          0 :         struct adapter *adap = pi->adapter;
     245                 :            :         struct mps_tcam_entry *entry;
     246                 :            :         struct mpstcam_table *t;
     247                 :            :         u16 rawf_idx;
     248                 :            :         int ret = 0;
     249                 :            : 
     250                 :          0 :         t = adap->mpstcam;
     251   [ #  #  #  # ]:          0 :         if (adap->params.rawf_size == 0 || t == NULL)
     252                 :            :                 return -EOPNOTSUPP;
     253                 :            : 
     254                 :          0 :         t4_os_write_lock(&t->lock);
     255                 :          0 :         rawf_idx = adap->params.rawf_start + pi->port_id;
     256                 :          0 :         entry = &t->entry[rawf_idx];
     257         [ #  # ]:          0 :         if (rte_atomic_load_explicit(&entry->refcnt, rte_memory_order_relaxed) != 1)
     258                 :          0 :                 goto out_unlock;
     259                 :            : 
     260                 :          0 :         ret = t4_free_raw_mac_filt(adap, pi->viid, entry->eth_addr,
     261                 :          0 :                                    entry->mask, rawf_idx, 0, pi->port_id,
     262                 :            :                                    false);
     263         [ #  # ]:          0 :         if (ret < 0)
     264                 :          0 :                 goto out_unlock;
     265                 :            : 
     266                 :          0 :         rte_atomic_store_explicit(&entry->refcnt, 0, rte_memory_order_relaxed);
     267                 :            : 
     268                 :          0 : out_unlock:
     269                 :            :         t4_os_write_unlock(&t->lock);
     270                 :          0 :         return ret;
     271                 :            : }
     272                 :            : 
     273                 :          0 : struct mpstcam_table *t4_init_mpstcam(struct adapter *adap)
     274                 :            : {
     275                 :          0 :         u16 size = adap->params.arch.mps_tcam_size;
     276                 :            :         struct mpstcam_table *t;
     277                 :            :         int i;
     278                 :            : 
     279                 :          0 :         t =  t4_os_alloc(sizeof(*t) + size * sizeof(struct mps_tcam_entry));
     280         [ #  # ]:          0 :         if (!t)
     281                 :            :                 return NULL;
     282                 :            : 
     283                 :            :         t4_os_rwlock_init(&t->lock);
     284                 :          0 :         t->full = false;
     285                 :          0 :         t->size = size;
     286                 :            : 
     287         [ #  # ]:          0 :         for (i = 0; i < size; i++) {
     288                 :          0 :                 reset_mpstcam_entry(&t->entry[i]);
     289                 :          0 :                 t->entry[i].mpstcam = t;
     290                 :          0 :                 t->entry[i].idx = i;
     291                 :            :         }
     292                 :            : 
     293                 :            :         /* RAW MAC entries are reserved for match-all wildcard to
     294                 :            :          * match all promiscuous traffic. So, mark them special.
     295                 :            :          */
     296         [ #  # ]:          0 :         for (i = 0; i < adap->params.rawf_size; i++)
     297                 :          0 :                 t->entry[adap->params.rawf_start + i].state = MPS_ENTRY_RAWF;
     298                 :            : 
     299                 :            :         /* first entry is used by chip. this is overwritten only
     300                 :            :          * in t4_cleanup_mpstcam()
     301                 :            :          */
     302                 :          0 :         t->entry[0].state = MPS_ENTRY_USED;
     303                 :          0 :         t->free_idx = 1;
     304                 :            : 
     305                 :          0 :         return t;
     306                 :            : }
     307                 :            : 
     308                 :          0 : void t4_cleanup_mpstcam(struct adapter *adap)
     309                 :            : {
     310         [ #  # ]:          0 :         if (adap->mpstcam)
     311                 :          0 :                 t4_os_free(adap->mpstcam);
     312                 :          0 : }

Generated by: LCOV version 1.14