Merge tag 'mlx5-fixes-2019-07-11' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-block.git] / drivers / net / ethernet / mellanox / mlx5 / core / eswitch.c
index b4f96f04a18be2a126d488a092fa91d5b38efff8..3b04d8927fb1a408cf5f34ae78f7282658ba874e 100644 (file)
@@ -1552,7 +1552,7 @@ static void node_guid_gen_from_mac(u64 *node_guid, u8 mac[ETH_ALEN])
 static void esw_apply_vport_conf(struct mlx5_eswitch *esw,
                                 struct mlx5_vport *vport)
 {
-       int vport_num = vport->vport;
+       u16 vport_num = vport->vport;
        int flags;
 
        if (esw->manager_vport == vport_num)
@@ -1715,14 +1715,56 @@ static int eswitch_vport_event(struct notifier_block *nb,
        return NOTIFY_OK;
 }
 
-int mlx5_esw_query_functions(struct mlx5_core_dev *dev, u32 *out, int outlen)
+/**
+ * mlx5_esw_query_functions - Returns raw output about functions state
+ * @dev:       Pointer to device to query
+ *
+ * mlx5_esw_query_functions() allocates and returns functions changed
+ * raw output memory pointer from device on success. Otherwise returns ERR_PTR.
+ * Caller must free the memory using kvfree() when valid pointer is returned.
+ */
+const u32 *mlx5_esw_query_functions(struct mlx5_core_dev *dev)
 {
+       int outlen = MLX5_ST_SZ_BYTES(query_esw_functions_out);
        u32 in[MLX5_ST_SZ_DW(query_esw_functions_in)] = {};
+       u32 *out;
+       int err;
+
+       out = kvzalloc(outlen, GFP_KERNEL);
+       if (!out)
+               return ERR_PTR(-ENOMEM);
 
        MLX5_SET(query_esw_functions_in, in, opcode,
                 MLX5_CMD_OP_QUERY_ESW_FUNCTIONS);
 
-       return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
+       err = mlx5_cmd_exec(dev, in, sizeof(in), out, outlen);
+       if (!err)
+               return out;
+
+       kvfree(out);
+       return ERR_PTR(err);
+}
+
+static void mlx5_eswitch_event_handlers_register(struct mlx5_eswitch *esw)
+{
+       MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE);
+       mlx5_eq_notifier_register(esw->dev, &esw->nb);
+
+       if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev)) {
+               MLX5_NB_INIT(&esw->esw_funcs.nb, mlx5_esw_funcs_changed_handler,
+                            ESW_FUNCTIONS_CHANGED);
+               mlx5_eq_notifier_register(esw->dev, &esw->esw_funcs.nb);
+       }
+}
+
+static void mlx5_eswitch_event_handlers_unregister(struct mlx5_eswitch *esw)
+{
+       if (esw->mode == MLX5_ESWITCH_OFFLOADS && mlx5_eswitch_is_funcs_handler(esw->dev))
+               mlx5_eq_notifier_unregister(esw->dev, &esw->esw_funcs.nb);
+
+       mlx5_eq_notifier_unregister(esw->dev, &esw->nb);
+
+       flush_workqueue(esw->work_queue);
 }
 
 /* Public E-Switch API */
@@ -1767,11 +1809,8 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode)
        if (err)
                esw_warn(esw->dev, "Failed to create eswitch TSAR");
 
-       /* Don't enable vport events when in MLX5_ESWITCH_OFFLOADS mode, since:
-        * 1. L2 table (MPFS) is programmed by PF/VF representors netdevs set_rx_mode
-        * 2. FDB/Eswitch is programmed by user space tools
-        */
-       enabled_events = (mode == MLX5_ESWITCH_LEGACY) ? SRIOV_VPORT_EVENTS : 0;
+       enabled_events = (mode == MLX5_ESWITCH_LEGACY) ? SRIOV_VPORT_EVENTS :
+               UC_ADDR_CHANGE;
 
        /* Enable PF vport */
        vport = mlx5_eswitch_get_vport(esw, MLX5_VPORT_PF);
@@ -1787,10 +1826,7 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int mode)
        mlx5_esw_for_each_vf_vport(esw, i, vport, esw->esw_funcs.num_vfs)
                esw_enable_vport(esw, vport, enabled_events);
 
-       if (mode == MLX5_ESWITCH_LEGACY) {
-               MLX5_NB_INIT(&esw->nb, eswitch_vport_event, NIC_VPORT_CHANGE);
-               mlx5_eq_notifier_register(esw->dev, &esw->nb);
-       }
+       mlx5_eswitch_event_handlers_register(esw);
 
        esw_info(esw->dev, "Enable: mode(%s), nvfs(%d), active vports(%d)\n",
                 mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
@@ -1824,9 +1860,7 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw)
                 esw->esw_funcs.num_vfs, esw->enabled_vports);
 
        mc_promisc = &esw->mc_promisc;
-
-       if (esw->mode == MLX5_ESWITCH_LEGACY)
-               mlx5_eq_notifier_unregister(esw->dev, &esw->nb);
+       mlx5_eswitch_event_handlers_unregister(esw);
 
        mlx5_esw_for_all_vports(esw, i, vport)
                esw_disable_vport(esw, vport);
@@ -1854,14 +1888,16 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw)
 
 int mlx5_eswitch_init(struct mlx5_core_dev *dev)
 {
-       int total_vports = MLX5_TOTAL_VPORTS(dev);
        struct mlx5_eswitch *esw;
        struct mlx5_vport *vport;
+       int total_vports;
        int err, i;
 
        if (!MLX5_VPORT_MANAGER(dev))
                return 0;
 
+       total_vports = mlx5_eswitch_get_total_vports(dev);
+
        esw_info(dev,
                 "Total vports %d, per vport: max uc(%d) max mc(%d)\n",
                 total_vports,
@@ -1874,6 +1910,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
 
        esw->dev = dev;
        esw->manager_vport = mlx5_eswitch_manager_vport(dev);
+       esw->first_host_vport = mlx5_eswitch_first_host_vport_num(dev);
 
        esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq");
        if (!esw->work_queue) {
@@ -1909,11 +1946,6 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
        esw->enabled_vports = 0;
        esw->mode = MLX5_ESWITCH_NONE;
        esw->offloads.inline_mode = MLX5_INLINE_MODE_NONE;
-       if (MLX5_CAP_ESW_FLOWTABLE_FDB(dev, reformat) &&
-           MLX5_CAP_ESW_FLOWTABLE_FDB(dev, decap))
-               esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_BASIC;
-       else
-               esw->offloads.encap = DEVLINK_ESWITCH_ENCAP_MODE_NONE;
 
        dev->priv.eswitch = esw;
        return 0;
@@ -1942,7 +1974,7 @@ void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
 
 /* Vport Administration */
 int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
-                              int vport, u8 mac[ETH_ALEN])
+                              u16 vport, u8 mac[ETH_ALEN])
 {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
        u64 node_guid;
@@ -1986,7 +2018,7 @@ unlock:
 }
 
 int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
-                                int vport, int link_state)
+                                u16 vport, int link_state)
 {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
        int err = 0;
@@ -2016,7 +2048,7 @@ unlock:
 }
 
 int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
-                                 int vport, struct ifla_vf_info *ivi)
+                                 u16 vport, struct ifla_vf_info *ivi)
 {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
 
@@ -2041,7 +2073,7 @@ int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,
 }
 
 int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
-                                 int vport, u16 vlan, u8 qos, u8 set_flags)
+                                 u16 vport, u16 vlan, u8 qos, u8 set_flags)
 {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
        int err = 0;
@@ -2074,7 +2106,7 @@ unlock:
 }
 
 int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
-                               int vport, u16 vlan, u8 qos)
+                               u16 vport, u16 vlan, u8 qos)
 {
        u8 set_flags = 0;
 
@@ -2085,7 +2117,7 @@ int mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw,
 }
 
 int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
-                                   int vport, bool spoofchk)
+                                   u16 vport, bool spoofchk)
 {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
        bool pschk;
@@ -2235,7 +2267,7 @@ out:
 }
 
 int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
-                                int vport, bool setting)
+                                u16 vport, bool setting)
 {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
 
@@ -2305,7 +2337,7 @@ static int normalize_vports_min_rate(struct mlx5_eswitch *esw, u32 divider)
        return 0;
 }
 
-int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, int vport,
+int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
                                u32 max_rate, u32 min_rate)
 {
        struct mlx5_vport *evport = mlx5_eswitch_get_vport(esw, vport);
@@ -2395,7 +2427,7 @@ static int mlx5_eswitch_query_vport_drop_stats(struct mlx5_core_dev *dev,
 }
 
 int mlx5_eswitch_get_vport_stats(struct mlx5_eswitch *esw,
-                                int vport_num,
+                                u16 vport_num,
                                 struct ifla_vf_stats *vf_stats)
 {
        struct mlx5_vport *vport = mlx5_eswitch_get_vport(esw, vport_num);
@@ -2510,8 +2542,7 @@ bool mlx5_esw_multipath_prereq(struct mlx5_core_dev *dev0,
 
 void mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, const int num_vfs)
 {
-       u32 out[MLX5_ST_SZ_DW(query_esw_functions_out)] = {};
-       int err;
+       const u32 *out;
 
        WARN_ON_ONCE(esw->mode != MLX5_ESWITCH_NONE);
 
@@ -2520,8 +2551,11 @@ void mlx5_eswitch_update_num_of_vfs(struct mlx5_eswitch *esw, const int num_vfs)
                return;
        }
 
-       err = mlx5_esw_query_functions(esw->dev, out, sizeof(out));
-       if (!err)
-               esw->esw_funcs.num_vfs = MLX5_GET(query_esw_functions_out, out,
-                                                 host_params_context.host_num_of_vfs);
+       out = mlx5_esw_query_functions(esw->dev);
+       if (IS_ERR(out))
+               return;
+
+       esw->esw_funcs.num_vfs = MLX5_GET(query_esw_functions_out, out,
+                                         host_params_context.host_num_of_vfs);
+       kvfree(out);
 }