sfc: More sensible semantics for efx_filter_insert_filter() replace flag
authorBen Hutchings <bhutchings@solarflare.com>
Mon, 14 Jan 2013 17:43:15 +0000 (17:43 +0000)
committerBen Hutchings <bhutchings@solarflare.com>
Thu, 7 Mar 2013 20:21:58 +0000 (20:21 +0000)
The 'replace' flag to efx_filter_insert_filter() controls whether the
new filter may replace *any* filter, and is checked even before
priority comparison.  But lower-priority filters should never
block insertion of higher-priority filters.

Change the priority checking so that lower-priority filters are
replaced regardless of the value of the flag, and rename the
flag to 'replace_equal'.

Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
drivers/net/ethernet/sfc/filter.c

index 8af42cd1feda7d7dddbd860b76cdddbf69ff01fa..2fdd3a5f21c4586b6b2fb4e7511ea9e01c07d7f5 100644 (file)
@@ -650,14 +650,22 @@ u32 efx_filter_get_rx_id_limit(struct efx_nic *efx)
  * efx_filter_insert_filter - add or replace a filter
  * @efx: NIC in which to insert the filter
  * @spec: Specification for the filter
- * @replace: Flag for whether the specified filter may replace a filter
- *     with an identical match expression and equal or lower priority
+ * @replace_equal: Flag for whether the specified filter may replace an
+ *     existing filter with equal priority
  *
  * On success, return the filter ID.
  * On failure, return a negative error code.
+ *
+ * If an existing filter has equal match values to the new filter
+ * spec, then the new filter might replace it, depending on the
+ * relative priorities.  If the existing filter has lower priority, or
+ * if @replace_equal is set and it has equal priority, then it is
+ * replaced.  Otherwise the function fails, returning -%EPERM if
+ * the existing filter has higher priority or -%EEXIST if it has
+ * equal priority.
  */
 s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
-                            bool replace)
+                            bool replace_equal)
 {
        struct efx_filter_state *state = efx->filter_state;
        struct efx_filter_table *table = efx_filter_spec_table(state, spec);
@@ -687,7 +695,7 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
 
        if (test_bit(filter_idx, table->used_bitmap)) {
                /* Should we replace the existing filter? */
-               if (!replace) {
+               if (spec->priority == saved_spec->priority && !replace_equal) {
                        rc = -EEXIST;
                        goto out;
                }