sfc: Change filter ID generation to satisfy priority semantics of RX NFC
authorBen Hutchings <bhutchings@solarflare.com>
Tue, 3 Jan 2012 12:05:15 +0000 (12:05 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 4 Jan 2012 19:09:11 +0000 (14:09 -0500)
Also add note that the efx_filter_spec::priority field has nothing
to do with priority between multiple matching filters.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/sfc/filter.c
drivers/net/ethernet/sfc/filter.h

index 2b9636f96e05769a5bba61ded58acf2b98a115ca..1e079bd31bb9227693b3f5db11a88893cf9496a3 100644 (file)
@@ -366,12 +366,45 @@ static int efx_filter_search(struct efx_filter_table *table,
        }
 }
 
-/* Construct/deconstruct external filter IDs */
+/*
+ * Construct/deconstruct external filter IDs.  These must be ordered
+ * by matching priority, for RX NFC semantics.
+ *
+ * Each RX MAC filter entry has a flag for whether it can override an
+ * RX IP filter that also matches.  So we assign locations for MAC
+ * filters with overriding behaviour, then for IP filters, then for
+ * MAC filters without overriding behaviour.
+ */
+
+#define EFX_FILTER_INDEX_WIDTH 13
+#define EFX_FILTER_INDEX_MASK  ((1 << EFX_FILTER_INDEX_WIDTH) - 1)
+
+static inline u32 efx_filter_make_id(enum efx_filter_table_id table_id,
+                                    unsigned int index, u8 flags)
+{
+       return (table_id == EFX_FILTER_TABLE_RX_MAC &&
+               flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP) ?
+               index :
+               (table_id + 1) << EFX_FILTER_INDEX_WIDTH | index;
+}
+
+static inline enum efx_filter_table_id efx_filter_id_table_id(u32 id)
+{
+       return (id <= EFX_FILTER_INDEX_MASK) ?
+               EFX_FILTER_TABLE_RX_MAC :
+               (id >> EFX_FILTER_INDEX_WIDTH) - 1;
+}
+
+static inline unsigned int efx_filter_id_index(u32 id)
+{
+       return id & EFX_FILTER_INDEX_MASK;
+}
 
-static inline int
-efx_filter_make_id(enum efx_filter_table_id table_id, unsigned index)
+static inline u8 efx_filter_id_flags(u32 id)
 {
-       return table_id << 16 | index;
+       return (id <= EFX_FILTER_INDEX_MASK) ?
+               EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_RX_OVERRIDE_IP :
+               EFX_FILTER_FLAG_RX;
 }
 
 /**
@@ -439,7 +472,7 @@ int efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
        netif_vdbg(efx, hw, efx->net_dev,
                   "%s: filter type %d index %d rxq %u set",
                   __func__, spec->type, filter_idx, spec->dmaq_id);
-       rc = efx_filter_make_id(table->id, filter_idx);
+       rc = efx_filter_make_id(table->id, filter_idx, spec->flags);
 
 out:
        spin_unlock_bh(&state->lock);
index 872f2132a49626c2ff3a5ac5c99e32ae22e121b6..dc9a256831d1155414cc9ead419fd080d060972b 100644 (file)
@@ -78,6 +78,11 @@ enum efx_filter_flags {
  *
  * Use the efx_filter_set_*() functions to initialise the @type and
  * @data fields.
+ *
+ * The @priority field is used by software to determine whether a new
+ * filter may replace an old one.  The hardware priority of a filter
+ * depends on the filter type and %EFX_FILTER_FLAG_RX_OVERRIDE_IP
+ * flag.
  */
 struct efx_filter_spec {
        u8      type:4;