sfc: Move SPI state to struct falcon_nic_data
[linux-2.6.git] / drivers / net / sfc / filter.c
1 /****************************************************************************
2  * Driver for Solarflare Solarstorm network controllers and boards
3  * Copyright 2005-2010 Solarflare Communications Inc.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 as published
7  * by the Free Software Foundation, incorporated herein by reference.
8  */
9
10 #include "efx.h"
11 #include "filter.h"
12 #include "io.h"
13 #include "nic.h"
14 #include "regs.h"
15
16 /* "Fudge factors" - difference between programmed value and actual depth.
17  * Due to pipelined implementation we need to program H/W with a value that
18  * is larger than the hop limit we want.
19  */
20 #define FILTER_CTL_SRCH_FUDGE_WILD 3
21 #define FILTER_CTL_SRCH_FUDGE_FULL 1
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
29 struct efx_filter_table {
30         u32             offset;         /* address of table relative to BAR */
31         unsigned        size;           /* number of entries */
32         unsigned        step;           /* step between entries */
33         unsigned        used;           /* number currently used */
34         unsigned long   *used_bitmap;
35         struct efx_filter_spec *spec;
36 };
37
38 struct efx_filter_state {
39         spinlock_t      lock;
40         struct efx_filter_table table[EFX_FILTER_TABLE_COUNT];
41         unsigned        search_depth[EFX_FILTER_TYPE_COUNT];
42 };
43
44 /* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
45  * key derived from the n-tuple.  The initial LFSR state is 0xffff. */
46 static u16 efx_filter_hash(u32 key)
47 {
48         u16 tmp;
49
50         /* First 16 rounds */
51         tmp = 0x1fff ^ key >> 16;
52         tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
53         tmp = tmp ^ tmp >> 9;
54         /* Last 16 rounds */
55         tmp = tmp ^ tmp << 13 ^ key;
56         tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
57         return tmp ^ tmp >> 9;
58 }
59
60 /* To allow for hash collisions, filter search continues at these
61  * increments from the first possible entry selected by the hash. */
62 static u16 efx_filter_increment(u32 key)
63 {
64         return key * 2 - 1;
65 }
66
67 static enum efx_filter_table_id
68 efx_filter_type_table_id(enum efx_filter_type type)
69 {
70         BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_TCP_FULL >> 2));
71         BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_TCP_WILD >> 2));
72         BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_UDP_FULL >> 2));
73         BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_RX_UDP_WILD >> 2));
74         BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_RX_MAC_FULL >> 2));
75         BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_RX_MAC_WILD >> 2));
76         return type >> 2;
77 }
78
79 static void
80 efx_filter_table_reset_search_depth(struct efx_filter_state *state,
81                                     enum efx_filter_table_id table_id)
82 {
83         memset(state->search_depth + (table_id << 2), 0,
84                sizeof(state->search_depth[0]) << 2);
85 }
86
87 static void efx_filter_push_rx_limits(struct efx_nic *efx)
88 {
89         struct efx_filter_state *state = efx->filter_state;
90         efx_oword_t filter_ctl;
91
92         efx_reado(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
93
94         EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_FULL_SRCH_LIMIT,
95                             state->search_depth[EFX_FILTER_RX_TCP_FULL] +
96                             FILTER_CTL_SRCH_FUDGE_FULL);
97         EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_WILD_SRCH_LIMIT,
98                             state->search_depth[EFX_FILTER_RX_TCP_WILD] +
99                             FILTER_CTL_SRCH_FUDGE_WILD);
100         EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_FULL_SRCH_LIMIT,
101                             state->search_depth[EFX_FILTER_RX_UDP_FULL] +
102                             FILTER_CTL_SRCH_FUDGE_FULL);
103         EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_WILD_SRCH_LIMIT,
104                             state->search_depth[EFX_FILTER_RX_UDP_WILD] +
105                             FILTER_CTL_SRCH_FUDGE_WILD);
106
107         if (state->table[EFX_FILTER_TABLE_RX_MAC].size) {
108                 EFX_SET_OWORD_FIELD(
109                         filter_ctl, FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
110                         state->search_depth[EFX_FILTER_RX_MAC_FULL] +
111                         FILTER_CTL_SRCH_FUDGE_FULL);
112                 EFX_SET_OWORD_FIELD(
113                         filter_ctl, FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
114                         state->search_depth[EFX_FILTER_RX_MAC_WILD] +
115                         FILTER_CTL_SRCH_FUDGE_WILD);
116         }
117
118         efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
119 }
120
121 /* Build a filter entry and return its n-tuple key. */
122 static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
123 {
124         u32 data3;
125
126         switch (efx_filter_type_table_id(spec->type)) {
127         case EFX_FILTER_TABLE_RX_IP: {
128                 bool is_udp = (spec->type == EFX_FILTER_RX_UDP_FULL ||
129                                spec->type == EFX_FILTER_RX_UDP_WILD);
130                 EFX_POPULATE_OWORD_7(
131                         *filter,
132                         FRF_BZ_RSS_EN,
133                         !!(spec->flags & EFX_FILTER_FLAG_RX_RSS),
134                         FRF_BZ_SCATTER_EN,
135                         !!(spec->flags & EFX_FILTER_FLAG_RX_SCATTER),
136                         FRF_BZ_TCP_UDP, is_udp,
137                         FRF_BZ_RXQ_ID, spec->dmaq_id,
138                         EFX_DWORD_2, spec->data[2],
139                         EFX_DWORD_1, spec->data[1],
140                         EFX_DWORD_0, spec->data[0]);
141                 data3 = is_udp;
142                 break;
143         }
144
145         case EFX_FILTER_TABLE_RX_MAC: {
146                 bool is_wild = spec->type == EFX_FILTER_RX_MAC_WILD;
147                 EFX_POPULATE_OWORD_8(
148                         *filter,
149                         FRF_CZ_RMFT_RSS_EN,
150                         !!(spec->flags & EFX_FILTER_FLAG_RX_RSS),
151                         FRF_CZ_RMFT_SCATTER_EN,
152                         !!(spec->flags & EFX_FILTER_FLAG_RX_SCATTER),
153                         FRF_CZ_RMFT_IP_OVERRIDE,
154                         !!(spec->flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP),
155                         FRF_CZ_RMFT_RXQ_ID, spec->dmaq_id,
156                         FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
157                         FRF_CZ_RMFT_DEST_MAC_HI, spec->data[2],
158                         FRF_CZ_RMFT_DEST_MAC_LO, spec->data[1],
159                         FRF_CZ_RMFT_VLAN_ID, spec->data[0]);
160                 data3 = is_wild;
161                 break;
162         }
163
164         default:
165                 BUG();
166         }
167
168         return spec->data[0] ^ spec->data[1] ^ spec->data[2] ^ data3;
169 }
170
171 static bool efx_filter_equal(const struct efx_filter_spec *left,
172                              const struct efx_filter_spec *right)
173 {
174         if (left->type != right->type ||
175             memcmp(left->data, right->data, sizeof(left->data)))
176                 return false;
177
178         return true;
179 }
180
181 static int efx_filter_search(struct efx_filter_table *table,
182                              struct efx_filter_spec *spec, u32 key,
183                              bool for_insert, int *depth_required)
184 {
185         unsigned hash, incr, filter_idx, depth;
186         struct efx_filter_spec *cmp;
187
188         hash = efx_filter_hash(key);
189         incr = efx_filter_increment(key);
190
191         for (depth = 1, filter_idx = hash & (table->size - 1);
192              depth <= FILTER_CTL_SRCH_MAX &&
193                      test_bit(filter_idx, table->used_bitmap);
194              ++depth) {
195                 cmp = &table->spec[filter_idx];
196                 if (efx_filter_equal(spec, cmp))
197                         goto found;
198                 filter_idx = (filter_idx + incr) & (table->size - 1);
199         }
200         if (!for_insert)
201                 return -ENOENT;
202         if (depth > FILTER_CTL_SRCH_MAX)
203                 return -EBUSY;
204 found:
205         *depth_required = depth;
206         return filter_idx;
207 }
208
209 /**
210  * efx_filter_insert_filter - add or replace a filter
211  * @efx: NIC in which to insert the filter
212  * @spec: Specification for the filter
213  * @replace: Flag for whether the specified filter may replace a filter
214  *      with an identical match expression and equal or lower priority
215  *
216  * On success, return the filter index within its table.
217  * On failure, return a negative error code.
218  */
219 int efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
220                              bool replace)
221 {
222         struct efx_filter_state *state = efx->filter_state;
223         enum efx_filter_table_id table_id =
224                 efx_filter_type_table_id(spec->type);
225         struct efx_filter_table *table = &state->table[table_id];
226         struct efx_filter_spec *saved_spec;
227         efx_oword_t filter;
228         int filter_idx, depth;
229         u32 key;
230         int rc;
231
232         if (table->size == 0)
233                 return -EINVAL;
234
235         key = efx_filter_build(&filter, spec);
236
237         netif_vdbg(efx, hw, efx->net_dev,
238                    "%s: type %d search_depth=%d", __func__, spec->type,
239                    state->search_depth[spec->type]);
240
241         spin_lock_bh(&state->lock);
242
243         rc = efx_filter_search(table, spec, key, true, &depth);
244         if (rc < 0)
245                 goto out;
246         filter_idx = rc;
247         BUG_ON(filter_idx >= table->size);
248         saved_spec = &table->spec[filter_idx];
249
250         if (test_bit(filter_idx, table->used_bitmap)) {
251                 /* Should we replace the existing filter? */
252                 if (!replace) {
253                         rc = -EEXIST;
254                         goto out;
255                 }
256                 if (spec->priority < saved_spec->priority) {
257                         rc = -EPERM;
258                         goto out;
259                 }
260         } else {
261                 __set_bit(filter_idx, table->used_bitmap);
262                 ++table->used;
263         }
264         *saved_spec = *spec;
265
266         if (state->search_depth[spec->type] < depth) {
267                 state->search_depth[spec->type] = depth;
268                 efx_filter_push_rx_limits(efx);
269         }
270
271         efx_writeo(efx, &filter, table->offset + table->step * filter_idx);
272
273         netif_vdbg(efx, hw, efx->net_dev,
274                    "%s: filter type %d index %d rxq %u set",
275                    __func__, spec->type, filter_idx, spec->dmaq_id);
276
277 out:
278         spin_unlock_bh(&state->lock);
279         return rc;
280 }
281
282 static void efx_filter_table_clear_entry(struct efx_nic *efx,
283                                          struct efx_filter_table *table,
284                                          int filter_idx)
285 {
286         static efx_oword_t filter;
287
288         if (test_bit(filter_idx, table->used_bitmap)) {
289                 __clear_bit(filter_idx, table->used_bitmap);
290                 --table->used;
291                 memset(&table->spec[filter_idx], 0, sizeof(table->spec[0]));
292
293                 efx_writeo(efx, &filter,
294                            table->offset + table->step * filter_idx);
295         }
296 }
297
298 /**
299  * efx_filter_remove_filter - remove a filter by specification
300  * @efx: NIC from which to remove the filter
301  * @spec: Specification for the filter
302  *
303  * On success, return zero.
304  * On failure, return a negative error code.
305  */
306 int efx_filter_remove_filter(struct efx_nic *efx, struct efx_filter_spec *spec)
307 {
308         struct efx_filter_state *state = efx->filter_state;
309         enum efx_filter_table_id table_id =
310                 efx_filter_type_table_id(spec->type);
311         struct efx_filter_table *table = &state->table[table_id];
312         struct efx_filter_spec *saved_spec;
313         efx_oword_t filter;
314         int filter_idx, depth;
315         u32 key;
316         int rc;
317
318         key = efx_filter_build(&filter, spec);
319
320         spin_lock_bh(&state->lock);
321
322         rc = efx_filter_search(table, spec, key, false, &depth);
323         if (rc < 0)
324                 goto out;
325         filter_idx = rc;
326         saved_spec = &table->spec[filter_idx];
327
328         if (spec->priority < saved_spec->priority) {
329                 rc = -EPERM;
330                 goto out;
331         }
332
333         efx_filter_table_clear_entry(efx, table, filter_idx);
334         if (table->used == 0)
335                 efx_filter_table_reset_search_depth(state, table_id);
336         rc = 0;
337
338 out:
339         spin_unlock_bh(&state->lock);
340         return rc;
341 }
342
343 /**
344  * efx_filter_table_clear - remove filters from a table by priority
345  * @efx: NIC from which to remove the filters
346  * @table_id: Table from which to remove the filters
347  * @priority: Maximum priority to remove
348  */
349 void efx_filter_table_clear(struct efx_nic *efx,
350                             enum efx_filter_table_id table_id,
351                             enum efx_filter_priority priority)
352 {
353         struct efx_filter_state *state = efx->filter_state;
354         struct efx_filter_table *table = &state->table[table_id];
355         int filter_idx;
356
357         spin_lock_bh(&state->lock);
358
359         for (filter_idx = 0; filter_idx < table->size; ++filter_idx)
360                 if (table->spec[filter_idx].priority <= priority)
361                         efx_filter_table_clear_entry(efx, table, filter_idx);
362         if (table->used == 0)
363                 efx_filter_table_reset_search_depth(state, table_id);
364
365         spin_unlock_bh(&state->lock);
366 }
367
368 /* Restore filter stater after reset */
369 void efx_restore_filters(struct efx_nic *efx)
370 {
371         struct efx_filter_state *state = efx->filter_state;
372         enum efx_filter_table_id table_id;
373         struct efx_filter_table *table;
374         efx_oword_t filter;
375         int filter_idx;
376
377         spin_lock_bh(&state->lock);
378
379         for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
380                 table = &state->table[table_id];
381                 for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
382                         if (!test_bit(filter_idx, table->used_bitmap))
383                                 continue;
384                         efx_filter_build(&filter, &table->spec[filter_idx]);
385                         efx_writeo(efx, &filter,
386                                    table->offset + table->step * filter_idx);
387                 }
388         }
389
390         efx_filter_push_rx_limits(efx);
391
392         spin_unlock_bh(&state->lock);
393 }
394
395 int efx_probe_filters(struct efx_nic *efx)
396 {
397         struct efx_filter_state *state;
398         struct efx_filter_table *table;
399         unsigned table_id;
400
401         state = kzalloc(sizeof(*efx->filter_state), GFP_KERNEL);
402         if (!state)
403                 return -ENOMEM;
404         efx->filter_state = state;
405
406         spin_lock_init(&state->lock);
407
408         if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
409                 table = &state->table[EFX_FILTER_TABLE_RX_IP];
410                 table->offset = FR_BZ_RX_FILTER_TBL0;
411                 table->size = FR_BZ_RX_FILTER_TBL0_ROWS;
412                 table->step = FR_BZ_RX_FILTER_TBL0_STEP;
413         }
414
415         if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
416                 table = &state->table[EFX_FILTER_TABLE_RX_MAC];
417                 table->offset = FR_CZ_RX_MAC_FILTER_TBL0;
418                 table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
419                 table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP;
420         }
421
422         for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
423                 table = &state->table[table_id];
424                 if (table->size == 0)
425                         continue;
426                 table->used_bitmap = kcalloc(BITS_TO_LONGS(table->size),
427                                              sizeof(unsigned long),
428                                              GFP_KERNEL);
429                 if (!table->used_bitmap)
430                         goto fail;
431                 table->spec = vzalloc(table->size * sizeof(*table->spec));
432                 if (!table->spec)
433                         goto fail;
434         }
435
436         return 0;
437
438 fail:
439         efx_remove_filters(efx);
440         return -ENOMEM;
441 }
442
443 void efx_remove_filters(struct efx_nic *efx)
444 {
445         struct efx_filter_state *state = efx->filter_state;
446         enum efx_filter_table_id table_id;
447
448         for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
449                 kfree(state->table[table_id].used_bitmap);
450                 vfree(state->table[table_id].spec);
451         }
452         kfree(state);
453 }