Commit 81848731 authored by Saeed Mahameed's avatar Saeed Mahameed Committed by David S. Miller

net/mlx5: E-Switch, Add SR-IOV (FDB) support

Enabling E-Switch SRIOV for nvfs+1 vports.

Create E-Switch FDB for L2 UC/MC mac steering between VFs/PF and
external vport (Uplink).

FDB contains forwarding rules such as:
	UC MAC0 -> vport0(PF).
	UC MAC1 -> vport1.
	UC MAC2 -> vport2.
	MC MACX -> vport0, vport2, Uplink.
	MC MACY -> vport1, Uplink.

For unmatched traffic FDB has the following default rules:
	Unmached Traffic (src vport != Uplink) -> Uplink.
	Unmached Traffic (src vport == Uplink) -> vport0(PF).

FDB rules population:
Each NIC vport (VF) will notify E-Switch manager of its UC/MC vport
context changes via modify vport context command, which will be
translated to an event that will be handled by E-Switch manager (PF)
which will update FDB table accordingly.
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 495716b1
...@@ -86,10 +86,25 @@ struct l2addr_node { ...@@ -86,10 +86,25 @@ struct l2addr_node {
kfree(ptr); \ kfree(ptr); \
}) })
struct mlx5_flow_rule {
void *ft;
u32 fi;
u8 match_criteria_enable;
u32 *match_criteria;
u32 *match_value;
u32 action;
u32 flow_tag;
bool valid;
atomic_t refcount;
struct mutex mutex; /* protect flow rule updates */
struct list_head dest_list;
};
struct mlx5_vport { struct mlx5_vport {
struct mlx5_core_dev *dev; struct mlx5_core_dev *dev;
int vport; int vport;
struct hlist_head uc_list[MLX5_L2_ADDR_HASH_SIZE]; struct hlist_head uc_list[MLX5_L2_ADDR_HASH_SIZE];
struct hlist_head mc_list[MLX5_L2_ADDR_HASH_SIZE];
struct work_struct vport_change_handler; struct work_struct vport_change_handler;
/* This spinlock protects access to vport data, between /* This spinlock protects access to vport data, between
...@@ -98,6 +113,7 @@ struct mlx5_vport { ...@@ -98,6 +113,7 @@ struct mlx5_vport {
*/ */
spinlock_t lock; /* vport events sync */ spinlock_t lock; /* vport events sync */
bool enabled; bool enabled;
u16 enabled_events;
}; };
struct mlx5_l2_table { struct mlx5_l2_table {
...@@ -106,17 +122,26 @@ struct mlx5_l2_table { ...@@ -106,17 +122,26 @@ struct mlx5_l2_table {
unsigned long *bitmap; unsigned long *bitmap;
}; };
struct mlx5_eswitch_fdb {
void *fdb;
};
struct mlx5_eswitch { struct mlx5_eswitch {
struct mlx5_core_dev *dev; struct mlx5_core_dev *dev;
struct mlx5_l2_table l2_table; struct mlx5_l2_table l2_table;
struct mlx5_eswitch_fdb fdb_table;
struct hlist_head mc_table[MLX5_L2_ADDR_HASH_SIZE];
struct workqueue_struct *work_queue; struct workqueue_struct *work_queue;
struct mlx5_vport *vports; struct mlx5_vport *vports;
int total_vports; int total_vports;
int enabled_vports;
}; };
/* E-Switch API */ /* E-Switch API */
int mlx5_eswitch_init(struct mlx5_core_dev *dev); int mlx5_eswitch_init(struct mlx5_core_dev *dev);
void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw); void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw);
void mlx5_eswitch_vport_event(struct mlx5_eswitch *esw, struct mlx5_eqe *eqe); void mlx5_eswitch_vport_event(struct mlx5_eswitch *esw, struct mlx5_eqe *eqe);
int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs);
void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw);
#endif /* __MLX5_ESWITCH_H__ */ #endif /* __MLX5_ESWITCH_H__ */
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/if_link.h>
#define DRIVER_NAME "mlx5_core" #define DRIVER_NAME "mlx5_core"
#define DRIVER_VERSION "3.0-1" #define DRIVER_VERSION "3.0-1"
......
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/mlx5/driver.h> #include <linux/mlx5/driver.h>
#include "mlx5_core.h" #include "mlx5_core.h"
#ifdef CONFIG_MLX5_CORE_EN
#include "eswitch.h"
#endif
static void enable_vfs(struct mlx5_core_dev *dev, int num_vfs) static void enable_vfs(struct mlx5_core_dev *dev, int num_vfs)
{ {
...@@ -144,13 +147,15 @@ int mlx5_core_sriov_configure(struct pci_dev *pdev, int num_vfs) ...@@ -144,13 +147,15 @@ int mlx5_core_sriov_configure(struct pci_dev *pdev, int num_vfs)
mlx5_core_cleanup_vfs(dev); mlx5_core_cleanup_vfs(dev);
if (!num_vfs) { if (!num_vfs) {
#ifdef CONFIG_MLX5_CORE_EN
mlx5_eswitch_disable_sriov(dev->priv.eswitch);
#endif
kfree(sriov->vfs_ctx); kfree(sriov->vfs_ctx);
sriov->vfs_ctx = NULL; sriov->vfs_ctx = NULL;
if (!pci_vfs_assigned(pdev)) if (!pci_vfs_assigned(pdev))
pci_disable_sriov(pdev); pci_disable_sriov(pdev);
else else
pr_info("unloading PF driver while leaving orphan VFs\n"); pr_info("unloading PF driver while leaving orphan VFs\n");
return 0; return 0;
} }
...@@ -161,6 +166,9 @@ int mlx5_core_sriov_configure(struct pci_dev *pdev, int num_vfs) ...@@ -161,6 +166,9 @@ int mlx5_core_sriov_configure(struct pci_dev *pdev, int num_vfs)
} }
mlx5_core_init_vfs(dev, num_vfs); mlx5_core_init_vfs(dev, num_vfs);
#ifdef CONFIG_MLX5_CORE_EN
mlx5_eswitch_enable_sriov(dev->priv.eswitch, num_vfs);
#endif
return num_vfs; return num_vfs;
} }
...@@ -199,6 +207,10 @@ int mlx5_sriov_init(struct mlx5_core_dev *dev) ...@@ -199,6 +207,10 @@ int mlx5_sriov_init(struct mlx5_core_dev *dev)
sriov->enabled_vfs = cur_vfs; sriov->enabled_vfs = cur_vfs;
mlx5_core_init_vfs(dev, cur_vfs); mlx5_core_init_vfs(dev, cur_vfs);
#ifdef CONFIG_MLX5_CORE_EN
if (cur_vfs)
mlx5_eswitch_enable_sriov(dev->priv.eswitch, cur_vfs);
#endif
enable_vfs(dev, cur_vfs); enable_vfs(dev, cur_vfs);
......
...@@ -1074,6 +1074,12 @@ enum { ...@@ -1074,6 +1074,12 @@ enum {
VPORT_STATE_UP = 0x1, VPORT_STATE_UP = 0x1,
}; };
enum {
MLX5_ESW_VPORT_ADMIN_STATE_DOWN = 0x0,
MLX5_ESW_VPORT_ADMIN_STATE_UP = 0x1,
MLX5_ESW_VPORT_ADMIN_STATE_AUTO = 0x2,
};
enum { enum {
MLX5_L3_PROT_TYPE_IPV4 = 0, MLX5_L3_PROT_TYPE_IPV4 = 0,
MLX5_L3_PROT_TYPE_IPV6 = 1, MLX5_L3_PROT_TYPE_IPV6 = 1,
......
...@@ -41,6 +41,15 @@ struct mlx5_flow_table_group { ...@@ -41,6 +41,15 @@ struct mlx5_flow_table_group {
u32 match_criteria[MLX5_ST_SZ_DW(fte_match_param)]; u32 match_criteria[MLX5_ST_SZ_DW(fte_match_param)];
}; };
struct mlx5_flow_destination {
enum mlx5_flow_destination_type type;
union {
u32 tir_num;
void *ft;
u32 vport_num;
};
};
void *mlx5_create_flow_table(struct mlx5_core_dev *dev, u8 level, u8 table_type, void *mlx5_create_flow_table(struct mlx5_core_dev *dev, u8 level, u8 table_type,
u16 num_groups, u16 num_groups,
struct mlx5_flow_table_group *group); struct mlx5_flow_table_group *group);
......
...@@ -827,9 +827,10 @@ struct mlx5_ifc_cmd_hca_cap_bits { ...@@ -827,9 +827,10 @@ struct mlx5_ifc_cmd_hca_cap_bits {
u8 reserved_69[0x220]; u8 reserved_69[0x220];
}; };
enum { enum mlx5_flow_destination_type {
MLX5_DEST_FORMAT_STRUCT_DESTINATION_TYPE_FLOW_TABLE_ = 0x1, MLX5_FLOW_DESTINATION_TYPE_VPORT = 0x0,
MLX5_DEST_FORMAT_STRUCT_DESTINATION_TYPE_TIR = 0x2, MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE = 0x1,
MLX5_FLOW_DESTINATION_TYPE_TIR = 0x2,
}; };
struct mlx5_ifc_dest_format_struct_bits { struct mlx5_ifc_dest_format_struct_bits {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment