1 | /* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */ |
2 | /* Copyright (c) 2019 Mellanox Technologies. */ |
3 | |
4 | #include "ecpf.h" |
5 | |
6 | bool mlx5_read_embedded_cpu(struct mlx5_core_dev *dev) |
7 | { |
8 | return (ioread32be(&dev->iseg->initializing) >> MLX5_ECPU_BIT_NUM) & 1; |
9 | } |
10 | |
11 | static bool mlx5_ecpf_esw_admins_host_pf(const struct mlx5_core_dev *dev) |
12 | { |
13 | /* In separate host mode, PF enables itself. |
14 | * When ECPF is eswitch manager, eswitch enables host PF after |
15 | * eswitch is setup. |
16 | */ |
17 | return mlx5_core_is_ecpf_esw_manager(dev); |
18 | } |
19 | |
20 | int mlx5_cmd_host_pf_enable_hca(struct mlx5_core_dev *dev) |
21 | { |
22 | u32 out[MLX5_ST_SZ_DW(enable_hca_out)] = {}; |
23 | u32 in[MLX5_ST_SZ_DW(enable_hca_in)] = {}; |
24 | |
25 | MLX5_SET(enable_hca_in, in, opcode, MLX5_CMD_OP_ENABLE_HCA); |
26 | MLX5_SET(enable_hca_in, in, function_id, 0); |
27 | MLX5_SET(enable_hca_in, in, embedded_cpu_function, 0); |
28 | return mlx5_cmd_exec(dev, in: &in, in_size: sizeof(in), out: &out, out_size: sizeof(out)); |
29 | } |
30 | |
31 | int mlx5_cmd_host_pf_disable_hca(struct mlx5_core_dev *dev) |
32 | { |
33 | u32 out[MLX5_ST_SZ_DW(disable_hca_out)] = {}; |
34 | u32 in[MLX5_ST_SZ_DW(disable_hca_in)] = {}; |
35 | |
36 | MLX5_SET(disable_hca_in, in, opcode, MLX5_CMD_OP_DISABLE_HCA); |
37 | MLX5_SET(disable_hca_in, in, function_id, 0); |
38 | MLX5_SET(disable_hca_in, in, embedded_cpu_function, 0); |
39 | return mlx5_cmd_exec(dev, in, in_size: sizeof(in), out, out_size: sizeof(out)); |
40 | } |
41 | |
42 | static int mlx5_host_pf_init(struct mlx5_core_dev *dev) |
43 | { |
44 | int err; |
45 | |
46 | if (mlx5_ecpf_esw_admins_host_pf(dev)) |
47 | return 0; |
48 | |
49 | /* ECPF shall enable HCA for host PF in the same way a PF |
50 | * does this for its VFs when ECPF is not a eswitch manager. |
51 | */ |
52 | err = mlx5_cmd_host_pf_enable_hca(dev); |
53 | if (err) |
54 | mlx5_core_err(dev, "Failed to enable external host PF HCA err(%d)\n" , err); |
55 | |
56 | return err; |
57 | } |
58 | |
59 | static void mlx5_host_pf_cleanup(struct mlx5_core_dev *dev) |
60 | { |
61 | int err; |
62 | |
63 | if (mlx5_ecpf_esw_admins_host_pf(dev)) |
64 | return; |
65 | |
66 | err = mlx5_cmd_host_pf_disable_hca(dev); |
67 | if (err) { |
68 | mlx5_core_err(dev, "Failed to disable external host PF HCA err(%d)\n" , err); |
69 | return; |
70 | } |
71 | } |
72 | |
73 | int mlx5_ec_init(struct mlx5_core_dev *dev) |
74 | { |
75 | if (!mlx5_core_is_ecpf(dev)) |
76 | return 0; |
77 | |
78 | return mlx5_host_pf_init(dev); |
79 | } |
80 | |
81 | void mlx5_ec_cleanup(struct mlx5_core_dev *dev) |
82 | { |
83 | int err; |
84 | |
85 | if (!mlx5_core_is_ecpf(dev)) |
86 | return; |
87 | |
88 | mlx5_host_pf_cleanup(dev); |
89 | |
90 | err = mlx5_wait_for_pages(dev, pages: &dev->priv.page_counters[MLX5_HOST_PF]); |
91 | if (err) |
92 | mlx5_core_warn(dev, "Timeout reclaiming external host PF pages err(%d)\n" , err); |
93 | |
94 | err = mlx5_wait_for_pages(dev, pages: &dev->priv.page_counters[MLX5_VF]); |
95 | if (err) |
96 | mlx5_core_warn(dev, "Timeout reclaiming external host VFs pages err(%d)\n" , err); |
97 | } |
98 | |