linux/drivers/net/sfc/filter.c
<<
>>
Prefs
   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 <linux/in.h>
  11#include "efx.h"
  12#include "filter.h"
  13#include "io.h"
  14#include "nic.h"
  15#include "regs.h"
  16
  17/* "Fudge factors" - difference between programmed value and actual depth.
  18 * Due to pipelined implementation we need to program H/W with a value that
  19 * is larger than the hop limit we want.
  20 */
  21#define FILTER_CTL_SRCH_FUDGE_WILD 3
  22#define FILTER_CTL_SRCH_FUDGE_FULL 1
  23
  24/* Hard maximum hop limit.  Hardware will time-out beyond 200-something.
  25 * We also need to avoid infinite loops in efx_filter_search() when the
  26 * table is full.
  27 */
  28#define FILTER_CTL_SRCH_MAX 200
  29
  30enum efx_filter_table_id {
  31        EFX_FILTER_TABLE_RX_IP = 0,
  32        EFX_FILTER_TABLE_RX_MAC,
  33        EFX_FILTER_TABLE_COUNT,
  34};
  35
  36struct efx_filter_table {
  37        enum efx_filter_table_id id;
  38        u32             offset;         /* address of table relative to BAR */
  39        unsigned        size;           /* number of entries */
  40        unsigned        step;           /* step between entries */
  41        unsigned        used;           /* number currently used */
  42        unsigned long   *used_bitmap;
  43        struct efx_filter_spec *spec;
  44        unsigned        search_depth[EFX_FILTER_TYPE_COUNT];
  45};
  46
  47struct efx_filter_state {
  48        spinlock_t      lock;
  49        struct efx_filter_table table[EFX_FILTER_TABLE_COUNT];
  50};
  51
  52/* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
  53 * key derived from the n-tuple.  The initial LFSR state is 0xffff. */
  54static u16 efx_filter_hash(u32 key)
  55{
  56        u16 tmp;
  57
  58        /* First 16 rounds */
  59        tmp = 0x1fff ^ key >> 16;
  60        tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
  61        tmp = tmp ^ tmp >> 9;
  62        /* Last 16 rounds */
  63        tmp = tmp ^ tmp << 13 ^ key;
  64        tmp = tmp ^ tmp >> 3 ^ tmp >> 6;
  65        return tmp ^ tmp >> 9;
  66}
  67
  68/* To allow for hash collisions, filter search continues at these
  69 * increments from the first possible entry selected by the hash. */
  70static u16 efx_filter_increment(u32 key)
  71{
  72        return key * 2 - 1;
  73}
  74
  75static enum efx_filter_table_id
  76efx_filter_spec_table_id(const struct efx_filter_spec *spec)
  77{
  78        BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_TCP_FULL >> 2));
  79        BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_TCP_WILD >> 2));
  80        BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_UDP_FULL >> 2));
  81        BUILD_BUG_ON(EFX_FILTER_TABLE_RX_IP != (EFX_FILTER_UDP_WILD >> 2));
  82        BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_MAC_FULL >> 2));
  83        BUILD_BUG_ON(EFX_FILTER_TABLE_RX_MAC != (EFX_FILTER_MAC_WILD >> 2));
  84        EFX_BUG_ON_PARANOID(spec->type == EFX_FILTER_UNSPEC);
  85        return spec->type >> 2;
  86}
  87
  88static struct efx_filter_table *
  89efx_filter_spec_table(struct efx_filter_state *state,
  90                      const struct efx_filter_spec *spec)
  91{
  92        if (spec->type == EFX_FILTER_UNSPEC)
  93                return NULL;
  94        else
  95                return &state->table[efx_filter_spec_table_id(spec)];
  96}
  97
  98static void efx_filter_table_reset_search_depth(struct efx_filter_table *table)
  99{
 100        memset(table->search_depth, 0, sizeof(table->search_depth));
 101}
 102
 103static void efx_filter_push_rx_limits(struct efx_nic *efx)
 104{
 105        struct efx_filter_state *state = efx->filter_state;
 106        struct efx_filter_table *table;
 107        efx_oword_t filter_ctl;
 108
 109        efx_reado(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
 110
 111        table = &state->table[EFX_FILTER_TABLE_RX_IP];
 112        EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_FULL_SRCH_LIMIT,
 113                            table->search_depth[EFX_FILTER_TCP_FULL] +
 114                            FILTER_CTL_SRCH_FUDGE_FULL);
 115        EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_WILD_SRCH_LIMIT,
 116                            table->search_depth[EFX_FILTER_TCP_WILD] +
 117                            FILTER_CTL_SRCH_FUDGE_WILD);
 118        EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_FULL_SRCH_LIMIT,
 119                            table->search_depth[EFX_FILTER_UDP_FULL] +
 120                            FILTER_CTL_SRCH_FUDGE_FULL);
 121        EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_WILD_SRCH_LIMIT,
 122                            table->search_depth[EFX_FILTER_UDP_WILD] +
 123                            FILTER_CTL_SRCH_FUDGE_WILD);
 124
 125        table = &state->table[EFX_FILTER_TABLE_RX_MAC];
 126        if (table->size) {
 127                EFX_SET_OWORD_FIELD(
 128                        filter_ctl, FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
 129                        table->search_depth[EFX_FILTER_MAC_FULL] +
 130                        FILTER_CTL_SRCH_FUDGE_FULL);
 131                EFX_SET_OWORD_FIELD(
 132                        filter_ctl, FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
 133                        table->search_depth[EFX_FILTER_MAC_WILD] +
 134                        FILTER_CTL_SRCH_FUDGE_WILD);
 135        }
 136
 137        efx_writeo(efx, &filter_ctl, FR_BZ_RX_FILTER_CTL);
 138}
 139
 140static inline void __efx_filter_set_ipv4(struct efx_filter_spec *spec,
 141                                         __be32 host1, __be16 port1,
 142                                         __be32 host2, __be16 port2)
 143{
 144        spec->data[0] = ntohl(host1) << 16 | ntohs(port1);
 145        spec->data[1] = ntohs(port2) << 16 | ntohl(host1) >> 16;
 146        spec->data[2] = ntohl(host2);
 147}
 148
 149/**
 150 * efx_filter_set_ipv4_local - specify IPv4 host, transport protocol and port
 151 * @spec: Specification to initialise
 152 * @proto: Transport layer protocol number
 153 * @host: Local host address (network byte order)
 154 * @port: Local port (network byte order)
 155 */
 156int efx_filter_set_ipv4_local(struct efx_filter_spec *spec, u8 proto,
 157                              __be32 host, __be16 port)
 158{
 159        __be32 host1;
 160        __be16 port1;
 161
 162        EFX_BUG_ON_PARANOID(!(spec->flags & EFX_FILTER_FLAG_RX));
 163
 164        /* This cannot currently be combined with other filtering */
 165        if (spec->type != EFX_FILTER_UNSPEC)
 166                return -EPROTONOSUPPORT;
 167
 168        if (port == 0)
 169                return -EINVAL;
 170
 171        switch (proto) {
 172        case IPPROTO_TCP:
 173                spec->type = EFX_FILTER_TCP_WILD;
 174                break;
 175        case IPPROTO_UDP:
 176                spec->type = EFX_FILTER_UDP_WILD;
 177                break;
 178        default:
 179                return -EPROTONOSUPPORT;
 180        }
 181
 182        /* Filter is constructed in terms of source and destination,
 183         * with the odd wrinkle that the ports are swapped in a UDP
 184         * wildcard filter.  We need to convert from local and remote
 185         * (= zero for wildcard) addresses.
 186         */
 187        host1 = 0;
 188        if (proto != IPPROTO_UDP) {
 189                port1 = 0;
 190        } else {
 191                port1 = port;
 192                port = 0;
 193        }
 194
 195        __efx_filter_set_ipv4(spec, host1, port1, host, port);
 196        return 0;
 197}
 198
 199/**
 200 * efx_filter_set_ipv4_full - specify IPv4 hosts, transport protocol and ports
 201 * @spec: Specification to initialise
 202 * @proto: Transport layer protocol number
 203 * @host: Local host address (network byte order)
 204 * @port: Local port (network byte order)
 205 * @rhost: Remote host address (network byte order)
 206 * @rport: Remote port (network byte order)
 207 */
 208int efx_filter_set_ipv4_full(struct efx_filter_spec *spec, u8 proto,
 209                             __be32 host, __be16 port,
 210                             __be32 rhost, __be16 rport)
 211{
 212        EFX_BUG_ON_PARANOID(!(spec->flags & EFX_FILTER_FLAG_RX));
 213
 214        /* This cannot currently be combined with other filtering */
 215        if (spec->type != EFX_FILTER_UNSPEC)
 216                return -EPROTONOSUPPORT;
 217
 218        if (port == 0 || rport == 0)
 219                return -EINVAL;
 220
 221        switch (proto) {
 222        case IPPROTO_TCP:
 223                spec->type = EFX_FILTER_TCP_FULL;
 224                break;
 225        case IPPROTO_UDP:
 226                spec->type = EFX_FILTER_UDP_FULL;
 227                break;
 228        default:
 229                return -EPROTONOSUPPORT;
 230        }
 231
 232        __efx_filter_set_ipv4(spec, rhost, rport, host, port);
 233        return 0;
 234}
 235
 236/**
 237 * efx_filter_set_eth_local - specify local Ethernet address and optional VID
 238 * @spec: Specification to initialise
 239 * @vid: VLAN ID to match, or %EFX_FILTER_VID_UNSPEC
 240 * @addr: Local Ethernet MAC address
 241 */
 242int efx_filter_set_eth_local(struct efx_filter_spec *spec,
 243                             u16 vid, const u8 *addr)
 244{
 245        EFX_BUG_ON_PARANOID(!(spec->flags & EFX_FILTER_FLAG_RX));
 246
 247        /* This cannot currently be combined with other filtering */
 248        if (spec->type != EFX_FILTER_UNSPEC)
 249                return -EPROTONOSUPPORT;
 250
 251        if (vid == EFX_FILTER_VID_UNSPEC) {
 252                spec->type = EFX_FILTER_MAC_WILD;
 253                spec->data[0] = 0;
 254        } else {
 255                spec->type = EFX_FILTER_MAC_FULL;
 256                spec->data[0] = vid;
 257        }
 258
 259        spec->data[1] = addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5];
 260        spec->data[2] = addr[0] << 8 | addr[1];
 261        return 0;
 262}
 263
 264/* Build a filter entry and return its n-tuple key. */
 265static u32 efx_filter_build(efx_oword_t *filter, struct efx_filter_spec *spec)
 266{
 267        u32 data3;
 268
 269        switch (efx_filter_spec_table_id(spec)) {
 270        case EFX_FILTER_TABLE_RX_IP: {
 271                bool is_udp = (spec->type == EFX_FILTER_UDP_FULL ||
 272                               spec->type == EFX_FILTER_UDP_WILD);
 273                EFX_POPULATE_OWORD_7(
 274                        *filter,
 275                        FRF_BZ_RSS_EN,
 276                        !!(spec->flags & EFX_FILTER_FLAG_RX_RSS),
 277                        FRF_BZ_SCATTER_EN,
 278                        !!(spec->flags & EFX_FILTER_FLAG_RX_SCATTER),
 279                        FRF_BZ_TCP_UDP, is_udp,
 280                        FRF_BZ_RXQ_ID, spec->dmaq_id,
 281                        EFX_DWORD_2, spec->data[2],
 282                        EFX_DWORD_1, spec->data[1],
 283                        EFX_DWORD_0, spec->data[0]);
 284                data3 = is_udp;
 285                break;
 286        }
 287
 288        case EFX_FILTER_TABLE_RX_MAC: {
 289                bool is_wild = spec->type == EFX_FILTER_MAC_WILD;
 290                EFX_POPULATE_OWORD_8(
 291                        *filter,
 292                        FRF_CZ_RMFT_RSS_EN,
 293                        !!(spec->flags & EFX_FILTER_FLAG_RX_RSS),
 294                        FRF_CZ_RMFT_SCATTER_EN,
 295                        !!(spec->flags & EFX_FILTER_FLAG_RX_SCATTER),
 296                        FRF_CZ_RMFT_IP_OVERRIDE,
 297                        !!(spec->flags & EFX_FILTER_FLAG_RX_OVERRIDE_IP),
 298                        FRF_CZ_RMFT_RXQ_ID, spec->dmaq_id,
 299                        FRF_CZ_RMFT_WILDCARD_MATCH, is_wild,
 300                        FRF_CZ_RMFT_DEST_MAC_HI, spec->data[2],
 301                        FRF_CZ_RMFT_DEST_MAC_LO, spec->data[1],
 302                        FRF_CZ_RMFT_VLAN_ID, spec->data[0]);
 303                data3 = is_wild;
 304                break;
 305        }
 306
 307        default:
 308                BUG();
 309        }
 310
 311        return spec->data[0] ^ spec->data[1] ^ spec->data[2] ^ data3;
 312}
 313
 314static bool efx_filter_equal(const struct efx_filter_spec *left,
 315                             const struct efx_filter_spec *right)
 316{
 317        if (left->type != right->type ||
 318            memcmp(left->data, right->data, sizeof(left->data)))
 319                return false;
 320
 321        return true;
 322}
 323
 324static int efx_filter_search(struct efx_filter_table *table,
 325                             struct efx_filter_spec *spec, u32 key,
 326                             bool for_insert, int *depth_required)
 327{
 328        unsigned hash, incr, filter_idx, depth;
 329        struct efx_filter_spec *cmp;
 330
 331        hash = efx_filter_hash(key);
 332        incr = efx_filter_increment(key);
 333
 334        for (depth = 1, filter_idx = hash & (table->size - 1);
 335             depth <= FILTER_CTL_SRCH_MAX &&
 336                     test_bit(filter_idx, table->used_bitmap);
 337             ++depth) {
 338                cmp = &table->spec[filter_idx];
 339                if (efx_filter_equal(spec, cmp))
 340                        goto found;
 341                filter_idx = (filter_idx + incr) & (table->size - 1);
 342        }
 343        if (!for_insert)
 344                return -ENOENT;
 345        if (depth > FILTER_CTL_SRCH_MAX)
 346                return -EBUSY;
 347found:
 348        *depth_required = depth;
 349        return filter_idx;
 350}
 351
 352/* Construct/deconstruct external filter IDs */
 353
 354static inline int
 355efx_filter_make_id(enum efx_filter_table_id table_id, unsigned index)
 356{
 357        return table_id << 16 | index;
 358}
 359
 360/**
 361 * efx_filter_insert_filter - add or replace a filter
 362 * @efx: NIC in which to insert the filter
 363 * @spec: Specification for the filter
 364 * @replace: Flag for whether the specified filter may replace a filter
 365 *      with an identical match expression and equal or lower priority
 366 *
 367 * On success, return the filter ID.
 368 * On failure, return a negative error code.
 369 */
 370int efx_filter_insert_filter(struct efx_nic *efx, struct efx_filter_spec *spec,
 371                             bool replace)
 372{
 373        struct efx_filter_state *state = efx->filter_state;
 374        struct efx_filter_table *table = efx_filter_spec_table(state, spec);
 375        struct efx_filter_spec *saved_spec;
 376        efx_oword_t filter;
 377        int filter_idx, depth;
 378        u32 key;
 379        int rc;
 380
 381        if (!table || table->size == 0)
 382                return -EINVAL;
 383
 384        key = efx_filter_build(&filter, spec);
 385
 386        netif_vdbg(efx, hw, efx->net_dev,
 387                   "%s: type %d search_depth=%d", __func__, spec->type,
 388                   table->search_depth[spec->type]);
 389
 390        spin_lock_bh(&state->lock);
 391
 392        rc = efx_filter_search(table, spec, key, true, &depth);
 393        if (rc < 0)
 394                goto out;
 395        filter_idx = rc;
 396        BUG_ON(filter_idx >= table->size);
 397        saved_spec = &table->spec[filter_idx];
 398
 399        if (test_bit(filter_idx, table->used_bitmap)) {
 400                /* Should we replace the existing filter? */
 401                if (!replace) {
 402                        rc = -EEXIST;
 403                        goto out;
 404                }
 405                if (spec->priority < saved_spec->priority) {
 406                        rc = -EPERM;
 407                        goto out;
 408                }
 409        } else {
 410                __set_bit(filter_idx, table->used_bitmap);
 411                ++table->used;
 412        }
 413        *saved_spec = *spec;
 414
 415        if (table->search_depth[spec->type] < depth) {
 416                table->search_depth[spec->type] = depth;
 417                efx_filter_push_rx_limits(efx);
 418        }
 419
 420        efx_writeo(efx, &filter, table->offset + table->step * filter_idx);
 421
 422        netif_vdbg(efx, hw, efx->net_dev,
 423                   "%s: filter type %d index %d rxq %u set",
 424                   __func__, spec->type, filter_idx, spec->dmaq_id);
 425        rc = efx_filter_make_id(table->id, filter_idx);
 426
 427out:
 428        spin_unlock_bh(&state->lock);
 429        return rc;
 430}
 431
 432static void efx_filter_table_clear_entry(struct efx_nic *efx,
 433                                         struct efx_filter_table *table,
 434                                         int filter_idx)
 435{
 436        static efx_oword_t filter;
 437
 438        if (test_bit(filter_idx, table->used_bitmap)) {
 439                __clear_bit(filter_idx, table->used_bitmap);
 440                --table->used;
 441                memset(&table->spec[filter_idx], 0, sizeof(table->spec[0]));
 442
 443                efx_writeo(efx, &filter,
 444                           table->offset + table->step * filter_idx);
 445        }
 446}
 447
 448/**
 449 * efx_filter_remove_filter - remove a filter by specification
 450 * @efx: NIC from which to remove the filter
 451 * @spec: Specification for the filter
 452 *
 453 * On success, return zero.
 454 * On failure, return a negative error code.
 455 */
 456int efx_filter_remove_filter(struct efx_nic *efx, struct efx_filter_spec *spec)
 457{
 458        struct efx_filter_state *state = efx->filter_state;
 459        struct efx_filter_table *table = efx_filter_spec_table(state, spec);
 460        struct efx_filter_spec *saved_spec;
 461        efx_oword_t filter;
 462        int filter_idx, depth;
 463        u32 key;
 464        int rc;
 465
 466        if (!table)
 467                return -EINVAL;
 468
 469        key = efx_filter_build(&filter, spec);
 470
 471        spin_lock_bh(&state->lock);
 472
 473        rc = efx_filter_search(table, spec, key, false, &depth);
 474        if (rc < 0)
 475                goto out;
 476        filter_idx = rc;
 477        saved_spec = &table->spec[filter_idx];
 478
 479        if (spec->priority < saved_spec->priority) {
 480                rc = -EPERM;
 481                goto out;
 482        }
 483
 484        efx_filter_table_clear_entry(efx, table, filter_idx);
 485        if (table->used == 0)
 486                efx_filter_table_reset_search_depth(table);
 487        rc = 0;
 488
 489out:
 490        spin_unlock_bh(&state->lock);
 491        return rc;
 492}
 493
 494static void efx_filter_table_clear(struct efx_nic *efx,
 495                                   enum efx_filter_table_id table_id,
 496                                   enum efx_filter_priority priority)
 497{
 498        struct efx_filter_state *state = efx->filter_state;
 499        struct efx_filter_table *table = &state->table[table_id];
 500        int filter_idx;
 501
 502        spin_lock_bh(&state->lock);
 503
 504        for (filter_idx = 0; filter_idx < table->size; ++filter_idx)
 505                if (table->spec[filter_idx].priority <= priority)
 506                        efx_filter_table_clear_entry(efx, table, filter_idx);
 507        if (table->used == 0)
 508                efx_filter_table_reset_search_depth(table);
 509
 510        spin_unlock_bh(&state->lock);
 511}
 512
 513/**
 514 * efx_filter_clear_rx - remove RX filters by priority
 515 * @efx: NIC from which to remove the filters
 516 * @priority: Maximum priority to remove
 517 */
 518void efx_filter_clear_rx(struct efx_nic *efx, enum efx_filter_priority priority)
 519{
 520        efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_IP, priority);
 521        efx_filter_table_clear(efx, EFX_FILTER_TABLE_RX_MAC, priority);
 522}
 523
 524/* Restore filter stater after reset */
 525void efx_restore_filters(struct efx_nic *efx)
 526{
 527        struct efx_filter_state *state = efx->filter_state;
 528        enum efx_filter_table_id table_id;
 529        struct efx_filter_table *table;
 530        efx_oword_t filter;
 531        int filter_idx;
 532
 533        spin_lock_bh(&state->lock);
 534
 535        for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
 536                table = &state->table[table_id];
 537                for (filter_idx = 0; filter_idx < table->size; filter_idx++) {
 538                        if (!test_bit(filter_idx, table->used_bitmap))
 539                                continue;
 540                        efx_filter_build(&filter, &table->spec[filter_idx]);
 541                        efx_writeo(efx, &filter,
 542                                   table->offset + table->step * filter_idx);
 543                }
 544        }
 545
 546        efx_filter_push_rx_limits(efx);
 547
 548        spin_unlock_bh(&state->lock);
 549}
 550
 551int efx_probe_filters(struct efx_nic *efx)
 552{
 553        struct efx_filter_state *state;
 554        struct efx_filter_table *table;
 555        unsigned table_id;
 556
 557        state = kzalloc(sizeof(*efx->filter_state), GFP_KERNEL);
 558        if (!state)
 559                return -ENOMEM;
 560        efx->filter_state = state;
 561
 562        spin_lock_init(&state->lock);
 563
 564        if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
 565                table = &state->table[EFX_FILTER_TABLE_RX_IP];
 566                table->id = EFX_FILTER_TABLE_RX_IP;
 567                table->offset = FR_BZ_RX_FILTER_TBL0;
 568                table->size = FR_BZ_RX_FILTER_TBL0_ROWS;
 569                table->step = FR_BZ_RX_FILTER_TBL0_STEP;
 570        }
 571
 572        if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0) {
 573                table = &state->table[EFX_FILTER_TABLE_RX_MAC];
 574                table->id = EFX_FILTER_TABLE_RX_MAC;
 575                table->offset = FR_CZ_RX_MAC_FILTER_TBL0;
 576                table->size = FR_CZ_RX_MAC_FILTER_TBL0_ROWS;
 577                table->step = FR_CZ_RX_MAC_FILTER_TBL0_STEP;
 578        }
 579
 580        for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
 581                table = &state->table[table_id];
 582                if (table->size == 0)
 583                        continue;
 584                table->used_bitmap = kcalloc(BITS_TO_LONGS(table->size),
 585                                             sizeof(unsigned long),
 586                                             GFP_KERNEL);
 587                if (!table->used_bitmap)
 588                        goto fail;
 589                table->spec = vzalloc(table->size * sizeof(*table->spec));
 590                if (!table->spec)
 591                        goto fail;
 592        }
 593
 594        return 0;
 595
 596fail:
 597        efx_remove_filters(efx);
 598        return -ENOMEM;
 599}
 600
 601void efx_remove_filters(struct efx_nic *efx)
 602{
 603        struct efx_filter_state *state = efx->filter_state;
 604        enum efx_filter_table_id table_id;
 605
 606        for (table_id = 0; table_id < EFX_FILTER_TABLE_COUNT; table_id++) {
 607                kfree(state->table[table_id].used_bitmap);
 608                vfree(state->table[table_id].spec);
 609        }
 610        kfree(state);
 611}
 612