aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2010-10-08 13:36:10 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-08 13:36:10 -0400
commit993284dfff3ba4643f08b592427d0ac758d30156 (patch)
treee929f5e896bb71d33eca2a6b21774ae93d051344
parent4e7f79511e7332ae4056eda9156a0299511ea41e (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.c11
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
23struct efx_filter_table { 29struct 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;
195found: 204found:
196 *depth_required = depth; 205 *depth_required = depth;
197 return filter_idx; 206 return filter_idx;