| /* SPDX-License-Identifier: GPL-2.0-only */ |
| /**************************************************************************** |
| * Driver for Solarflare network controllers and boards |
| * Copyright 2019 Solarflare Communications Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 as published |
| * by the Free Software Foundation, incorporated herein by reference. |
| */ |
| #ifndef EFX_MCDI_FILTERS_H |
| #define EFX_MCDI_FILTERS_H |
| |
| #include "net_driver.h" |
| #include "filter.h" |
| #include "mcdi_pcol.h" |
| |
| #define EFX_EF10_FILTER_DEV_UC_MAX 32 |
| #define EFX_EF10_FILTER_DEV_MC_MAX 256 |
| |
| enum efx_mcdi_filter_default_filters { |
| EFX_EF10_BCAST, |
| EFX_EF10_UCDEF, |
| EFX_EF10_MCDEF, |
| EFX_EF10_VXLAN4_UCDEF, |
| EFX_EF10_VXLAN4_MCDEF, |
| EFX_EF10_VXLAN6_UCDEF, |
| EFX_EF10_VXLAN6_MCDEF, |
| EFX_EF10_NVGRE4_UCDEF, |
| EFX_EF10_NVGRE4_MCDEF, |
| EFX_EF10_NVGRE6_UCDEF, |
| EFX_EF10_NVGRE6_MCDEF, |
| EFX_EF10_GENEVE4_UCDEF, |
| EFX_EF10_GENEVE4_MCDEF, |
| EFX_EF10_GENEVE6_UCDEF, |
| EFX_EF10_GENEVE6_MCDEF, |
| |
| EFX_EF10_NUM_DEFAULT_FILTERS |
| }; |
| |
| /* Per-VLAN filters information */ |
| struct efx_mcdi_filter_vlan { |
| struct list_head list; |
| u16 vid; |
| u16 uc[EFX_EF10_FILTER_DEV_UC_MAX]; |
| u16 mc[EFX_EF10_FILTER_DEV_MC_MAX]; |
| u16 default_filters[EFX_EF10_NUM_DEFAULT_FILTERS]; |
| }; |
| |
| struct efx_mcdi_dev_addr { |
| u8 addr[ETH_ALEN]; |
| }; |
| |
| struct efx_mcdi_filter_table { |
| /* The MCDI match masks supported by this fw & hw, in order of priority */ |
| u32 rx_match_mcdi_flags[ |
| MC_CMD_GET_PARSER_DISP_INFO_OUT_SUPPORTED_MATCHES_MAXNUM * 2]; |
| unsigned int rx_match_count; |
| /* Our RSS context is exclusive (as opposed to shared) */ |
| bool rx_rss_context_exclusive; |
| |
| struct rw_semaphore lock; /* Protects entries */ |
| struct { |
| unsigned long spec; /* pointer to spec plus flag bits */ |
| /* AUTO_OLD is used to mark and sweep MAC filters for the device address lists. */ |
| /* unused flag 1UL */ |
| #define EFX_EF10_FILTER_FLAG_AUTO_OLD 2UL |
| #define EFX_EF10_FILTER_FLAGS 3UL |
| u64 handle; /* firmware handle */ |
| } *entry; |
| /* Shadow of net_device address lists, guarded by mac_lock */ |
| struct efx_mcdi_dev_addr dev_uc_list[EFX_EF10_FILTER_DEV_UC_MAX]; |
| struct efx_mcdi_dev_addr dev_mc_list[EFX_EF10_FILTER_DEV_MC_MAX]; |
| int dev_uc_count; |
| int dev_mc_count; |
| bool uc_promisc; |
| bool mc_promisc; |
| /* Whether in multicast promiscuous mode when last changed */ |
| bool mc_promisc_last; |
| bool mc_overflow; /* Too many MC addrs; should always imply mc_promisc */ |
| /* RSS contexts have yet to be restored after MC reboot */ |
| bool must_restore_rss_contexts; |
| /* filters have yet to be restored after MC reboot */ |
| bool must_restore_filters; |
| /* Multicast filter chaining allows less-specific filters to receive |
| * multicast packets that matched more-specific filters. Early EF10 |
| * firmware didn't support this (SF bug 26807); if mc_chaining == false |
| * then we still subscribe the dev_mc_list even when mc_promisc to |
| * prevent another VI stealing the traffic. |
| */ |
| bool mc_chaining; |
| bool vlan_filter; |
| struct list_head vlan_list; |
| }; |
| |
| int efx_mcdi_filter_table_probe(struct efx_nic *efx, bool multicast_chaining); |
| void efx_mcdi_filter_table_remove(struct efx_nic *efx); |
| void efx_mcdi_filter_table_restore(struct efx_nic *efx); |
| |
| void efx_mcdi_filter_table_reset_mc_allocations(struct efx_nic *efx); |
| |
| /* |
| * The filter table(s) are managed by firmware and we have write-only |
| * access. When removing filters we must identify them to the |
| * firmware by a 64-bit handle, but this is too wide for Linux kernel |
| * interfaces (32-bit for RX NFC, 16-bit for RFS). Also, we need to |
| * be able to tell in advance whether a requested insertion will |
| * replace an existing filter. Therefore we maintain a software hash |
| * table, which should be at least as large as the hardware hash |
| * table. |
| * |
| * Huntington has a single 8K filter table shared between all filter |
| * types and both ports. |
| */ |
| #define EFX_MCDI_FILTER_TBL_ROWS 8192 |
| |
| bool efx_mcdi_filter_match_supported(struct efx_mcdi_filter_table *table, |
| bool encap, |
| enum efx_filter_match_flags match_flags); |
| |
| void efx_mcdi_filter_sync_rx_mode(struct efx_nic *efx); |
| s32 efx_mcdi_filter_insert(struct efx_nic *efx, struct efx_filter_spec *spec, |
| bool replace_equal); |
| int efx_mcdi_filter_remove_safe(struct efx_nic *efx, |
| enum efx_filter_priority priority, |
| u32 filter_id); |
| int efx_mcdi_filter_get_safe(struct efx_nic *efx, |
| enum efx_filter_priority priority, |
| u32 filter_id, struct efx_filter_spec *spec); |
| |
| u32 efx_mcdi_filter_count_rx_used(struct efx_nic *efx, |
| enum efx_filter_priority priority); |
| int efx_mcdi_filter_clear_rx(struct efx_nic *efx, |
| enum efx_filter_priority priority); |
| u32 efx_mcdi_filter_get_rx_id_limit(struct efx_nic *efx); |
| s32 efx_mcdi_filter_get_rx_ids(struct efx_nic *efx, |
| enum efx_filter_priority priority, |
| u32 *buf, u32 size); |
| |
| void efx_mcdi_filter_cleanup_vlans(struct efx_nic *efx); |
| int efx_mcdi_filter_add_vlan(struct efx_nic *efx, u16 vid); |
| struct efx_mcdi_filter_vlan *efx_mcdi_filter_find_vlan(struct efx_nic *efx, u16 vid); |
| void efx_mcdi_filter_del_vlan(struct efx_nic *efx, u16 vid); |
| |
| void efx_mcdi_rx_free_indir_table(struct efx_nic *efx); |
| int efx_mcdi_rx_push_rss_context_config(struct efx_nic *efx, |
| struct efx_rss_context *ctx, |
| const u32 *rx_indir_table, |
| const u8 *key); |
| int efx_mcdi_pf_rx_push_rss_config(struct efx_nic *efx, bool user, |
| const u32 *rx_indir_table, |
| const u8 *key); |
| int efx_mcdi_vf_rx_push_rss_config(struct efx_nic *efx, bool user, |
| const u32 *rx_indir_table |
| __attribute__ ((unused)), |
| const u8 *key |
| __attribute__ ((unused))); |
| int efx_mcdi_rx_pull_rss_config(struct efx_nic *efx); |
| int efx_mcdi_rx_pull_rss_context_config(struct efx_nic *efx, |
| struct efx_rss_context *ctx); |
| int efx_mcdi_get_rss_context_flags(struct efx_nic *efx, u32 context, |
| u32 *flags); |
| void efx_mcdi_set_rss_context_flags(struct efx_nic *efx, |
| struct efx_rss_context *ctx); |
| void efx_mcdi_rx_restore_rss_contexts(struct efx_nic *efx); |
| |
| static inline void efx_mcdi_update_rx_scatter(struct efx_nic *efx) |
| { |
| /* no need to do anything here */ |
| } |
| |
| bool efx_mcdi_filter_rfs_expire_one(struct efx_nic *efx, u32 flow_id, |
| unsigned int filter_idx); |
| |
| #endif |