aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2013-01-14 16:23:16 -0500
committerBen Hutchings <bhutchings@solarflare.com>2013-03-07 15:22:01 -0500
commit297891cecc23b85c6b788b0ec6f2f7e71d89003e (patch)
tree931050494fa3f19dd2071590aeaecd3271ca98af /drivers/net/ethernet/sfc
parent385904f819e31fcf5a5aa53fa91f3352bffa6d19 (diff)
sfc: Merge efx_filter_search() into efx_filter_insert()
efx_filter_search() is only called from efx_filter_insert(), and neither function is very long. The following bug fix requires a more sophisticated search with a third result, which is going to be easier to implement as part of the same function. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc')
-rw-r--r--drivers/net/ethernet/sfc/filter.c60
1 files changed, 24 insertions, 36 deletions
diff --git a/drivers/net/ethernet/sfc/filter.c b/drivers/net/ethernet/sfc/filter.c
index 8d83d9832b21..769560a2cb34 100644
--- a/drivers/net/ethernet/sfc/filter.c
+++ b/drivers/net/ethernet/sfc/filter.c
@@ -513,37 +513,6 @@ static bool efx_filter_equal(const struct efx_filter_spec *left,
513 return true; 513 return true;
514} 514}
515 515
516static int efx_filter_search(struct efx_filter_table *table,
517 struct efx_filter_spec *spec, u32 key,
518 unsigned int *depth_required)
519{
520 unsigned hash, incr, filter_idx, depth, depth_max;
521
522 hash = efx_filter_hash(key);
523 incr = efx_filter_increment(key);
524
525 filter_idx = hash & (table->size - 1);
526 depth = 1;
527 depth_max = (spec->priority <= EFX_FILTER_PRI_HINT ?
528 FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX);
529
530 for (;;) {
531 /* Return success if entry is unused or matches this spec */
532 if (!test_bit(filter_idx, table->used_bitmap) ||
533 efx_filter_equal(spec, &table->spec[filter_idx])) {
534 *depth_required = depth;
535 return filter_idx;
536 }
537
538 /* Return failure if we reached the maximum search depth */
539 if (depth == depth_max)
540 return -EBUSY;
541
542 filter_idx = (filter_idx + incr) & (table->size - 1);
543 ++depth;
544 }
545}
546
547/* 516/*
548 * Construct/deconstruct external filter IDs. At least the RX filter 517 * Construct/deconstruct external filter IDs. At least the RX filter
549 * IDs must be ordered by matching priority, for RX NFC semantics. 518 * IDs must be ordered by matching priority, for RX NFC semantics.
@@ -679,14 +648,33 @@ s32 efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
679 spin_lock_bh(&state->lock); 648 spin_lock_bh(&state->lock);
680 } else { 649 } else {
681 u32 key = efx_filter_build(&filter, spec); 650 u32 key = efx_filter_build(&filter, spec);
651 unsigned int hash = efx_filter_hash(key);
652 unsigned int incr = efx_filter_increment(key);
653 unsigned int depth_max =
654 spec->priority <= EFX_FILTER_PRI_HINT ?
655 FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX;
656
657 filter_idx = hash & (table->size - 1);
658 depth = 1;
682 659
683 spin_lock_bh(&state->lock); 660 spin_lock_bh(&state->lock);
684 661
685 rc = efx_filter_search(table, spec, key, &depth); 662 for (;;) {
686 if (rc < 0) 663 if (!test_bit(filter_idx, table->used_bitmap) ||
687 goto out; 664 efx_filter_equal(spec, &table->spec[filter_idx]))
688 filter_idx = rc; 665 break;
689 BUG_ON(filter_idx >= table->size); 666
667 /* Return failure if we reached the maximum search
668 * depth
669 */
670 if (depth == depth_max) {
671 rc = -EBUSY;
672 goto out;
673 }
674
675 filter_idx = (filter_idx + incr) & (table->size - 1);
676 ++depth;
677 }
690 } 678 }
691 679
692 saved_spec = &table->spec[filter_idx]; 680 saved_spec = &table->spec[filter_idx];