Merge branch 'mlx5-next' of git://git.kernel.org/pub/scm/linux/kernel/git/mellanox...
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlx5 / core / fs_core.c
index 84caffe..f1b908d 100644 (file)
 #define KERNEL_MIN_LEVEL (KERNEL_NIC_PRIO_NUM_LEVELS + 1)
 
 #define KERNEL_NIC_TC_NUM_PRIOS  1
-#define KERNEL_NIC_TC_NUM_LEVELS 2
+#define KERNEL_NIC_TC_NUM_LEVELS 3
 
 #define ANCHOR_NUM_LEVELS 1
 #define ANCHOR_NUM_PRIOS 1
@@ -1574,9 +1574,22 @@ static struct mlx5_flow_rule *find_flow_rule(struct fs_fte *fte,
        return NULL;
 }
 
-static bool check_conflicting_actions(u32 action1, u32 action2)
+static bool check_conflicting_actions_vlan(const struct mlx5_fs_vlan *vlan0,
+                                          const struct mlx5_fs_vlan *vlan1)
 {
-       u32 xored_actions = action1 ^ action2;
+       return vlan0->ethtype != vlan1->ethtype ||
+              vlan0->vid != vlan1->vid ||
+              vlan0->prio != vlan1->prio;
+}
+
+static bool check_conflicting_actions(const struct mlx5_flow_act *act1,
+                                     const struct mlx5_flow_act *act2)
+{
+       u32 action1 = act1->action;
+       u32 action2 = act2->action;
+       u32 xored_actions;
+
+       xored_actions = action1 ^ action2;
 
        /* if one rule only wants to count, it's ok */
        if (action1 == MLX5_FLOW_CONTEXT_ACTION_COUNT ||
@@ -1593,6 +1606,22 @@ static bool check_conflicting_actions(u32 action1, u32 action2)
                             MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2))
                return true;
 
+       if (action1 & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT &&
+           act1->pkt_reformat != act2->pkt_reformat)
+               return true;
+
+       if (action1 & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR &&
+           act1->modify_hdr != act2->modify_hdr)
+               return true;
+
+       if (action1 & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH &&
+           check_conflicting_actions_vlan(&act1->vlan[0], &act2->vlan[0]))
+               return true;
+
+       if (action1 & MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH_2 &&
+           check_conflicting_actions_vlan(&act1->vlan[1], &act2->vlan[1]))
+               return true;
+
        return false;
 }
 
@@ -1600,7 +1629,7 @@ static int check_conflicting_ftes(struct fs_fte *fte,
                                  const struct mlx5_flow_context *flow_context,
                                  const struct mlx5_flow_act *flow_act)
 {
-       if (check_conflicting_actions(flow_act->action, fte->action.action)) {
+       if (check_conflicting_actions(flow_act, &fte->action)) {
                mlx5_core_warn(get_dev(&fte->node),
                               "Found two FTEs with conflicting actions\n");
                return -EEXIST;
@@ -2866,6 +2895,14 @@ static int create_fdb_bypass(struct mlx5_flow_steering *steering)
        return 0;
 }
 
+static void cleanup_fdb_root_ns(struct mlx5_flow_steering *steering)
+{
+       cleanup_root_ns(steering->fdb_root_ns);
+       steering->fdb_root_ns = NULL;
+       kfree(steering->fdb_sub_ns);
+       steering->fdb_sub_ns = NULL;
+}
+
 static int init_fdb_root_ns(struct mlx5_flow_steering *steering)
 {
        struct fs_prio *maj_prio;
@@ -2916,10 +2953,7 @@ static int init_fdb_root_ns(struct mlx5_flow_steering *steering)
        return 0;
 
 out_err:
-       cleanup_root_ns(steering->fdb_root_ns);
-       kfree(steering->fdb_sub_ns);
-       steering->fdb_sub_ns = NULL;
-       steering->fdb_root_ns = NULL;
+       cleanup_fdb_root_ns(steering);
        return err;
 }
 
@@ -3079,10 +3113,7 @@ void mlx5_fs_core_cleanup(struct mlx5_core_dev *dev)
        struct mlx5_flow_steering *steering = dev->priv.steering;
 
        cleanup_root_ns(steering->root_ns);
-       cleanup_root_ns(steering->fdb_root_ns);
-       steering->fdb_root_ns = NULL;
-       kfree(steering->fdb_sub_ns);
-       steering->fdb_sub_ns = NULL;
+       cleanup_fdb_root_ns(steering);
        cleanup_root_ns(steering->port_sel_root_ns);
        cleanup_root_ns(steering->sniffer_rx_root_ns);
        cleanup_root_ns(steering->sniffer_tx_root_ns);