diff options
author | Ben Hutchings <bhutchings@solarflare.com> | 2010-10-08 13:36:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-10-08 13:36:10 -0400 |
commit | 993284dfff3ba4643f08b592427d0ac758d30156 (patch) | |
tree | e929f5e896bb71d33eca2a6b21774ae93d051344 | |
parent | 4e7f79511e7332ae4056eda9156a0299511ea41e (diff) |
sfc: Don't try to set filters with search depths we know won't work
The filter engine will time-out and ignore filters beyond
200-something hops. We also need to avoid infinite loops in
efx_filter_search() when the table is full.
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/sfc/filter.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/net/sfc/filter.c b/drivers/net/sfc/filter.c index abc884d09d57..52cb6082b910 100644 --- a/drivers/net/sfc/filter.c +++ b/drivers/net/sfc/filter.c | |||
@@ -20,6 +20,12 @@ | |||
20 | #define FILTER_CTL_SRCH_FUDGE_WILD 3 | 20 | #define FILTER_CTL_SRCH_FUDGE_WILD 3 |
21 | #define FILTER_CTL_SRCH_FUDGE_FULL 1 | 21 | #define FILTER_CTL_SRCH_FUDGE_FULL 1 |
22 | 22 | ||
23 | /* Hard maximum hop limit. Hardware will time-out beyond 200-something. | ||
24 | * We also need to avoid infinite loops in efx_filter_search() when the | ||
25 | * table is full. | ||
26 | */ | ||
27 | #define FILTER_CTL_SRCH_MAX 200 | ||
28 | |||
23 | struct efx_filter_table { | 29 | struct efx_filter_table { |
24 | u32 offset; /* address of table relative to BAR */ | 30 | u32 offset; /* address of table relative to BAR */ |
25 | unsigned size; /* number of entries */ | 31 | unsigned size; /* number of entries */ |
@@ -183,7 +189,8 @@ static int efx_filter_search(struct efx_filter_table *table, | |||
183 | incr = efx_filter_increment(key); | 189 | incr = efx_filter_increment(key); |
184 | 190 | ||
185 | for (depth = 1, filter_idx = hash & (table->size - 1); | 191 | for (depth = 1, filter_idx = hash & (table->size - 1); |
186 | test_bit(filter_idx, table->used_bitmap); | 192 | depth <= FILTER_CTL_SRCH_MAX && |
193 | test_bit(filter_idx, table->used_bitmap); | ||
187 | ++depth) { | 194 | ++depth) { |
188 | cmp = &table->spec[filter_idx]; | 195 | cmp = &table->spec[filter_idx]; |
189 | if (efx_filter_equal(spec, cmp)) | 196 | if (efx_filter_equal(spec, cmp)) |
@@ -192,6 +199,8 @@ static int efx_filter_search(struct efx_filter_table *table, | |||
192 | } | 199 | } |
193 | if (!for_insert) | 200 | if (!for_insert) |
194 | return -ENOENT; | 201 | return -ENOENT; |
202 | if (depth > FILTER_CTL_SRCH_MAX) | ||
203 | return -EBUSY; | ||
195 | found: | 204 | found: |
196 | *depth_required = depth; | 205 | *depth_required = depth; |
197 | return filter_idx; | 206 | return filter_idx; |