root/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ionic_rx_filter_free
  2. ionic_rx_filter_del
  3. ionic_rx_filters_init
  4. ionic_rx_filters_deinit
  5. ionic_rx_filter_save
  6. ionic_rx_filter_by_vlan
  7. ionic_rx_filter_by_addr

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
   3 
   4 #include <linux/netdevice.h>
   5 #include <linux/etherdevice.h>
   6 
   7 #include "ionic.h"
   8 #include "ionic_lif.h"
   9 #include "ionic_rx_filter.h"
  10 
  11 void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f)
  12 {
  13         struct device *dev = lif->ionic->dev;
  14 
  15         hlist_del(&f->by_id);
  16         hlist_del(&f->by_hash);
  17         devm_kfree(dev, f);
  18 }
  19 
  20 int ionic_rx_filter_del(struct ionic_lif *lif, struct ionic_rx_filter *f)
  21 {
  22         struct ionic_admin_ctx ctx = {
  23                 .work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
  24                 .cmd.rx_filter_del = {
  25                         .opcode = IONIC_CMD_RX_FILTER_DEL,
  26                         .filter_id = cpu_to_le32(f->filter_id),
  27                 },
  28         };
  29 
  30         return ionic_adminq_post_wait(lif, &ctx);
  31 }
  32 
  33 int ionic_rx_filters_init(struct ionic_lif *lif)
  34 {
  35         unsigned int i;
  36 
  37         spin_lock_init(&lif->rx_filters.lock);
  38 
  39         for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
  40                 INIT_HLIST_HEAD(&lif->rx_filters.by_hash[i]);
  41                 INIT_HLIST_HEAD(&lif->rx_filters.by_id[i]);
  42         }
  43 
  44         return 0;
  45 }
  46 
  47 void ionic_rx_filters_deinit(struct ionic_lif *lif)
  48 {
  49         struct ionic_rx_filter *f;
  50         struct hlist_head *head;
  51         struct hlist_node *tmp;
  52         unsigned int i;
  53 
  54         for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
  55                 head = &lif->rx_filters.by_id[i];
  56                 hlist_for_each_entry_safe(f, tmp, head, by_id)
  57                         ionic_rx_filter_free(lif, f);
  58         }
  59 }
  60 
  61 int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
  62                          u32 hash, struct ionic_admin_ctx *ctx)
  63 {
  64         struct device *dev = lif->ionic->dev;
  65         struct ionic_rx_filter_add_cmd *ac;
  66         struct ionic_rx_filter *f;
  67         struct hlist_head *head;
  68         unsigned int key;
  69 
  70         ac = &ctx->cmd.rx_filter_add;
  71 
  72         switch (le16_to_cpu(ac->match)) {
  73         case IONIC_RX_FILTER_MATCH_VLAN:
  74                 key = le16_to_cpu(ac->vlan.vlan);
  75                 break;
  76         case IONIC_RX_FILTER_MATCH_MAC:
  77                 key = *(u32 *)ac->mac.addr;
  78                 break;
  79         case IONIC_RX_FILTER_MATCH_MAC_VLAN:
  80                 key = le16_to_cpu(ac->mac_vlan.vlan);
  81                 break;
  82         default:
  83                 return -EINVAL;
  84         }
  85 
  86         f = devm_kzalloc(dev, sizeof(*f), GFP_KERNEL);
  87         if (!f)
  88                 return -ENOMEM;
  89 
  90         f->flow_id = flow_id;
  91         f->filter_id = le32_to_cpu(ctx->comp.rx_filter_add.filter_id);
  92         f->rxq_index = rxq_index;
  93         memcpy(&f->cmd, ac, sizeof(f->cmd));
  94 
  95         INIT_HLIST_NODE(&f->by_hash);
  96         INIT_HLIST_NODE(&f->by_id);
  97 
  98         spin_lock_bh(&lif->rx_filters.lock);
  99 
 100         key = hash_32(key, IONIC_RX_FILTER_HASH_BITS);
 101         head = &lif->rx_filters.by_hash[key];
 102         hlist_add_head(&f->by_hash, head);
 103 
 104         key = f->filter_id & IONIC_RX_FILTER_HLISTS_MASK;
 105         head = &lif->rx_filters.by_id[key];
 106         hlist_add_head(&f->by_id, head);
 107 
 108         spin_unlock_bh(&lif->rx_filters.lock);
 109 
 110         return 0;
 111 }
 112 
 113 struct ionic_rx_filter *ionic_rx_filter_by_vlan(struct ionic_lif *lif, u16 vid)
 114 {
 115         struct ionic_rx_filter *f;
 116         struct hlist_head *head;
 117         unsigned int key;
 118 
 119         key = hash_32(vid, IONIC_RX_FILTER_HASH_BITS);
 120         head = &lif->rx_filters.by_hash[key];
 121 
 122         hlist_for_each_entry(f, head, by_hash) {
 123                 if (le16_to_cpu(f->cmd.match) != IONIC_RX_FILTER_MATCH_VLAN)
 124                         continue;
 125                 if (le16_to_cpu(f->cmd.vlan.vlan) == vid)
 126                         return f;
 127         }
 128 
 129         return NULL;
 130 }
 131 
 132 struct ionic_rx_filter *ionic_rx_filter_by_addr(struct ionic_lif *lif,
 133                                                 const u8 *addr)
 134 {
 135         struct ionic_rx_filter *f;
 136         struct hlist_head *head;
 137         unsigned int key;
 138 
 139         key = hash_32(*(u32 *)addr, IONIC_RX_FILTER_HASH_BITS);
 140         head = &lif->rx_filters.by_hash[key];
 141 
 142         hlist_for_each_entry(f, head, by_hash) {
 143                 if (le16_to_cpu(f->cmd.match) != IONIC_RX_FILTER_MATCH_MAC)
 144                         continue;
 145                 if (memcmp(addr, f->cmd.mac.addr, ETH_ALEN) == 0)
 146                         return f;
 147         }
 148 
 149         return NULL;
 150 }

/* [<][>][^][v][top][bottom][index][help] */