blob: c29c7c8389807b32898c1cf159548f9d36a18e32 [file] [log] [blame]
Eli Cohene126ba92013-07-07 17:25:49 +03001/*
Saeed Mahameed6cf0a152015-04-02 17:07:30 +03002 * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved.
Eli Cohene126ba92013-07-07 17:25:49 +03003 *
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 * SOFTWARE.
31 */
32
Maor Gottliebfe248c32017-05-30 10:29:14 +030033#include <linux/debugfs.h>
Christoph Hellwigadec6402015-08-28 09:27:19 +020034#include <linux/highmem.h>
Eli Cohene126ba92013-07-07 17:25:49 +030035#include <linux/module.h>
36#include <linux/init.h>
37#include <linux/errno.h>
38#include <linux/pci.h>
39#include <linux/dma-mapping.h>
40#include <linux/slab.h>
Ariel Levkovich24da0012018-04-05 18:53:27 +030041#include <linux/bitmap.h>
Guy Levi37aa5c32016-04-27 16:49:50 +030042#if defined(CONFIG_X86)
43#include <asm/pat.h>
44#endif
Eli Cohene126ba92013-07-07 17:25:49 +030045#include <linux/sched.h>
Ingo Molnar6e84f312017-02-08 18:51:29 +010046#include <linux/sched/mm.h>
Ingo Molnar0881e7b2017-02-05 15:30:50 +010047#include <linux/sched/task.h>
Maor Gottlieb7c2344c2016-06-17 14:56:44 +030048#include <linux/delay.h>
Eli Cohene126ba92013-07-07 17:25:49 +030049#include <rdma/ib_user_verbs.h>
Achiad Shochat3f89a642015-12-23 18:47:21 +020050#include <rdma/ib_addr.h>
Achiad Shochat2811ba52015-12-23 18:47:24 +020051#include <rdma/ib_cache.h>
Achiad Shochatada68c32016-02-22 18:17:23 +020052#include <linux/mlx5/port.h>
Majd Dibbiny1b5daf12015-06-04 19:30:46 +030053#include <linux/mlx5/vport.h>
Pravin Shedge72c7fe92017-12-06 22:19:39 +053054#include <linux/mlx5/fs.h>
Maor Gottlieb7c2344c2016-06-17 14:56:44 +030055#include <linux/list.h>
Eli Cohene126ba92013-07-07 17:25:49 +030056#include <rdma/ib_smi.h>
57#include <rdma/ib_umem.h>
Maor Gottlieb038d2ef2016-01-11 10:26:07 +020058#include <linux/in.h>
59#include <linux/etherdevice.h>
Eli Cohene126ba92013-07-07 17:25:49 +030060#include "mlx5_ib.h"
Mark Blochfc385b72018-01-16 14:34:48 +000061#include "ib_rep.h"
Parav Pandite1f24a72017-04-16 07:29:29 +030062#include "cmd.h"
Boris Pismenny3346c482017-08-20 15:13:08 +030063#include <linux/mlx5/fs_helpers.h>
Aviad Yehezkelc6475a02018-03-28 09:27:50 +030064#include <linux/mlx5/accel.h>
Matan Barak8c846602018-03-28 09:27:41 +030065#include <rdma/uverbs_std_types.h>
Aviad Yehezkelc6475a02018-03-28 09:27:50 +030066#include <rdma/mlx5_user_ioctl_verbs.h>
67#include <rdma/mlx5_user_ioctl_cmds.h>
Matan Barak8c846602018-03-28 09:27:41 +030068
69#define UVERBS_MODULE_NAME mlx5_ib
70#include <rdma/uverbs_named_ioctl.h>
Eli Cohene126ba92013-07-07 17:25:49 +030071
72#define DRIVER_NAME "mlx5_ib"
Tariq Toukanb3599112017-02-22 17:45:46 +020073#define DRIVER_VERSION "5.0-0"
Eli Cohene126ba92013-07-07 17:25:49 +030074
75MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
76MODULE_DESCRIPTION("Mellanox Connect-IB HCA IB driver");
77MODULE_LICENSE("Dual BSD/GPL");
Eli Cohene126ba92013-07-07 17:25:49 +030078
Eli Cohene126ba92013-07-07 17:25:49 +030079static char mlx5_version[] =
80 DRIVER_NAME ": Mellanox Connect-IB Infiniband driver v"
Tariq Toukanb3599112017-02-22 17:45:46 +020081 DRIVER_VERSION "\n";
Eli Cohene126ba92013-07-07 17:25:49 +030082
Daniel Jurgensd69a24e2018-01-04 17:25:37 +020083struct mlx5_ib_event_work {
84 struct work_struct work;
85 struct mlx5_core_dev *dev;
86 void *context;
87 enum mlx5_dev_event event;
88 unsigned long param;
89};
90
Eran Ben Elishada7525d2015-12-14 16:34:10 +020091enum {
92 MLX5_ATOMIC_SIZE_QP_8BYTES = 1 << 3,
93};
Majd Dibbiny1b5daf12015-06-04 19:30:46 +030094
Daniel Jurgensd69a24e2018-01-04 17:25:37 +020095static struct workqueue_struct *mlx5_ib_event_wq;
Daniel Jurgens32f69e42018-01-04 17:25:36 +020096static LIST_HEAD(mlx5_ib_unaffiliated_port_list);
97static LIST_HEAD(mlx5_ib_dev_list);
98/*
99 * This mutex should be held when accessing either of the above lists
100 */
101static DEFINE_MUTEX(mlx5_ib_multiport_mutex);
102
Ilya Lesokhinc44ef992018-03-13 15:18:48 +0200103/* We can't use an array for xlt_emergency_page because dma_map_single
104 * doesn't work on kernel modules memory
105 */
106static unsigned long xlt_emergency_page;
107static struct mutex xlt_emergency_page_mutex;
108
Daniel Jurgens32f69e42018-01-04 17:25:36 +0200109struct mlx5_ib_dev *mlx5_ib_get_ibdev_from_mpi(struct mlx5_ib_multiport_info *mpi)
110{
111 struct mlx5_ib_dev *dev;
112
113 mutex_lock(&mlx5_ib_multiport_mutex);
114 dev = mpi->ibdev;
115 mutex_unlock(&mlx5_ib_multiport_mutex);
116 return dev;
117}
118
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300119static enum rdma_link_layer
Achiad Shochatebd61f62015-12-23 18:47:16 +0200120mlx5_port_type_cap_to_rdma_ll(int port_type_cap)
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300121{
Achiad Shochatebd61f62015-12-23 18:47:16 +0200122 switch (port_type_cap) {
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300123 case MLX5_CAP_PORT_TYPE_IB:
124 return IB_LINK_LAYER_INFINIBAND;
125 case MLX5_CAP_PORT_TYPE_ETH:
126 return IB_LINK_LAYER_ETHERNET;
127 default:
128 return IB_LINK_LAYER_UNSPECIFIED;
129 }
130}
131
Achiad Shochatebd61f62015-12-23 18:47:16 +0200132static enum rdma_link_layer
133mlx5_ib_port_link_layer(struct ib_device *device, u8 port_num)
134{
135 struct mlx5_ib_dev *dev = to_mdev(device);
136 int port_type_cap = MLX5_CAP_GEN(dev->mdev, port_type);
137
138 return mlx5_port_type_cap_to_rdma_ll(port_type_cap);
139}
140
Moni Shouafd65f1b2017-05-30 09:56:05 +0300141static int get_port_state(struct ib_device *ibdev,
142 u8 port_num,
143 enum ib_port_state *state)
144{
145 struct ib_port_attr attr;
146 int ret;
147
148 memset(&attr, 0, sizeof(attr));
Mark Bloch8e6efa32017-11-06 12:22:13 +0000149 ret = ibdev->query_port(ibdev, port_num, &attr);
Moni Shouafd65f1b2017-05-30 09:56:05 +0300150 if (!ret)
151 *state = attr.state;
152 return ret;
153}
154
Achiad Shochatfc24fc52015-12-23 18:47:17 +0200155static int mlx5_netdev_event(struct notifier_block *this,
156 unsigned long event, void *ptr)
157{
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200158 struct mlx5_roce *roce = container_of(this, struct mlx5_roce, nb);
Achiad Shochatfc24fc52015-12-23 18:47:17 +0200159 struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200160 u8 port_num = roce->native_port_num;
161 struct mlx5_core_dev *mdev;
162 struct mlx5_ib_dev *ibdev;
163
164 ibdev = roce->dev;
Daniel Jurgens32f69e42018-01-04 17:25:36 +0200165 mdev = mlx5_ib_get_native_port_mdev(ibdev, port_num, NULL);
166 if (!mdev)
167 return NOTIFY_DONE;
Achiad Shochatfc24fc52015-12-23 18:47:17 +0200168
Aviv Heller5ec8c832016-09-18 20:48:00 +0300169 switch (event) {
170 case NETDEV_REGISTER:
171 case NETDEV_UNREGISTER:
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200172 write_lock(&roce->netdev_lock);
Mark Blochbcf87f12018-01-16 15:02:36 +0000173 if (ibdev->rep) {
174 struct mlx5_eswitch *esw = ibdev->mdev->priv.eswitch;
175 struct net_device *rep_ndev;
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200176
Mark Blochbcf87f12018-01-16 15:02:36 +0000177 rep_ndev = mlx5_ib_get_rep_netdev(esw,
178 ibdev->rep->vport);
179 if (rep_ndev == ndev)
180 roce->netdev = (event == NETDEV_UNREGISTER) ?
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200181 NULL : ndev;
Parav Pandit84a6a7a2018-04-23 17:01:55 +0300182 } else if (ndev->dev.parent == &mdev->pdev->dev) {
Mark Blochbcf87f12018-01-16 15:02:36 +0000183 roce->netdev = (event == NETDEV_UNREGISTER) ?
184 NULL : ndev;
185 }
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200186 write_unlock(&roce->netdev_lock);
Aviv Heller5ec8c832016-09-18 20:48:00 +0300187 break;
Achiad Shochatfc24fc52015-12-23 18:47:17 +0200188
Moni Shouafd65f1b2017-05-30 09:56:05 +0300189 case NETDEV_CHANGE:
Aviv Heller5ec8c832016-09-18 20:48:00 +0300190 case NETDEV_UP:
Aviv Heller88621df2016-09-18 20:48:02 +0300191 case NETDEV_DOWN: {
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200192 struct net_device *lag_ndev = mlx5_lag_get_roce_netdev(mdev);
Aviv Heller88621df2016-09-18 20:48:02 +0300193 struct net_device *upper = NULL;
194
195 if (lag_ndev) {
196 upper = netdev_master_upper_dev_get(lag_ndev);
197 dev_put(lag_ndev);
198 }
199
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200200 if ((upper == ndev || (!upper && ndev == roce->netdev))
Aviv Heller88621df2016-09-18 20:48:02 +0300201 && ibdev->ib_active) {
Bart Van Assche626bc022016-12-05 17:18:08 -0800202 struct ib_event ibev = { };
Moni Shouafd65f1b2017-05-30 09:56:05 +0300203 enum ib_port_state port_state;
Aviv Heller5ec8c832016-09-18 20:48:00 +0300204
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200205 if (get_port_state(&ibdev->ib_dev, port_num,
206 &port_state))
207 goto done;
Moni Shouafd65f1b2017-05-30 09:56:05 +0300208
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200209 if (roce->last_port_state == port_state)
210 goto done;
Moni Shouafd65f1b2017-05-30 09:56:05 +0300211
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200212 roce->last_port_state = port_state;
Aviv Heller5ec8c832016-09-18 20:48:00 +0300213 ibev.device = &ibdev->ib_dev;
Moni Shouafd65f1b2017-05-30 09:56:05 +0300214 if (port_state == IB_PORT_DOWN)
215 ibev.event = IB_EVENT_PORT_ERR;
216 else if (port_state == IB_PORT_ACTIVE)
217 ibev.event = IB_EVENT_PORT_ACTIVE;
218 else
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200219 goto done;
Moni Shouafd65f1b2017-05-30 09:56:05 +0300220
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200221 ibev.element.port_num = port_num;
Aviv Heller5ec8c832016-09-18 20:48:00 +0300222 ib_dispatch_event(&ibev);
223 }
224 break;
Aviv Heller88621df2016-09-18 20:48:02 +0300225 }
Aviv Heller5ec8c832016-09-18 20:48:00 +0300226
227 default:
228 break;
229 }
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200230done:
Daniel Jurgens32f69e42018-01-04 17:25:36 +0200231 mlx5_ib_put_native_port_mdev(ibdev, port_num);
Achiad Shochatfc24fc52015-12-23 18:47:17 +0200232 return NOTIFY_DONE;
233}
234
235static struct net_device *mlx5_ib_get_netdev(struct ib_device *device,
236 u8 port_num)
237{
238 struct mlx5_ib_dev *ibdev = to_mdev(device);
239 struct net_device *ndev;
Daniel Jurgens32f69e42018-01-04 17:25:36 +0200240 struct mlx5_core_dev *mdev;
Achiad Shochatfc24fc52015-12-23 18:47:17 +0200241
Daniel Jurgens32f69e42018-01-04 17:25:36 +0200242 mdev = mlx5_ib_get_native_port_mdev(ibdev, port_num, NULL);
243 if (!mdev)
244 return NULL;
245
246 ndev = mlx5_lag_get_roce_netdev(mdev);
Aviv Heller88621df2016-09-18 20:48:02 +0300247 if (ndev)
Daniel Jurgens32f69e42018-01-04 17:25:36 +0200248 goto out;
Aviv Heller88621df2016-09-18 20:48:02 +0300249
Achiad Shochatfc24fc52015-12-23 18:47:17 +0200250 /* Ensure ndev does not disappear before we invoke dev_hold()
251 */
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200252 read_lock(&ibdev->roce[port_num - 1].netdev_lock);
253 ndev = ibdev->roce[port_num - 1].netdev;
Achiad Shochatfc24fc52015-12-23 18:47:17 +0200254 if (ndev)
255 dev_hold(ndev);
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +0200256 read_unlock(&ibdev->roce[port_num - 1].netdev_lock);
Achiad Shochatfc24fc52015-12-23 18:47:17 +0200257
Daniel Jurgens32f69e42018-01-04 17:25:36 +0200258out:
259 mlx5_ib_put_native_port_mdev(ibdev, port_num);
Achiad Shochatfc24fc52015-12-23 18:47:17 +0200260 return ndev;
261}
262
Daniel Jurgens32f69e42018-01-04 17:25:36 +0200263struct mlx5_core_dev *mlx5_ib_get_native_port_mdev(struct mlx5_ib_dev *ibdev,
264 u8 ib_port_num,
265 u8 *native_port_num)
266{
267 enum rdma_link_layer ll = mlx5_ib_port_link_layer(&ibdev->ib_dev,
268 ib_port_num);
269 struct mlx5_core_dev *mdev = NULL;
270 struct mlx5_ib_multiport_info *mpi;
271 struct mlx5_ib_port *port;
272
Mark Bloch210b1f72018-03-05 20:09:47 +0200273 if (!mlx5_core_mp_enabled(ibdev->mdev) ||
274 ll != IB_LINK_LAYER_ETHERNET) {
275 if (native_port_num)
276 *native_port_num = ib_port_num;
277 return ibdev->mdev;
278 }
279
Daniel Jurgens32f69e42018-01-04 17:25:36 +0200280 if (native_port_num)
281 *native_port_num = 1;
282
Daniel Jurgens32f69e42018-01-04 17:25:36 +0200283 port = &ibdev->port[ib_port_num - 1];
284 if (!port)
285 return NULL;
286
287 spin_lock(&port->mp.mpi_lock);
288 mpi = ibdev->port[ib_port_num - 1].mp.mpi;
289 if (mpi && !mpi->unaffiliate) {
290 mdev = mpi->mdev;
291 /* If it's the master no need to refcount, it'll exist
292 * as long as the ib_dev exists.
293 */
294 if (!mpi->is_master)
295 mpi->mdev_refcnt++;
296 }
297 spin_unlock(&port->mp.mpi_lock);
298
299 return mdev;
300}
301
302void mlx5_ib_put_native_port_mdev(struct mlx5_ib_dev *ibdev, u8 port_num)
303{
304 enum rdma_link_layer ll = mlx5_ib_port_link_layer(&ibdev->ib_dev,
305 port_num);
306 struct mlx5_ib_multiport_info *mpi;
307 struct mlx5_ib_port *port;
308
309 if (!mlx5_core_mp_enabled(ibdev->mdev) || ll != IB_LINK_LAYER_ETHERNET)
310 return;
311
312 port = &ibdev->port[port_num - 1];
313
314 spin_lock(&port->mp.mpi_lock);
315 mpi = ibdev->port[port_num - 1].mp.mpi;
316 if (mpi->is_master)
317 goto out;
318
319 mpi->mdev_refcnt--;
320 if (mpi->unaffiliate)
321 complete(&mpi->unref_comp);
322out:
323 spin_unlock(&port->mp.mpi_lock);
324}
325
Noa Osherovichf1b65df2017-04-20 20:53:33 +0300326static int translate_eth_proto_oper(u32 eth_proto_oper, u8 *active_speed,
327 u8 *active_width)
328{
329 switch (eth_proto_oper) {
330 case MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII):
331 case MLX5E_PROT_MASK(MLX5E_1000BASE_KX):
332 case MLX5E_PROT_MASK(MLX5E_100BASE_TX):
333 case MLX5E_PROT_MASK(MLX5E_1000BASE_T):
334 *active_width = IB_WIDTH_1X;
335 *active_speed = IB_SPEED_SDR;
336 break;
337 case MLX5E_PROT_MASK(MLX5E_10GBASE_T):
338 case MLX5E_PROT_MASK(MLX5E_10GBASE_CX4):
339 case MLX5E_PROT_MASK(MLX5E_10GBASE_KX4):
340 case MLX5E_PROT_MASK(MLX5E_10GBASE_KR):
341 case MLX5E_PROT_MASK(MLX5E_10GBASE_CR):
342 case MLX5E_PROT_MASK(MLX5E_10GBASE_SR):
343 case MLX5E_PROT_MASK(MLX5E_10GBASE_ER):
344 *active_width = IB_WIDTH_1X;
345 *active_speed = IB_SPEED_QDR;
346 break;
347 case MLX5E_PROT_MASK(MLX5E_25GBASE_CR):
348 case MLX5E_PROT_MASK(MLX5E_25GBASE_KR):
349 case MLX5E_PROT_MASK(MLX5E_25GBASE_SR):
350 *active_width = IB_WIDTH_1X;
351 *active_speed = IB_SPEED_EDR;
352 break;
353 case MLX5E_PROT_MASK(MLX5E_40GBASE_CR4):
354 case MLX5E_PROT_MASK(MLX5E_40GBASE_KR4):
355 case MLX5E_PROT_MASK(MLX5E_40GBASE_SR4):
356 case MLX5E_PROT_MASK(MLX5E_40GBASE_LR4):
357 *active_width = IB_WIDTH_4X;
358 *active_speed = IB_SPEED_QDR;
359 break;
360 case MLX5E_PROT_MASK(MLX5E_50GBASE_CR2):
361 case MLX5E_PROT_MASK(MLX5E_50GBASE_KR2):
362 case MLX5E_PROT_MASK(MLX5E_50GBASE_SR2):
363 *active_width = IB_WIDTH_1X;
364 *active_speed = IB_SPEED_HDR;
365 break;
366 case MLX5E_PROT_MASK(MLX5E_56GBASE_R4):
367 *active_width = IB_WIDTH_4X;
368 *active_speed = IB_SPEED_FDR;
369 break;
370 case MLX5E_PROT_MASK(MLX5E_100GBASE_CR4):
371 case MLX5E_PROT_MASK(MLX5E_100GBASE_SR4):
372 case MLX5E_PROT_MASK(MLX5E_100GBASE_KR4):
373 case MLX5E_PROT_MASK(MLX5E_100GBASE_LR4):
374 *active_width = IB_WIDTH_4X;
375 *active_speed = IB_SPEED_EDR;
376 break;
377 default:
378 return -EINVAL;
379 }
380
381 return 0;
382}
383
Ilan Tayari095b0922017-05-14 16:04:30 +0300384static int mlx5_query_port_roce(struct ib_device *device, u8 port_num,
385 struct ib_port_attr *props)
Achiad Shochat3f89a642015-12-23 18:47:21 +0200386{
387 struct mlx5_ib_dev *dev = to_mdev(device);
Colin Ian Kingda005f92018-01-09 15:55:43 +0000388 struct mlx5_core_dev *mdev;
Aviv Heller88621df2016-09-18 20:48:02 +0300389 struct net_device *ndev, *upper;
Achiad Shochat3f89a642015-12-23 18:47:21 +0200390 enum ib_mtu ndev_ib_mtu;
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +0200391 bool put_mdev = true;
Leon Romanovskyc876a1b2016-01-09 13:06:25 +0200392 u16 qkey_viol_cntr;
Noa Osherovichf1b65df2017-04-20 20:53:33 +0300393 u32 eth_prot_oper;
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +0200394 u8 mdev_port_num;
Ilan Tayari095b0922017-05-14 16:04:30 +0300395 int err;
Achiad Shochat3f89a642015-12-23 18:47:21 +0200396
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +0200397 mdev = mlx5_ib_get_native_port_mdev(dev, port_num, &mdev_port_num);
398 if (!mdev) {
399 /* This means the port isn't affiliated yet. Get the
400 * info for the master port instead.
401 */
402 put_mdev = false;
403 mdev = dev->mdev;
404 mdev_port_num = 1;
405 port_num = 1;
406 }
407
Noa Osherovichf1b65df2017-04-20 20:53:33 +0300408 /* Possible bad flows are checked before filling out props so in case
409 * of an error it will still be zeroed out.
Noa Osherovich50f22fd2017-04-20 20:53:32 +0300410 */
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +0200411 err = mlx5_query_port_eth_proto_oper(mdev, &eth_prot_oper,
412 mdev_port_num);
Ilan Tayari095b0922017-05-14 16:04:30 +0300413 if (err)
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +0200414 goto out;
Noa Osherovichf1b65df2017-04-20 20:53:33 +0300415
Honggang Li7672ed32018-03-16 10:37:13 +0800416 props->active_width = IB_WIDTH_4X;
417 props->active_speed = IB_SPEED_QDR;
418
Noa Osherovichf1b65df2017-04-20 20:53:33 +0300419 translate_eth_proto_oper(eth_prot_oper, &props->active_speed,
420 &props->active_width);
Achiad Shochat3f89a642015-12-23 18:47:21 +0200421
422 props->port_cap_flags |= IB_PORT_CM_SUP;
423 props->port_cap_flags |= IB_PORT_IP_BASED_GIDS;
424
425 props->gid_tbl_len = MLX5_CAP_ROCE(dev->mdev,
426 roce_address_table_size);
427 props->max_mtu = IB_MTU_4096;
428 props->max_msg_sz = 1 << MLX5_CAP_GEN(dev->mdev, log_max_msg);
429 props->pkey_tbl_len = 1;
430 props->state = IB_PORT_DOWN;
431 props->phys_state = 3;
432
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +0200433 mlx5_query_nic_vport_qkey_viol_cntr(mdev, &qkey_viol_cntr);
Leon Romanovskyc876a1b2016-01-09 13:06:25 +0200434 props->qkey_viol_cntr = qkey_viol_cntr;
Achiad Shochat3f89a642015-12-23 18:47:21 +0200435
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +0200436 /* If this is a stub query for an unaffiliated port stop here */
437 if (!put_mdev)
438 goto out;
439
Achiad Shochat3f89a642015-12-23 18:47:21 +0200440 ndev = mlx5_ib_get_netdev(device, port_num);
441 if (!ndev)
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +0200442 goto out;
Achiad Shochat3f89a642015-12-23 18:47:21 +0200443
Aviv Heller88621df2016-09-18 20:48:02 +0300444 if (mlx5_lag_is_active(dev->mdev)) {
445 rcu_read_lock();
446 upper = netdev_master_upper_dev_get_rcu(ndev);
447 if (upper) {
448 dev_put(ndev);
449 ndev = upper;
450 dev_hold(ndev);
451 }
452 rcu_read_unlock();
453 }
454
Achiad Shochat3f89a642015-12-23 18:47:21 +0200455 if (netif_running(ndev) && netif_carrier_ok(ndev)) {
456 props->state = IB_PORT_ACTIVE;
457 props->phys_state = 5;
458 }
459
460 ndev_ib_mtu = iboe_get_mtu(ndev->mtu);
461
462 dev_put(ndev);
463
464 props->active_mtu = min(props->max_mtu, ndev_ib_mtu);
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +0200465out:
466 if (put_mdev)
467 mlx5_ib_put_native_port_mdev(dev, port_num);
468 return err;
Achiad Shochat3f89a642015-12-23 18:47:21 +0200469}
470
Ilan Tayari095b0922017-05-14 16:04:30 +0300471static int set_roce_addr(struct mlx5_ib_dev *dev, u8 port_num,
472 unsigned int index, const union ib_gid *gid,
473 const struct ib_gid_attr *attr)
Achiad Shochat3cca2602015-12-23 18:47:23 +0200474{
Ilan Tayari095b0922017-05-14 16:04:30 +0300475 enum ib_gid_type gid_type = IB_GID_TYPE_IB;
476 u8 roce_version = 0;
477 u8 roce_l3_type = 0;
478 bool vlan = false;
479 u8 mac[ETH_ALEN];
480 u16 vlan_id = 0;
Achiad Shochat3cca2602015-12-23 18:47:23 +0200481
Ilan Tayari095b0922017-05-14 16:04:30 +0300482 if (gid) {
483 gid_type = attr->gid_type;
484 ether_addr_copy(mac, attr->ndev->dev_addr);
Achiad Shochat3cca2602015-12-23 18:47:23 +0200485
Ilan Tayari095b0922017-05-14 16:04:30 +0300486 if (is_vlan_dev(attr->ndev)) {
487 vlan = true;
488 vlan_id = vlan_dev_vlan_id(attr->ndev);
489 }
Achiad Shochat3cca2602015-12-23 18:47:23 +0200490 }
491
Ilan Tayari095b0922017-05-14 16:04:30 +0300492 switch (gid_type) {
Achiad Shochat3cca2602015-12-23 18:47:23 +0200493 case IB_GID_TYPE_IB:
Ilan Tayari095b0922017-05-14 16:04:30 +0300494 roce_version = MLX5_ROCE_VERSION_1;
Achiad Shochat3cca2602015-12-23 18:47:23 +0200495 break;
496 case IB_GID_TYPE_ROCE_UDP_ENCAP:
Ilan Tayari095b0922017-05-14 16:04:30 +0300497 roce_version = MLX5_ROCE_VERSION_2;
498 if (ipv6_addr_v4mapped((void *)gid))
499 roce_l3_type = MLX5_ROCE_L3_TYPE_IPV4;
500 else
501 roce_l3_type = MLX5_ROCE_L3_TYPE_IPV6;
Achiad Shochat3cca2602015-12-23 18:47:23 +0200502 break;
503
504 default:
Ilan Tayari095b0922017-05-14 16:04:30 +0300505 mlx5_ib_warn(dev, "Unexpected GID type %u\n", gid_type);
Achiad Shochat3cca2602015-12-23 18:47:23 +0200506 }
507
Ilan Tayari095b0922017-05-14 16:04:30 +0300508 return mlx5_core_roce_gid_set(dev->mdev, index, roce_version,
509 roce_l3_type, gid->raw, mac, vlan,
Daniel Jurgenscfe4e372018-01-04 17:25:41 +0200510 vlan_id, port_num);
Achiad Shochat3cca2602015-12-23 18:47:23 +0200511}
512
Parav Panditf4df9a72018-06-05 08:40:16 +0300513static int mlx5_ib_add_gid(const struct ib_gid_attr *attr,
Achiad Shochat3cca2602015-12-23 18:47:23 +0200514 __always_unused void **context)
515{
Parav Pandit414448d2018-04-01 15:08:24 +0300516 return set_roce_addr(to_mdev(attr->device), attr->port_num,
Parav Panditf4df9a72018-06-05 08:40:16 +0300517 attr->index, &attr->gid, attr);
Achiad Shochat3cca2602015-12-23 18:47:23 +0200518}
519
Parav Pandit414448d2018-04-01 15:08:24 +0300520static int mlx5_ib_del_gid(const struct ib_gid_attr *attr,
521 __always_unused void **context)
Achiad Shochat3cca2602015-12-23 18:47:23 +0200522{
Parav Pandit414448d2018-04-01 15:08:24 +0300523 return set_roce_addr(to_mdev(attr->device), attr->port_num,
524 attr->index, NULL, NULL);
Achiad Shochat3cca2602015-12-23 18:47:23 +0200525}
526
Parav Pandit47ec3862018-06-13 10:22:06 +0300527__be16 mlx5_get_roce_udp_sport(struct mlx5_ib_dev *dev,
528 const struct ib_gid_attr *attr)
Achiad Shochat2811ba52015-12-23 18:47:24 +0200529{
Parav Pandit47ec3862018-06-13 10:22:06 +0300530 if (attr->gid_type != IB_GID_TYPE_ROCE_UDP_ENCAP)
Achiad Shochat2811ba52015-12-23 18:47:24 +0200531 return 0;
532
533 return cpu_to_be16(MLX5_CAP_ROCE(dev->mdev, r_roce_min_src_udp_port));
534}
535
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300536static int mlx5_use_mad_ifc(struct mlx5_ib_dev *dev)
537{
Noa Osherovich7fae6652016-09-12 19:16:23 +0300538 if (MLX5_CAP_GEN(dev->mdev, port_type) == MLX5_CAP_PORT_TYPE_IB)
539 return !MLX5_CAP_GEN(dev->mdev, ib_virt);
540 return 0;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300541}
542
543enum {
544 MLX5_VPORT_ACCESS_METHOD_MAD,
545 MLX5_VPORT_ACCESS_METHOD_HCA,
546 MLX5_VPORT_ACCESS_METHOD_NIC,
547};
548
549static int mlx5_get_vport_access_method(struct ib_device *ibdev)
550{
551 if (mlx5_use_mad_ifc(to_mdev(ibdev)))
552 return MLX5_VPORT_ACCESS_METHOD_MAD;
553
Achiad Shochatebd61f62015-12-23 18:47:16 +0200554 if (mlx5_ib_port_link_layer(ibdev, 1) ==
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300555 IB_LINK_LAYER_ETHERNET)
556 return MLX5_VPORT_ACCESS_METHOD_NIC;
557
558 return MLX5_VPORT_ACCESS_METHOD_HCA;
559}
560
Eran Ben Elishada7525d2015-12-14 16:34:10 +0200561static void get_atomic_caps(struct mlx5_ib_dev *dev,
Moni Shoua776a3902018-01-02 16:19:33 +0200562 u8 atomic_size_qp,
Eran Ben Elishada7525d2015-12-14 16:34:10 +0200563 struct ib_device_attr *props)
564{
565 u8 tmp;
566 u8 atomic_operations = MLX5_CAP_ATOMIC(dev->mdev, atomic_operations);
Eran Ben Elishada7525d2015-12-14 16:34:10 +0200567 u8 atomic_req_8B_endianness_mode =
Or Gerlitzbd108382017-05-28 15:24:17 +0300568 MLX5_CAP_ATOMIC(dev->mdev, atomic_req_8B_endianness_mode);
Eran Ben Elishada7525d2015-12-14 16:34:10 +0200569
570 /* Check if HW supports 8 bytes standard atomic operations and capable
571 * of host endianness respond
572 */
573 tmp = MLX5_ATOMIC_OPS_CMP_SWAP | MLX5_ATOMIC_OPS_FETCH_ADD;
574 if (((atomic_operations & tmp) == tmp) &&
575 (atomic_size_qp & MLX5_ATOMIC_SIZE_QP_8BYTES) &&
576 (atomic_req_8B_endianness_mode)) {
577 props->atomic_cap = IB_ATOMIC_HCA;
578 } else {
579 props->atomic_cap = IB_ATOMIC_NONE;
580 }
581}
582
Moni Shoua776a3902018-01-02 16:19:33 +0200583static void get_atomic_caps_qp(struct mlx5_ib_dev *dev,
584 struct ib_device_attr *props)
585{
586 u8 atomic_size_qp = MLX5_CAP_ATOMIC(dev->mdev, atomic_size_qp);
587
588 get_atomic_caps(dev, atomic_size_qp, props);
589}
590
591static void get_atomic_caps_dc(struct mlx5_ib_dev *dev,
592 struct ib_device_attr *props)
593{
594 u8 atomic_size_qp = MLX5_CAP_ATOMIC(dev->mdev, atomic_size_dc);
595
596 get_atomic_caps(dev, atomic_size_qp, props);
597}
598
599bool mlx5_ib_dc_atomic_is_supported(struct mlx5_ib_dev *dev)
600{
601 struct ib_device_attr props = {};
602
603 get_atomic_caps_dc(dev, &props);
604 return (props.atomic_cap == IB_ATOMIC_HCA) ? true : false;
605}
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300606static int mlx5_query_system_image_guid(struct ib_device *ibdev,
607 __be64 *sys_image_guid)
608{
609 struct mlx5_ib_dev *dev = to_mdev(ibdev);
610 struct mlx5_core_dev *mdev = dev->mdev;
611 u64 tmp;
612 int err;
613
614 switch (mlx5_get_vport_access_method(ibdev)) {
615 case MLX5_VPORT_ACCESS_METHOD_MAD:
616 return mlx5_query_mad_ifc_system_image_guid(ibdev,
617 sys_image_guid);
618
619 case MLX5_VPORT_ACCESS_METHOD_HCA:
620 err = mlx5_query_hca_vport_system_image_guid(mdev, &tmp);
Achiad Shochat3f89a642015-12-23 18:47:21 +0200621 break;
622
623 case MLX5_VPORT_ACCESS_METHOD_NIC:
624 err = mlx5_query_nic_vport_system_image_guid(mdev, &tmp);
625 break;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300626
627 default:
628 return -EINVAL;
629 }
Achiad Shochat3f89a642015-12-23 18:47:21 +0200630
631 if (!err)
632 *sys_image_guid = cpu_to_be64(tmp);
633
634 return err;
635
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300636}
637
638static int mlx5_query_max_pkeys(struct ib_device *ibdev,
639 u16 *max_pkeys)
640{
641 struct mlx5_ib_dev *dev = to_mdev(ibdev);
642 struct mlx5_core_dev *mdev = dev->mdev;
643
644 switch (mlx5_get_vport_access_method(ibdev)) {
645 case MLX5_VPORT_ACCESS_METHOD_MAD:
646 return mlx5_query_mad_ifc_max_pkeys(ibdev, max_pkeys);
647
648 case MLX5_VPORT_ACCESS_METHOD_HCA:
649 case MLX5_VPORT_ACCESS_METHOD_NIC:
650 *max_pkeys = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(mdev,
651 pkey_table_size));
652 return 0;
653
654 default:
655 return -EINVAL;
656 }
657}
658
659static int mlx5_query_vendor_id(struct ib_device *ibdev,
660 u32 *vendor_id)
661{
662 struct mlx5_ib_dev *dev = to_mdev(ibdev);
663
664 switch (mlx5_get_vport_access_method(ibdev)) {
665 case MLX5_VPORT_ACCESS_METHOD_MAD:
666 return mlx5_query_mad_ifc_vendor_id(ibdev, vendor_id);
667
668 case MLX5_VPORT_ACCESS_METHOD_HCA:
669 case MLX5_VPORT_ACCESS_METHOD_NIC:
670 return mlx5_core_query_vendor_id(dev->mdev, vendor_id);
671
672 default:
673 return -EINVAL;
674 }
675}
676
677static int mlx5_query_node_guid(struct mlx5_ib_dev *dev,
678 __be64 *node_guid)
679{
680 u64 tmp;
681 int err;
682
683 switch (mlx5_get_vport_access_method(&dev->ib_dev)) {
684 case MLX5_VPORT_ACCESS_METHOD_MAD:
685 return mlx5_query_mad_ifc_node_guid(dev, node_guid);
686
687 case MLX5_VPORT_ACCESS_METHOD_HCA:
688 err = mlx5_query_hca_vport_node_guid(dev->mdev, &tmp);
Achiad Shochat3f89a642015-12-23 18:47:21 +0200689 break;
690
691 case MLX5_VPORT_ACCESS_METHOD_NIC:
692 err = mlx5_query_nic_vport_node_guid(dev->mdev, &tmp);
693 break;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300694
695 default:
696 return -EINVAL;
697 }
Achiad Shochat3f89a642015-12-23 18:47:21 +0200698
699 if (!err)
700 *node_guid = cpu_to_be64(tmp);
701
702 return err;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300703}
704
705struct mlx5_reg_node_desc {
Yuval Shaiabd99fde2016-08-25 10:57:07 -0700706 u8 desc[IB_DEVICE_NODE_DESC_MAX];
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300707};
708
709static int mlx5_query_node_desc(struct mlx5_ib_dev *dev, char *node_desc)
710{
711 struct mlx5_reg_node_desc in;
712
713 if (mlx5_use_mad_ifc(dev))
714 return mlx5_query_mad_ifc_node_desc(dev, node_desc);
715
716 memset(&in, 0, sizeof(in));
717
718 return mlx5_core_access_reg(dev->mdev, &in, sizeof(in), node_desc,
719 sizeof(struct mlx5_reg_node_desc),
720 MLX5_REG_NODE_DESC, 0, 0);
721}
722
Eli Cohene126ba92013-07-07 17:25:49 +0300723static int mlx5_ib_query_device(struct ib_device *ibdev,
Matan Barak2528e332015-06-11 16:35:25 +0300724 struct ib_device_attr *props,
725 struct ib_udata *uhw)
Eli Cohene126ba92013-07-07 17:25:49 +0300726{
727 struct mlx5_ib_dev *dev = to_mdev(ibdev);
Saeed Mahameed938fe832015-05-28 22:28:41 +0300728 struct mlx5_core_dev *mdev = dev->mdev;
Eli Cohene126ba92013-07-07 17:25:49 +0300729 int err = -ENOMEM;
Eli Cohen288c01b2016-10-27 16:36:45 +0300730 int max_sq_desc;
Eli Cohene126ba92013-07-07 17:25:49 +0300731 int max_rq_sg;
732 int max_sq_sg;
Sagi Grimberge0238a62015-07-21 14:40:12 +0300733 u64 min_page_size = 1ull << MLX5_CAP_GEN(mdev, log_pg_sz);
Daniel Jurgens85c7c012018-01-04 17:25:43 +0200734 bool raw_support = !mlx5_core_mp_enabled(mdev);
Bodong Wang402ca532016-06-17 15:02:20 +0300735 struct mlx5_ib_query_device_resp resp = {};
736 size_t resp_len;
737 u64 max_tso;
Eli Cohene126ba92013-07-07 17:25:49 +0300738
Bodong Wang402ca532016-06-17 15:02:20 +0300739 resp_len = sizeof(resp.comp_mask) + sizeof(resp.response_length);
740 if (uhw->outlen && uhw->outlen < resp_len)
741 return -EINVAL;
742 else
743 resp.response_length = resp_len;
744
745 if (uhw->inlen && !ib_is_udata_cleared(uhw, 0, uhw->inlen))
Matan Barak2528e332015-06-11 16:35:25 +0300746 return -EINVAL;
747
Eli Cohene126ba92013-07-07 17:25:49 +0300748 memset(props, 0, sizeof(*props));
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300749 err = mlx5_query_system_image_guid(ibdev,
750 &props->sys_image_guid);
751 if (err)
752 return err;
753
754 err = mlx5_query_max_pkeys(ibdev, &props->max_pkeys);
755 if (err)
756 return err;
757
758 err = mlx5_query_vendor_id(ibdev, &props->vendor_id);
759 if (err)
760 return err;
Eli Cohene126ba92013-07-07 17:25:49 +0300761
Jack Morgenstein9603b612014-07-28 23:30:22 +0300762 props->fw_ver = ((u64)fw_rev_maj(dev->mdev) << 32) |
763 (fw_rev_min(dev->mdev) << 16) |
764 fw_rev_sub(dev->mdev);
Eli Cohene126ba92013-07-07 17:25:49 +0300765 props->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT |
766 IB_DEVICE_PORT_ACTIVE_EVENT |
767 IB_DEVICE_SYS_IMAGE_GUID |
Eli Cohen1a4c3a32014-02-06 17:41:25 +0200768 IB_DEVICE_RC_RNR_NAK_GEN;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300769
770 if (MLX5_CAP_GEN(mdev, pkv))
Eli Cohene126ba92013-07-07 17:25:49 +0300771 props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300772 if (MLX5_CAP_GEN(mdev, qkv))
Eli Cohene126ba92013-07-07 17:25:49 +0300773 props->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300774 if (MLX5_CAP_GEN(mdev, apm))
Eli Cohene126ba92013-07-07 17:25:49 +0300775 props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300776 if (MLX5_CAP_GEN(mdev, xrc))
Eli Cohene126ba92013-07-07 17:25:49 +0300777 props->device_cap_flags |= IB_DEVICE_XRC;
Matan Barakd2370e02016-02-29 18:05:30 +0200778 if (MLX5_CAP_GEN(mdev, imaicl)) {
779 props->device_cap_flags |= IB_DEVICE_MEM_WINDOW |
780 IB_DEVICE_MEM_WINDOW_TYPE_2B;
781 props->max_mw = 1 << MLX5_CAP_GEN(mdev, log_max_mkey);
Sagi Grimbergb005d312016-02-29 19:07:33 +0200782 /* We support 'Gappy' memory registration too */
783 props->device_cap_flags |= IB_DEVICE_SG_GAPS_REG;
Matan Barakd2370e02016-02-29 18:05:30 +0200784 }
Eli Cohene126ba92013-07-07 17:25:49 +0300785 props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300786 if (MLX5_CAP_GEN(mdev, sho)) {
Sagi Grimberg2dea9092014-02-23 14:19:13 +0200787 props->device_cap_flags |= IB_DEVICE_SIGNATURE_HANDOVER;
788 /* At this stage no support for signature handover */
789 props->sig_prot_cap = IB_PROT_T10DIF_TYPE_1 |
790 IB_PROT_T10DIF_TYPE_2 |
791 IB_PROT_T10DIF_TYPE_3;
792 props->sig_guard_cap = IB_GUARD_T10DIF_CRC |
793 IB_GUARD_T10DIF_CSUM;
794 }
Saeed Mahameed938fe832015-05-28 22:28:41 +0300795 if (MLX5_CAP_GEN(mdev, block_lb_mc))
Eli Cohenf360d882014-04-02 00:10:16 +0300796 props->device_cap_flags |= IB_DEVICE_BLOCK_MULTICAST_LOOPBACK;
Eli Cohene126ba92013-07-07 17:25:49 +0300797
Daniel Jurgens85c7c012018-01-04 17:25:43 +0200798 if (MLX5_CAP_GEN(dev->mdev, eth_net_offloads) && raw_support) {
Noa Osheroviche8161332017-01-18 15:40:01 +0200799 if (MLX5_CAP_ETH(mdev, csum_cap)) {
800 /* Legacy bit to support old userspace libraries */
Bodong Wang88115fe2015-12-18 13:53:20 +0200801 props->device_cap_flags |= IB_DEVICE_RAW_IP_CSUM;
Noa Osheroviche8161332017-01-18 15:40:01 +0200802 props->raw_packet_caps |= IB_RAW_PACKET_CAP_IP_CSUM;
803 }
804
805 if (MLX5_CAP_ETH(dev->mdev, vlan_cap))
806 props->raw_packet_caps |=
807 IB_RAW_PACKET_CAP_CVLAN_STRIPPING;
Bodong Wang88115fe2015-12-18 13:53:20 +0200808
Bodong Wang402ca532016-06-17 15:02:20 +0300809 if (field_avail(typeof(resp), tso_caps, uhw->outlen)) {
810 max_tso = MLX5_CAP_ETH(mdev, max_lso_cap);
811 if (max_tso) {
812 resp.tso_caps.max_tso = 1 << max_tso;
813 resp.tso_caps.supported_qpts |=
814 1 << IB_QPT_RAW_PACKET;
815 resp.response_length += sizeof(resp.tso_caps);
816 }
817 }
Yishai Hadas31f69a82016-08-28 11:28:45 +0300818
819 if (field_avail(typeof(resp), rss_caps, uhw->outlen)) {
820 resp.rss_caps.rx_hash_function =
821 MLX5_RX_HASH_FUNC_TOEPLITZ;
822 resp.rss_caps.rx_hash_fields_mask =
823 MLX5_RX_HASH_SRC_IPV4 |
824 MLX5_RX_HASH_DST_IPV4 |
825 MLX5_RX_HASH_SRC_IPV6 |
826 MLX5_RX_HASH_DST_IPV6 |
827 MLX5_RX_HASH_SRC_PORT_TCP |
828 MLX5_RX_HASH_DST_PORT_TCP |
829 MLX5_RX_HASH_SRC_PORT_UDP |
Maor Gottlieb4e2b53a2017-12-24 14:51:25 +0200830 MLX5_RX_HASH_DST_PORT_UDP |
831 MLX5_RX_HASH_INNER;
Matan Barak2d93fc82018-03-28 09:27:55 +0300832 if (mlx5_accel_ipsec_device_caps(dev->mdev) &
833 MLX5_ACCEL_IPSEC_CAP_DEVICE)
834 resp.rss_caps.rx_hash_fields_mask |=
835 MLX5_RX_HASH_IPSEC_SPI;
Yishai Hadas31f69a82016-08-28 11:28:45 +0300836 resp.response_length += sizeof(resp.rss_caps);
837 }
838 } else {
839 if (field_avail(typeof(resp), tso_caps, uhw->outlen))
840 resp.response_length += sizeof(resp.tso_caps);
841 if (field_avail(typeof(resp), rss_caps, uhw->outlen))
842 resp.response_length += sizeof(resp.rss_caps);
Bodong Wang402ca532016-06-17 15:02:20 +0300843 }
844
Erez Shitritf0313962016-02-21 16:27:17 +0200845 if (MLX5_CAP_GEN(mdev, ipoib_basic_offloads)) {
846 props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
847 props->device_cap_flags |= IB_DEVICE_UD_TSO;
848 }
849
Maor Gottlieb03404e82017-05-30 10:29:13 +0300850 if (MLX5_CAP_GEN(dev->mdev, rq_delay_drop) &&
Daniel Jurgens85c7c012018-01-04 17:25:43 +0200851 MLX5_CAP_GEN(dev->mdev, general_notification_event) &&
852 raw_support)
Maor Gottlieb03404e82017-05-30 10:29:13 +0300853 props->raw_packet_caps |= IB_RAW_PACKET_CAP_DELAY_DROP;
854
Yishai Hadas1d54f892017-06-08 16:15:11 +0300855 if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads) &&
856 MLX5_CAP_IPOIB_ENHANCED(mdev, csum_cap))
857 props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
858
Majd Dibbinycff5a0f2016-04-17 17:19:38 +0300859 if (MLX5_CAP_GEN(dev->mdev, eth_net_offloads) &&
Daniel Jurgens85c7c012018-01-04 17:25:43 +0200860 MLX5_CAP_ETH(dev->mdev, scatter_fcs) &&
861 raw_support) {
Noa Osheroviche8161332017-01-18 15:40:01 +0200862 /* Legacy bit to support old userspace libraries */
Majd Dibbinycff5a0f2016-04-17 17:19:38 +0300863 props->device_cap_flags |= IB_DEVICE_RAW_SCATTER_FCS;
Noa Osheroviche8161332017-01-18 15:40:01 +0200864 props->raw_packet_caps |= IB_RAW_PACKET_CAP_SCATTER_FCS;
865 }
Majd Dibbinycff5a0f2016-04-17 17:19:38 +0300866
Ariel Levkovich24da0012018-04-05 18:53:27 +0300867 if (MLX5_CAP_DEV_MEM(mdev, memic)) {
868 props->max_dm_size =
869 MLX5_CAP_DEV_MEM(mdev, max_memic_size);
870 }
871
Maor Gottliebda6d6ba32016-06-04 15:15:28 +0300872 if (mlx5_get_flow_namespace(dev->mdev, MLX5_FLOW_NAMESPACE_BYPASS))
873 props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING;
874
Noa Osherovichb1383aa2017-10-29 13:59:45 +0200875 if (MLX5_CAP_GEN(mdev, end_pad))
876 props->device_cap_flags |= IB_DEVICE_PCI_WRITE_END_PADDING;
877
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300878 props->vendor_part_id = mdev->pdev->device;
879 props->hw_ver = mdev->pdev->revision;
Eli Cohene126ba92013-07-07 17:25:49 +0300880
881 props->max_mr_size = ~0ull;
Sagi Grimberge0238a62015-07-21 14:40:12 +0300882 props->page_size_cap = ~(min_page_size - 1);
Saeed Mahameed938fe832015-05-28 22:28:41 +0300883 props->max_qp = 1 << MLX5_CAP_GEN(mdev, log_max_qp);
884 props->max_qp_wr = 1 << MLX5_CAP_GEN(mdev, log_max_qp_sz);
885 max_rq_sg = MLX5_CAP_GEN(mdev, max_wqe_sz_rq) /
886 sizeof(struct mlx5_wqe_data_seg);
Eli Cohen288c01b2016-10-27 16:36:45 +0300887 max_sq_desc = min_t(int, MLX5_CAP_GEN(mdev, max_wqe_sz_sq), 512);
888 max_sq_sg = (max_sq_desc - sizeof(struct mlx5_wqe_ctrl_seg) -
889 sizeof(struct mlx5_wqe_raddr_seg)) /
890 sizeof(struct mlx5_wqe_data_seg);
Steve Wise33023fb2018-06-18 08:05:26 -0700891 props->max_send_sge = max_sq_sg;
892 props->max_recv_sge = max_rq_sg;
Sagi Grimberg986ef952016-03-31 19:03:25 +0300893 props->max_sge_rd = MLX5_MAX_SGE_RD;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300894 props->max_cq = 1 << MLX5_CAP_GEN(mdev, log_max_cq);
Leon Romanovsky9f177682016-01-14 08:11:40 +0200895 props->max_cqe = (1 << MLX5_CAP_GEN(mdev, log_max_cq_sz)) - 1;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300896 props->max_mr = 1 << MLX5_CAP_GEN(mdev, log_max_mkey);
897 props->max_pd = 1 << MLX5_CAP_GEN(mdev, log_max_pd);
898 props->max_qp_rd_atom = 1 << MLX5_CAP_GEN(mdev, log_max_ra_req_qp);
899 props->max_qp_init_rd_atom = 1 << MLX5_CAP_GEN(mdev, log_max_ra_res_qp);
900 props->max_srq = 1 << MLX5_CAP_GEN(mdev, log_max_srq);
901 props->max_srq_wr = (1 << MLX5_CAP_GEN(mdev, log_max_srq_sz)) - 1;
902 props->local_ca_ack_delay = MLX5_CAP_GEN(mdev, local_ca_ack_delay);
Eli Cohene126ba92013-07-07 17:25:49 +0300903 props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp;
Eli Cohene126ba92013-07-07 17:25:49 +0300904 props->max_srq_sge = max_rq_sg - 1;
Sagi Grimberg911f4332016-03-03 13:37:51 +0200905 props->max_fast_reg_page_list_len =
906 1 << MLX5_CAP_GEN(mdev, log_max_klm_list_size);
Moni Shoua776a3902018-01-02 16:19:33 +0200907 get_atomic_caps_qp(dev, props);
Eli Cohen81bea282013-09-11 16:35:30 +0300908 props->masked_atomic_cap = IB_ATOMIC_NONE;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300909 props->max_mcast_grp = 1 << MLX5_CAP_GEN(mdev, log_max_mcg);
910 props->max_mcast_qp_attach = MLX5_CAP_GEN(mdev, max_qp_mcg);
Eli Cohene126ba92013-07-07 17:25:49 +0300911 props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
912 props->max_mcast_grp;
913 props->max_map_per_fmr = INT_MAX; /* no limit in ConnectIB */
Maor Gottlieb86695a62016-10-27 16:36:38 +0300914 props->max_ah = INT_MAX;
Matan Barak7c60bcb2015-12-15 20:30:11 +0200915 props->hca_core_clock = MLX5_CAP_GEN(mdev, device_frequency_khz);
916 props->timestamp_mask = 0x7FFFFFFFFFFFFFFFULL;
Eli Cohene126ba92013-07-07 17:25:49 +0300917
Haggai Eran8cdd3122014-12-11 17:04:20 +0200918#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
Saeed Mahameed938fe832015-05-28 22:28:41 +0300919 if (MLX5_CAP_GEN(mdev, pg))
Haggai Eran8cdd3122014-12-11 17:04:20 +0200920 props->device_cap_flags |= IB_DEVICE_ON_DEMAND_PAGING;
921 props->odp_caps = dev->odp_caps;
922#endif
923
Leon Romanovsky051f2632015-12-20 12:16:11 +0200924 if (MLX5_CAP_GEN(mdev, cd))
925 props->device_cap_flags |= IB_DEVICE_CROSS_CHANNEL;
926
Eli Coheneff901d2016-03-11 22:58:42 +0200927 if (!mlx5_core_is_pf(mdev))
928 props->device_cap_flags |= IB_DEVICE_VIRTUAL_FUNCTION;
929
Yishai Hadas31f69a82016-08-28 11:28:45 +0300930 if (mlx5_ib_port_link_layer(ibdev, 1) ==
Daniel Jurgens85c7c012018-01-04 17:25:43 +0200931 IB_LINK_LAYER_ETHERNET && raw_support) {
Yishai Hadas31f69a82016-08-28 11:28:45 +0300932 props->rss_caps.max_rwq_indirection_tables =
933 1 << MLX5_CAP_GEN(dev->mdev, log_max_rqt);
934 props->rss_caps.max_rwq_indirection_table_size =
935 1 << MLX5_CAP_GEN(dev->mdev, log_max_rqt_size);
936 props->rss_caps.supported_qpts = 1 << IB_QPT_RAW_PACKET;
937 props->max_wq_type_rq =
938 1 << MLX5_CAP_GEN(dev->mdev, log_max_rq);
939 }
940
Artemy Kovalyoveb761892017-08-17 15:52:09 +0300941 if (MLX5_CAP_GEN(mdev, tag_matching)) {
Leon Romanovsky78b1beb2017-09-24 21:46:29 +0300942 props->tm_caps.max_rndv_hdr_size = MLX5_TM_MAX_RNDV_MSG_SIZE;
943 props->tm_caps.max_num_tags =
Artemy Kovalyoveb761892017-08-17 15:52:09 +0300944 (1 << MLX5_CAP_GEN(mdev, log_tag_matching_list_sz)) - 1;
Leon Romanovsky78b1beb2017-09-24 21:46:29 +0300945 props->tm_caps.flags = IB_TM_CAP_RC;
946 props->tm_caps.max_ops =
Artemy Kovalyoveb761892017-08-17 15:52:09 +0300947 1 << MLX5_CAP_GEN(mdev, log_max_qp_sz);
Leon Romanovsky78b1beb2017-09-24 21:46:29 +0300948 props->tm_caps.max_sge = MLX5_TM_MAX_SGE;
Artemy Kovalyoveb761892017-08-17 15:52:09 +0300949 }
950
Yonatan Cohen87ab3f52017-11-13 10:51:18 +0200951 if (MLX5_CAP_GEN(dev->mdev, cq_moderation)) {
952 props->cq_caps.max_cq_moderation_count =
953 MLX5_MAX_CQ_COUNT;
954 props->cq_caps.max_cq_moderation_period =
955 MLX5_MAX_CQ_PERIOD;
956 }
957
Bodong Wang7e43a2a2016-10-31 12:16:44 +0200958 if (field_avail(typeof(resp), cqe_comp_caps, uhw->outlen)) {
Bodong Wang7e43a2a2016-10-31 12:16:44 +0200959 resp.response_length += sizeof(resp.cqe_comp_caps);
Yonatan Cohen572f46b2018-05-27 13:42:33 +0300960
961 if (MLX5_CAP_GEN(dev->mdev, cqe_compression)) {
962 resp.cqe_comp_caps.max_num =
963 MLX5_CAP_GEN(dev->mdev,
964 cqe_compression_max_num);
965
966 resp.cqe_comp_caps.supported_format =
967 MLX5_IB_CQE_RES_FORMAT_HASH |
968 MLX5_IB_CQE_RES_FORMAT_CSUM;
Yonatan Cohen6f1006a2018-05-27 13:42:34 +0300969
970 if (MLX5_CAP_GEN(dev->mdev, mini_cqe_resp_stride_index))
971 resp.cqe_comp_caps.supported_format |=
972 MLX5_IB_CQE_RES_FORMAT_CSUM_STRIDX;
Yonatan Cohen572f46b2018-05-27 13:42:33 +0300973 }
Bodong Wang7e43a2a2016-10-31 12:16:44 +0200974 }
975
Daniel Jurgens85c7c012018-01-04 17:25:43 +0200976 if (field_avail(typeof(resp), packet_pacing_caps, uhw->outlen) &&
977 raw_support) {
Bodong Wangd9491672016-12-01 13:43:13 +0200978 if (MLX5_CAP_QOS(mdev, packet_pacing) &&
979 MLX5_CAP_GEN(mdev, qos)) {
980 resp.packet_pacing_caps.qp_rate_limit_max =
981 MLX5_CAP_QOS(mdev, packet_pacing_max_rate);
982 resp.packet_pacing_caps.qp_rate_limit_min =
983 MLX5_CAP_QOS(mdev, packet_pacing_min_rate);
984 resp.packet_pacing_caps.supported_qpts |=
985 1 << IB_QPT_RAW_PACKET;
Bodong Wang61147f32018-03-19 15:10:30 +0200986 if (MLX5_CAP_QOS(mdev, packet_pacing_burst_bound) &&
987 MLX5_CAP_QOS(mdev, packet_pacing_typical_size))
988 resp.packet_pacing_caps.cap_flags |=
989 MLX5_IB_PP_SUPPORT_BURST;
Bodong Wangd9491672016-12-01 13:43:13 +0200990 }
991 resp.response_length += sizeof(resp.packet_pacing_caps);
992 }
993
Leon Romanovsky9f885202017-01-02 11:37:39 +0200994 if (field_avail(typeof(resp), mlx5_ib_support_multi_pkt_send_wqes,
995 uhw->outlen)) {
Bodong Wang795b6092017-08-17 15:52:34 +0300996 if (MLX5_CAP_ETH(mdev, multi_pkt_send_wqe))
997 resp.mlx5_ib_support_multi_pkt_send_wqes =
998 MLX5_IB_ALLOW_MPW;
Bodong Wang050da902017-08-17 15:52:35 +0300999
1000 if (MLX5_CAP_ETH(mdev, enhanced_multi_pkt_send_wqe))
1001 resp.mlx5_ib_support_multi_pkt_send_wqes |=
1002 MLX5_IB_SUPPORT_EMPW;
1003
Leon Romanovsky9f885202017-01-02 11:37:39 +02001004 resp.response_length +=
1005 sizeof(resp.mlx5_ib_support_multi_pkt_send_wqes);
1006 }
1007
Guy Levide57f2a2017-10-19 08:25:52 +03001008 if (field_avail(typeof(resp), flags, uhw->outlen)) {
1009 resp.response_length += sizeof(resp.flags);
Guy Levi7a0c8f42017-10-19 08:25:53 +03001010
Guy Levide57f2a2017-10-19 08:25:52 +03001011 if (MLX5_CAP_GEN(mdev, cqe_compression_128))
1012 resp.flags |=
1013 MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_COMP;
Guy Levi7a0c8f42017-10-19 08:25:53 +03001014
1015 if (MLX5_CAP_GEN(mdev, cqe_128_always))
1016 resp.flags |= MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_PAD;
Guy Levide57f2a2017-10-19 08:25:52 +03001017 }
Leon Romanovsky9f885202017-01-02 11:37:39 +02001018
Noa Osherovich96dc3fc2017-08-17 15:52:28 +03001019 if (field_avail(typeof(resp), sw_parsing_caps,
1020 uhw->outlen)) {
1021 resp.response_length += sizeof(resp.sw_parsing_caps);
1022 if (MLX5_CAP_ETH(mdev, swp)) {
1023 resp.sw_parsing_caps.sw_parsing_offloads |=
1024 MLX5_IB_SW_PARSING;
1025
1026 if (MLX5_CAP_ETH(mdev, swp_csum))
1027 resp.sw_parsing_caps.sw_parsing_offloads |=
1028 MLX5_IB_SW_PARSING_CSUM;
1029
1030 if (MLX5_CAP_ETH(mdev, swp_lso))
1031 resp.sw_parsing_caps.sw_parsing_offloads |=
1032 MLX5_IB_SW_PARSING_LSO;
1033
1034 if (resp.sw_parsing_caps.sw_parsing_offloads)
1035 resp.sw_parsing_caps.supported_qpts =
1036 BIT(IB_QPT_RAW_PACKET);
1037 }
1038 }
1039
Daniel Jurgens85c7c012018-01-04 17:25:43 +02001040 if (field_avail(typeof(resp), striding_rq_caps, uhw->outlen) &&
1041 raw_support) {
Noa Osherovichb4f34592017-10-17 18:01:12 +03001042 resp.response_length += sizeof(resp.striding_rq_caps);
1043 if (MLX5_CAP_GEN(mdev, striding_rq)) {
1044 resp.striding_rq_caps.min_single_stride_log_num_of_bytes =
1045 MLX5_MIN_SINGLE_STRIDE_LOG_NUM_BYTES;
1046 resp.striding_rq_caps.max_single_stride_log_num_of_bytes =
1047 MLX5_MAX_SINGLE_STRIDE_LOG_NUM_BYTES;
1048 resp.striding_rq_caps.min_single_wqe_log_num_of_strides =
1049 MLX5_MIN_SINGLE_WQE_LOG_NUM_STRIDES;
1050 resp.striding_rq_caps.max_single_wqe_log_num_of_strides =
1051 MLX5_MAX_SINGLE_WQE_LOG_NUM_STRIDES;
1052 resp.striding_rq_caps.supported_qpts =
1053 BIT(IB_QPT_RAW_PACKET);
1054 }
1055 }
1056
Maor Gottliebf95ef6c2017-10-19 08:25:55 +03001057 if (field_avail(typeof(resp), tunnel_offloads_caps,
1058 uhw->outlen)) {
1059 resp.response_length += sizeof(resp.tunnel_offloads_caps);
1060 if (MLX5_CAP_ETH(mdev, tunnel_stateless_vxlan))
1061 resp.tunnel_offloads_caps |=
1062 MLX5_IB_TUNNELED_OFFLOADS_VXLAN;
1063 if (MLX5_CAP_ETH(mdev, tunnel_stateless_geneve_rx))
1064 resp.tunnel_offloads_caps |=
1065 MLX5_IB_TUNNELED_OFFLOADS_GENEVE;
1066 if (MLX5_CAP_ETH(mdev, tunnel_stateless_gre))
1067 resp.tunnel_offloads_caps |=
1068 MLX5_IB_TUNNELED_OFFLOADS_GRE;
Ariel Levkoviche818e252018-05-13 14:33:35 +03001069 if (MLX5_CAP_GEN(mdev, flex_parser_protocols) &
1070 MLX5_FLEX_PROTO_CW_MPLS_GRE)
1071 resp.tunnel_offloads_caps |=
1072 MLX5_IB_TUNNELED_OFFLOADS_MPLS_GRE;
1073 if (MLX5_CAP_GEN(mdev, flex_parser_protocols) &
1074 MLX5_FLEX_PROTO_CW_MPLS_UDP)
1075 resp.tunnel_offloads_caps |=
1076 MLX5_IB_TUNNELED_OFFLOADS_MPLS_UDP;
Maor Gottliebf95ef6c2017-10-19 08:25:55 +03001077 }
1078
Bodong Wang402ca532016-06-17 15:02:20 +03001079 if (uhw->outlen) {
1080 err = ib_copy_to_udata(uhw, &resp, resp.response_length);
1081
1082 if (err)
1083 return err;
1084 }
1085
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001086 return 0;
1087}
Eli Cohene126ba92013-07-07 17:25:49 +03001088
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001089enum mlx5_ib_width {
1090 MLX5_IB_WIDTH_1X = 1 << 0,
1091 MLX5_IB_WIDTH_2X = 1 << 1,
1092 MLX5_IB_WIDTH_4X = 1 << 2,
1093 MLX5_IB_WIDTH_8X = 1 << 3,
1094 MLX5_IB_WIDTH_12X = 1 << 4
1095};
1096
1097static int translate_active_width(struct ib_device *ibdev, u8 active_width,
1098 u8 *ib_width)
1099{
1100 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1101 int err = 0;
1102
1103 if (active_width & MLX5_IB_WIDTH_1X) {
1104 *ib_width = IB_WIDTH_1X;
1105 } else if (active_width & MLX5_IB_WIDTH_2X) {
1106 mlx5_ib_dbg(dev, "active_width %d is not supported by IB spec\n",
1107 (int)active_width);
1108 err = -EINVAL;
1109 } else if (active_width & MLX5_IB_WIDTH_4X) {
1110 *ib_width = IB_WIDTH_4X;
1111 } else if (active_width & MLX5_IB_WIDTH_8X) {
1112 *ib_width = IB_WIDTH_8X;
1113 } else if (active_width & MLX5_IB_WIDTH_12X) {
1114 *ib_width = IB_WIDTH_12X;
1115 } else {
1116 mlx5_ib_dbg(dev, "Invalid active_width %d\n",
1117 (int)active_width);
1118 err = -EINVAL;
1119 }
1120
1121 return err;
1122}
1123
1124static int mlx5_mtu_to_ib_mtu(int mtu)
1125{
1126 switch (mtu) {
1127 case 256: return 1;
1128 case 512: return 2;
1129 case 1024: return 3;
1130 case 2048: return 4;
1131 case 4096: return 5;
1132 default:
1133 pr_warn("invalid mtu\n");
1134 return -1;
1135 }
1136}
1137
1138enum ib_max_vl_num {
1139 __IB_MAX_VL_0 = 1,
1140 __IB_MAX_VL_0_1 = 2,
1141 __IB_MAX_VL_0_3 = 3,
1142 __IB_MAX_VL_0_7 = 4,
1143 __IB_MAX_VL_0_14 = 5,
1144};
1145
1146enum mlx5_vl_hw_cap {
1147 MLX5_VL_HW_0 = 1,
1148 MLX5_VL_HW_0_1 = 2,
1149 MLX5_VL_HW_0_2 = 3,
1150 MLX5_VL_HW_0_3 = 4,
1151 MLX5_VL_HW_0_4 = 5,
1152 MLX5_VL_HW_0_5 = 6,
1153 MLX5_VL_HW_0_6 = 7,
1154 MLX5_VL_HW_0_7 = 8,
1155 MLX5_VL_HW_0_14 = 15
1156};
1157
1158static int translate_max_vl_num(struct ib_device *ibdev, u8 vl_hw_cap,
1159 u8 *max_vl_num)
1160{
1161 switch (vl_hw_cap) {
1162 case MLX5_VL_HW_0:
1163 *max_vl_num = __IB_MAX_VL_0;
1164 break;
1165 case MLX5_VL_HW_0_1:
1166 *max_vl_num = __IB_MAX_VL_0_1;
1167 break;
1168 case MLX5_VL_HW_0_3:
1169 *max_vl_num = __IB_MAX_VL_0_3;
1170 break;
1171 case MLX5_VL_HW_0_7:
1172 *max_vl_num = __IB_MAX_VL_0_7;
1173 break;
1174 case MLX5_VL_HW_0_14:
1175 *max_vl_num = __IB_MAX_VL_0_14;
1176 break;
1177
1178 default:
1179 return -EINVAL;
1180 }
1181
1182 return 0;
1183}
1184
1185static int mlx5_query_hca_port(struct ib_device *ibdev, u8 port,
1186 struct ib_port_attr *props)
1187{
1188 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1189 struct mlx5_core_dev *mdev = dev->mdev;
1190 struct mlx5_hca_vport_context *rep;
Saeed Mahameed046339e2016-04-22 00:33:03 +03001191 u16 max_mtu;
1192 u16 oper_mtu;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001193 int err;
1194 u8 ib_link_width_oper;
1195 u8 vl_hw_cap;
1196
1197 rep = kzalloc(sizeof(*rep), GFP_KERNEL);
1198 if (!rep) {
1199 err = -ENOMEM;
1200 goto out;
1201 }
1202
Or Gerlitzc4550c62017-01-24 13:02:39 +02001203 /* props being zeroed by the caller, avoid zeroing it here */
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001204
1205 err = mlx5_query_hca_vport_context(mdev, 0, port, 0, rep);
1206 if (err)
1207 goto out;
1208
1209 props->lid = rep->lid;
1210 props->lmc = rep->lmc;
1211 props->sm_lid = rep->sm_lid;
1212 props->sm_sl = rep->sm_sl;
1213 props->state = rep->vport_state;
1214 props->phys_state = rep->port_physical_state;
1215 props->port_cap_flags = rep->cap_mask1;
1216 props->gid_tbl_len = mlx5_get_gid_table_len(MLX5_CAP_GEN(mdev, gid_table_size));
1217 props->max_msg_sz = 1 << MLX5_CAP_GEN(mdev, log_max_msg);
1218 props->pkey_tbl_len = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(mdev, pkey_table_size));
1219 props->bad_pkey_cntr = rep->pkey_violation_counter;
1220 props->qkey_viol_cntr = rep->qkey_violation_counter;
1221 props->subnet_timeout = rep->subnet_timeout;
1222 props->init_type_reply = rep->init_type_reply;
Eli Coheneff901d2016-03-11 22:58:42 +02001223 props->grh_required = rep->grh_required;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001224
1225 err = mlx5_query_port_link_width_oper(mdev, &ib_link_width_oper, port);
1226 if (err)
1227 goto out;
1228
1229 err = translate_active_width(ibdev, ib_link_width_oper,
1230 &props->active_width);
1231 if (err)
1232 goto out;
Noa Osherovichd5beb7f2016-06-02 10:47:53 +03001233 err = mlx5_query_port_ib_proto_oper(mdev, &props->active_speed, port);
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001234 if (err)
1235 goto out;
1236
Saeed Mahameedfacc9692015-06-11 14:47:27 +03001237 mlx5_query_port_max_mtu(mdev, &max_mtu, port);
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001238
1239 props->max_mtu = mlx5_mtu_to_ib_mtu(max_mtu);
1240
Saeed Mahameedfacc9692015-06-11 14:47:27 +03001241 mlx5_query_port_oper_mtu(mdev, &oper_mtu, port);
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001242
1243 props->active_mtu = mlx5_mtu_to_ib_mtu(oper_mtu);
1244
1245 err = mlx5_query_port_vl_hw_cap(mdev, &vl_hw_cap, port);
1246 if (err)
1247 goto out;
1248
1249 err = translate_max_vl_num(ibdev, vl_hw_cap,
1250 &props->max_vl_num);
1251out:
1252 kfree(rep);
Eli Cohene126ba92013-07-07 17:25:49 +03001253 return err;
1254}
1255
1256int mlx5_ib_query_port(struct ib_device *ibdev, u8 port,
1257 struct ib_port_attr *props)
1258{
Ilan Tayari095b0922017-05-14 16:04:30 +03001259 unsigned int count;
1260 int ret;
1261
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001262 switch (mlx5_get_vport_access_method(ibdev)) {
1263 case MLX5_VPORT_ACCESS_METHOD_MAD:
Ilan Tayari095b0922017-05-14 16:04:30 +03001264 ret = mlx5_query_mad_ifc_port(ibdev, port, props);
1265 break;
Eli Cohene126ba92013-07-07 17:25:49 +03001266
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001267 case MLX5_VPORT_ACCESS_METHOD_HCA:
Ilan Tayari095b0922017-05-14 16:04:30 +03001268 ret = mlx5_query_hca_port(ibdev, port, props);
1269 break;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001270
Achiad Shochat3f89a642015-12-23 18:47:21 +02001271 case MLX5_VPORT_ACCESS_METHOD_NIC:
Ilan Tayari095b0922017-05-14 16:04:30 +03001272 ret = mlx5_query_port_roce(ibdev, port, props);
1273 break;
Achiad Shochat3f89a642015-12-23 18:47:21 +02001274
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001275 default:
Ilan Tayari095b0922017-05-14 16:04:30 +03001276 ret = -EINVAL;
Eli Cohene126ba92013-07-07 17:25:49 +03001277 }
Ilan Tayari095b0922017-05-14 16:04:30 +03001278
1279 if (!ret && props) {
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001280 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1281 struct mlx5_core_dev *mdev;
1282 bool put_mdev = true;
1283
1284 mdev = mlx5_ib_get_native_port_mdev(dev, port, NULL);
1285 if (!mdev) {
1286 /* If the port isn't affiliated yet query the master.
1287 * The master and slave will have the same values.
1288 */
1289 mdev = dev->mdev;
1290 port = 1;
1291 put_mdev = false;
1292 }
1293 count = mlx5_core_reserved_gids_count(mdev);
1294 if (put_mdev)
1295 mlx5_ib_put_native_port_mdev(dev, port);
Ilan Tayari095b0922017-05-14 16:04:30 +03001296 props->gid_tbl_len -= count;
1297 }
1298 return ret;
Eli Cohene126ba92013-07-07 17:25:49 +03001299}
1300
Mark Bloch8e6efa32017-11-06 12:22:13 +00001301static int mlx5_ib_rep_query_port(struct ib_device *ibdev, u8 port,
1302 struct ib_port_attr *props)
1303{
1304 int ret;
1305
1306 /* Only link layer == ethernet is valid for representors */
1307 ret = mlx5_query_port_roce(ibdev, port, props);
1308 if (ret || !props)
1309 return ret;
1310
1311 /* We don't support GIDS */
1312 props->gid_tbl_len = 0;
1313
1314 return ret;
1315}
1316
Eli Cohene126ba92013-07-07 17:25:49 +03001317static int mlx5_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
1318 union ib_gid *gid)
1319{
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001320 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1321 struct mlx5_core_dev *mdev = dev->mdev;
Eli Cohene126ba92013-07-07 17:25:49 +03001322
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001323 switch (mlx5_get_vport_access_method(ibdev)) {
1324 case MLX5_VPORT_ACCESS_METHOD_MAD:
1325 return mlx5_query_mad_ifc_gids(ibdev, port, index, gid);
Eli Cohene126ba92013-07-07 17:25:49 +03001326
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001327 case MLX5_VPORT_ACCESS_METHOD_HCA:
1328 return mlx5_query_hca_vport_gid(mdev, 0, port, 0, index, gid);
Eli Cohene126ba92013-07-07 17:25:49 +03001329
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001330 default:
1331 return -EINVAL;
1332 }
Eli Cohene126ba92013-07-07 17:25:49 +03001333
Eli Cohene126ba92013-07-07 17:25:49 +03001334}
1335
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001336static int mlx5_query_hca_nic_pkey(struct ib_device *ibdev, u8 port,
1337 u16 index, u16 *pkey)
1338{
1339 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1340 struct mlx5_core_dev *mdev;
1341 bool put_mdev = true;
1342 u8 mdev_port_num;
1343 int err;
1344
1345 mdev = mlx5_ib_get_native_port_mdev(dev, port, &mdev_port_num);
1346 if (!mdev) {
1347 /* The port isn't affiliated yet, get the PKey from the master
1348 * port. For RoCE the PKey tables will be the same.
1349 */
1350 put_mdev = false;
1351 mdev = dev->mdev;
1352 mdev_port_num = 1;
1353 }
1354
1355 err = mlx5_query_hca_vport_pkey(mdev, 0, mdev_port_num, 0,
1356 index, pkey);
1357 if (put_mdev)
1358 mlx5_ib_put_native_port_mdev(dev, port);
1359
1360 return err;
1361}
1362
Eli Cohene126ba92013-07-07 17:25:49 +03001363static int mlx5_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
1364 u16 *pkey)
1365{
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001366 switch (mlx5_get_vport_access_method(ibdev)) {
1367 case MLX5_VPORT_ACCESS_METHOD_MAD:
1368 return mlx5_query_mad_ifc_pkey(ibdev, port, index, pkey);
Eli Cohene126ba92013-07-07 17:25:49 +03001369
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001370 case MLX5_VPORT_ACCESS_METHOD_HCA:
1371 case MLX5_VPORT_ACCESS_METHOD_NIC:
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001372 return mlx5_query_hca_nic_pkey(ibdev, port, index, pkey);
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001373 default:
1374 return -EINVAL;
1375 }
Eli Cohene126ba92013-07-07 17:25:49 +03001376}
1377
Eli Cohene126ba92013-07-07 17:25:49 +03001378static int mlx5_ib_modify_device(struct ib_device *ibdev, int mask,
1379 struct ib_device_modify *props)
1380{
1381 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1382 struct mlx5_reg_node_desc in;
1383 struct mlx5_reg_node_desc out;
1384 int err;
1385
1386 if (mask & ~IB_DEVICE_MODIFY_NODE_DESC)
1387 return -EOPNOTSUPP;
1388
1389 if (!(mask & IB_DEVICE_MODIFY_NODE_DESC))
1390 return 0;
1391
1392 /*
1393 * If possible, pass node desc to FW, so it can generate
1394 * a 144 trap. If cmd fails, just ignore.
1395 */
Yuval Shaiabd99fde2016-08-25 10:57:07 -07001396 memcpy(&in, props->node_desc, IB_DEVICE_NODE_DESC_MAX);
Jack Morgenstein9603b612014-07-28 23:30:22 +03001397 err = mlx5_core_access_reg(dev->mdev, &in, sizeof(in), &out,
Eli Cohene126ba92013-07-07 17:25:49 +03001398 sizeof(out), MLX5_REG_NODE_DESC, 0, 1);
1399 if (err)
1400 return err;
1401
Yuval Shaiabd99fde2016-08-25 10:57:07 -07001402 memcpy(ibdev->node_desc, props->node_desc, IB_DEVICE_NODE_DESC_MAX);
Eli Cohene126ba92013-07-07 17:25:49 +03001403
1404 return err;
1405}
1406
Eli Cohencdbe33d2017-02-14 07:25:38 +02001407static int set_port_caps_atomic(struct mlx5_ib_dev *dev, u8 port_num, u32 mask,
1408 u32 value)
1409{
1410 struct mlx5_hca_vport_context ctx = {};
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001411 struct mlx5_core_dev *mdev;
1412 u8 mdev_port_num;
Eli Cohencdbe33d2017-02-14 07:25:38 +02001413 int err;
1414
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001415 mdev = mlx5_ib_get_native_port_mdev(dev, port_num, &mdev_port_num);
1416 if (!mdev)
1417 return -ENODEV;
1418
1419 err = mlx5_query_hca_vport_context(mdev, 0, mdev_port_num, 0, &ctx);
Eli Cohencdbe33d2017-02-14 07:25:38 +02001420 if (err)
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001421 goto out;
Eli Cohencdbe33d2017-02-14 07:25:38 +02001422
1423 if (~ctx.cap_mask1_perm & mask) {
1424 mlx5_ib_warn(dev, "trying to change bitmask 0x%X but change supported 0x%X\n",
1425 mask, ctx.cap_mask1_perm);
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001426 err = -EINVAL;
1427 goto out;
Eli Cohencdbe33d2017-02-14 07:25:38 +02001428 }
1429
1430 ctx.cap_mask1 = value;
1431 ctx.cap_mask1_perm = mask;
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001432 err = mlx5_core_modify_hca_vport_context(mdev, 0, mdev_port_num,
1433 0, &ctx);
1434
1435out:
1436 mlx5_ib_put_native_port_mdev(dev, port_num);
Eli Cohencdbe33d2017-02-14 07:25:38 +02001437
1438 return err;
1439}
1440
Eli Cohene126ba92013-07-07 17:25:49 +03001441static int mlx5_ib_modify_port(struct ib_device *ibdev, u8 port, int mask,
1442 struct ib_port_modify *props)
1443{
1444 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1445 struct ib_port_attr attr;
1446 u32 tmp;
1447 int err;
Eli Cohencdbe33d2017-02-14 07:25:38 +02001448 u32 change_mask;
1449 u32 value;
1450 bool is_ib = (mlx5_ib_port_link_layer(ibdev, port) ==
1451 IB_LINK_LAYER_INFINIBAND);
1452
Majd Dibbinyec255872017-08-23 08:35:42 +03001453 /* CM layer calls ib_modify_port() regardless of the link layer. For
1454 * Ethernet ports, qkey violation and Port capabilities are meaningless.
1455 */
1456 if (!is_ib)
1457 return 0;
1458
Eli Cohencdbe33d2017-02-14 07:25:38 +02001459 if (MLX5_CAP_GEN(dev->mdev, ib_virt) && is_ib) {
1460 change_mask = props->clr_port_cap_mask | props->set_port_cap_mask;
1461 value = ~props->clr_port_cap_mask | props->set_port_cap_mask;
1462 return set_port_caps_atomic(dev, port, change_mask, value);
1463 }
Eli Cohene126ba92013-07-07 17:25:49 +03001464
1465 mutex_lock(&dev->cap_mask_mutex);
1466
Or Gerlitzc4550c62017-01-24 13:02:39 +02001467 err = ib_query_port(ibdev, port, &attr);
Eli Cohene126ba92013-07-07 17:25:49 +03001468 if (err)
1469 goto out;
1470
1471 tmp = (attr.port_cap_flags | props->set_port_cap_mask) &
1472 ~props->clr_port_cap_mask;
1473
Jack Morgenstein9603b612014-07-28 23:30:22 +03001474 err = mlx5_set_port_caps(dev->mdev, port, tmp);
Eli Cohene126ba92013-07-07 17:25:49 +03001475
1476out:
1477 mutex_unlock(&dev->cap_mask_mutex);
1478 return err;
1479}
1480
Eli Cohen30aa60b2017-01-03 23:55:27 +02001481static void print_lib_caps(struct mlx5_ib_dev *dev, u64 caps)
1482{
1483 mlx5_ib_dbg(dev, "MLX5_LIB_CAP_4K_UAR = %s\n",
1484 caps & MLX5_LIB_CAP_4K_UAR ? "y" : "n");
1485}
1486
Yishai Hadas31a78a52017-12-24 16:31:34 +02001487static u16 calc_dynamic_bfregs(int uars_per_sys_page)
1488{
1489 /* Large page with non 4k uar support might limit the dynamic size */
1490 if (uars_per_sys_page == 1 && PAGE_SIZE > 4096)
1491 return MLX5_MIN_DYN_BFREGS;
1492
1493 return MLX5_MAX_DYN_BFREGS;
1494}
1495
Eli Cohenb037c292017-01-03 23:55:26 +02001496static int calc_total_bfregs(struct mlx5_ib_dev *dev, bool lib_uar_4k,
1497 struct mlx5_ib_alloc_ucontext_req_v2 *req,
Yishai Hadas31a78a52017-12-24 16:31:34 +02001498 struct mlx5_bfreg_info *bfregi)
Eli Cohenb037c292017-01-03 23:55:26 +02001499{
1500 int uars_per_sys_page;
1501 int bfregs_per_sys_page;
1502 int ref_bfregs = req->total_num_bfregs;
1503
1504 if (req->total_num_bfregs == 0)
1505 return -EINVAL;
1506
1507 BUILD_BUG_ON(MLX5_MAX_BFREGS % MLX5_NON_FP_BFREGS_IN_PAGE);
1508 BUILD_BUG_ON(MLX5_MAX_BFREGS < MLX5_NON_FP_BFREGS_IN_PAGE);
1509
1510 if (req->total_num_bfregs > MLX5_MAX_BFREGS)
1511 return -ENOMEM;
1512
1513 uars_per_sys_page = get_uars_per_sys_page(dev, lib_uar_4k);
1514 bfregs_per_sys_page = uars_per_sys_page * MLX5_NON_FP_BFREGS_PER_UAR;
Yishai Hadas31a78a52017-12-24 16:31:34 +02001515 /* This holds the required static allocation asked by the user */
Eli Cohenb037c292017-01-03 23:55:26 +02001516 req->total_num_bfregs = ALIGN(req->total_num_bfregs, bfregs_per_sys_page);
Eli Cohenb037c292017-01-03 23:55:26 +02001517 if (req->num_low_latency_bfregs > req->total_num_bfregs - 1)
1518 return -EINVAL;
1519
Yishai Hadas31a78a52017-12-24 16:31:34 +02001520 bfregi->num_static_sys_pages = req->total_num_bfregs / bfregs_per_sys_page;
1521 bfregi->num_dyn_bfregs = ALIGN(calc_dynamic_bfregs(uars_per_sys_page), bfregs_per_sys_page);
1522 bfregi->total_num_bfregs = req->total_num_bfregs + bfregi->num_dyn_bfregs;
1523 bfregi->num_sys_pages = bfregi->total_num_bfregs / bfregs_per_sys_page;
1524
1525 mlx5_ib_dbg(dev, "uar_4k: fw support %s, lib support %s, user requested %d bfregs, allocated %d, total bfregs %d, using %d sys pages\n",
Eli Cohenb037c292017-01-03 23:55:26 +02001526 MLX5_CAP_GEN(dev->mdev, uar_4k) ? "yes" : "no",
1527 lib_uar_4k ? "yes" : "no", ref_bfregs,
Yishai Hadas31a78a52017-12-24 16:31:34 +02001528 req->total_num_bfregs, bfregi->total_num_bfregs,
1529 bfregi->num_sys_pages);
Eli Cohenb037c292017-01-03 23:55:26 +02001530
1531 return 0;
1532}
1533
1534static int allocate_uars(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *context)
1535{
1536 struct mlx5_bfreg_info *bfregi;
1537 int err;
1538 int i;
1539
1540 bfregi = &context->bfregi;
Yishai Hadas31a78a52017-12-24 16:31:34 +02001541 for (i = 0; i < bfregi->num_static_sys_pages; i++) {
Eli Cohenb037c292017-01-03 23:55:26 +02001542 err = mlx5_cmd_alloc_uar(dev->mdev, &bfregi->sys_pages[i]);
1543 if (err)
1544 goto error;
1545
1546 mlx5_ib_dbg(dev, "allocated uar %d\n", bfregi->sys_pages[i]);
1547 }
Yishai Hadas4ed131d2017-12-24 16:31:35 +02001548
1549 for (i = bfregi->num_static_sys_pages; i < bfregi->num_sys_pages; i++)
1550 bfregi->sys_pages[i] = MLX5_IB_INVALID_UAR_INDEX;
1551
Eli Cohenb037c292017-01-03 23:55:26 +02001552 return 0;
1553
1554error:
1555 for (--i; i >= 0; i--)
1556 if (mlx5_cmd_free_uar(dev->mdev, bfregi->sys_pages[i]))
1557 mlx5_ib_warn(dev, "failed to free uar %d\n", i);
1558
1559 return err;
1560}
1561
1562static int deallocate_uars(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *context)
1563{
1564 struct mlx5_bfreg_info *bfregi;
1565 int err;
1566 int i;
1567
1568 bfregi = &context->bfregi;
Yishai Hadas4ed131d2017-12-24 16:31:35 +02001569 for (i = 0; i < bfregi->num_sys_pages; i++) {
1570 if (i < bfregi->num_static_sys_pages ||
1571 bfregi->sys_pages[i] != MLX5_IB_INVALID_UAR_INDEX) {
1572 err = mlx5_cmd_free_uar(dev->mdev, bfregi->sys_pages[i]);
1573 if (err) {
1574 mlx5_ib_warn(dev, "failed to free uar %d, err=%d\n", i, err);
1575 return err;
1576 }
Eli Cohenb037c292017-01-03 23:55:26 +02001577 }
1578 }
Yishai Hadas4ed131d2017-12-24 16:31:35 +02001579
Eli Cohenb037c292017-01-03 23:55:26 +02001580 return 0;
1581}
1582
Huy Nguyenc85023e2017-05-30 09:42:54 +03001583static int mlx5_ib_alloc_transport_domain(struct mlx5_ib_dev *dev, u32 *tdn)
1584{
1585 int err;
1586
1587 err = mlx5_core_alloc_transport_domain(dev->mdev, tdn);
1588 if (err)
1589 return err;
1590
1591 if ((MLX5_CAP_GEN(dev->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) ||
Eran Ben Elisha8978cc92018-01-09 11:41:10 +02001592 (!MLX5_CAP_GEN(dev->mdev, disable_local_lb_uc) &&
1593 !MLX5_CAP_GEN(dev->mdev, disable_local_lb_mc)))
Huy Nguyenc85023e2017-05-30 09:42:54 +03001594 return err;
1595
1596 mutex_lock(&dev->lb_mutex);
1597 dev->user_td++;
1598
1599 if (dev->user_td == 2)
1600 err = mlx5_nic_vport_update_local_lb(dev->mdev, true);
1601
1602 mutex_unlock(&dev->lb_mutex);
1603 return err;
1604}
1605
1606static void mlx5_ib_dealloc_transport_domain(struct mlx5_ib_dev *dev, u32 tdn)
1607{
1608 mlx5_core_dealloc_transport_domain(dev->mdev, tdn);
1609
1610 if ((MLX5_CAP_GEN(dev->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) ||
Eran Ben Elisha8978cc92018-01-09 11:41:10 +02001611 (!MLX5_CAP_GEN(dev->mdev, disable_local_lb_uc) &&
1612 !MLX5_CAP_GEN(dev->mdev, disable_local_lb_mc)))
Huy Nguyenc85023e2017-05-30 09:42:54 +03001613 return;
1614
1615 mutex_lock(&dev->lb_mutex);
1616 dev->user_td--;
1617
1618 if (dev->user_td < 2)
1619 mlx5_nic_vport_update_local_lb(dev->mdev, false);
1620
1621 mutex_unlock(&dev->lb_mutex);
1622}
1623
Eli Cohene126ba92013-07-07 17:25:49 +03001624static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
1625 struct ib_udata *udata)
1626{
1627 struct mlx5_ib_dev *dev = to_mdev(ibdev);
Matan Barakb368d7c2015-12-15 20:30:12 +02001628 struct mlx5_ib_alloc_ucontext_req_v2 req = {};
1629 struct mlx5_ib_alloc_ucontext_resp resp = {};
Feras Daoud5c99eae2018-01-16 20:08:41 +02001630 struct mlx5_core_dev *mdev = dev->mdev;
Eli Cohene126ba92013-07-07 17:25:49 +03001631 struct mlx5_ib_ucontext *context;
Eli Cohen2f5ff262017-01-03 23:55:21 +02001632 struct mlx5_bfreg_info *bfregi;
Eli Cohen78c0f982014-01-30 13:49:48 +02001633 int ver;
Eli Cohene126ba92013-07-07 17:25:49 +03001634 int err;
Majd Dibbinya168a41c2016-01-28 17:51:47 +02001635 size_t min_req_v2 = offsetof(struct mlx5_ib_alloc_ucontext_req_v2,
1636 max_cqe_version);
Eli Cohenb037c292017-01-03 23:55:26 +02001637 bool lib_uar_4k;
Eli Cohene126ba92013-07-07 17:25:49 +03001638
1639 if (!dev->ib_active)
1640 return ERR_PTR(-EAGAIN);
1641
Amrani, Rame0931112017-06-27 17:04:42 +03001642 if (udata->inlen == sizeof(struct mlx5_ib_alloc_ucontext_req))
Eli Cohen78c0f982014-01-30 13:49:48 +02001643 ver = 0;
Amrani, Rame0931112017-06-27 17:04:42 +03001644 else if (udata->inlen >= min_req_v2)
Eli Cohen78c0f982014-01-30 13:49:48 +02001645 ver = 2;
1646 else
1647 return ERR_PTR(-EINVAL);
1648
Amrani, Rame0931112017-06-27 17:04:42 +03001649 err = ib_copy_from_udata(&req, udata, min(udata->inlen, sizeof(req)));
Eli Cohene126ba92013-07-07 17:25:49 +03001650 if (err)
1651 return ERR_PTR(err);
1652
Yishai Hadasa8b92ca2018-06-17 12:59:57 +03001653 if (req.flags & ~MLX5_IB_ALLOC_UCTX_DEVX)
1654 return ERR_PTR(-EOPNOTSUPP);
Eli Cohen78c0f982014-01-30 13:49:48 +02001655
Haggai Abramovskyf72300c2016-01-14 19:12:58 +02001656 if (req.comp_mask || req.reserved0 || req.reserved1 || req.reserved2)
Matan Barakb368d7c2015-12-15 20:30:12 +02001657 return ERR_PTR(-EOPNOTSUPP);
1658
Eli Cohen2f5ff262017-01-03 23:55:21 +02001659 req.total_num_bfregs = ALIGN(req.total_num_bfregs,
1660 MLX5_NON_FP_BFREGS_PER_UAR);
1661 if (req.num_low_latency_bfregs > req.total_num_bfregs - 1)
Eli Cohene126ba92013-07-07 17:25:49 +03001662 return ERR_PTR(-EINVAL);
1663
Saeed Mahameed938fe832015-05-28 22:28:41 +03001664 resp.qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp);
Noa Osherovich2cc6ad52016-06-04 15:15:33 +03001665 if (mlx5_core_is_pf(dev->mdev) && MLX5_CAP_GEN(dev->mdev, bf))
1666 resp.bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size);
Daniel Jurgensb47bd6e2016-10-25 18:36:24 +03001667 resp.cache_line_size = cache_line_size();
Saeed Mahameed938fe832015-05-28 22:28:41 +03001668 resp.max_sq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq);
1669 resp.max_rq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq);
1670 resp.max_send_wqebb = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz);
1671 resp.max_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz);
1672 resp.max_srq_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_srq_sz);
Haggai Abramovskyf72300c2016-01-14 19:12:58 +02001673 resp.cqe_version = min_t(__u8,
1674 (__u8)MLX5_CAP_GEN(dev->mdev, cqe_version),
1675 req.max_cqe_version);
Eli Cohen30aa60b2017-01-03 23:55:27 +02001676 resp.log_uar_size = MLX5_CAP_GEN(dev->mdev, uar_4k) ?
1677 MLX5_ADAPTER_PAGE_SHIFT : PAGE_SHIFT;
1678 resp.num_uars_per_page = MLX5_CAP_GEN(dev->mdev, uar_4k) ?
1679 MLX5_CAP_GEN(dev->mdev, num_of_uars_per_page) : 1;
Matan Barakb368d7c2015-12-15 20:30:12 +02001680 resp.response_length = min(offsetof(typeof(resp), response_length) +
1681 sizeof(resp.response_length), udata->outlen);
Eli Cohene126ba92013-07-07 17:25:49 +03001682
Matan Barakc03faa52018-03-28 09:27:54 +03001683 if (mlx5_accel_ipsec_device_caps(dev->mdev) & MLX5_ACCEL_IPSEC_CAP_DEVICE) {
1684 if (mlx5_get_flow_namespace(dev->mdev, MLX5_FLOW_NAMESPACE_EGRESS))
1685 resp.flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM;
1686 if (mlx5_accel_ipsec_device_caps(dev->mdev) & MLX5_ACCEL_IPSEC_CAP_REQUIRED_METADATA)
1687 resp.flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_REQ_METADATA;
1688 if (MLX5_CAP_FLOWTABLE(dev->mdev, flow_table_properties_nic_receive.ft_field_support.outer_esp_spi))
1689 resp.flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_SPI_STEERING;
1690 if (mlx5_accel_ipsec_device_caps(dev->mdev) & MLX5_ACCEL_IPSEC_CAP_TX_IV_IS_ESN)
1691 resp.flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_TX_IV_IS_ESN;
1692 /* MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_FULL_OFFLOAD is currently always 0 */
1693 }
1694
Eli Cohene126ba92013-07-07 17:25:49 +03001695 context = kzalloc(sizeof(*context), GFP_KERNEL);
1696 if (!context)
1697 return ERR_PTR(-ENOMEM);
1698
Eli Cohen30aa60b2017-01-03 23:55:27 +02001699 lib_uar_4k = req.lib_caps & MLX5_LIB_CAP_4K_UAR;
Eli Cohen2f5ff262017-01-03 23:55:21 +02001700 bfregi = &context->bfregi;
Eli Cohenb037c292017-01-03 23:55:26 +02001701
1702 /* updates req->total_num_bfregs */
Yishai Hadas31a78a52017-12-24 16:31:34 +02001703 err = calc_total_bfregs(dev, lib_uar_4k, &req, bfregi);
Eli Cohenb037c292017-01-03 23:55:26 +02001704 if (err)
1705 goto out_ctx;
1706
Eli Cohen2f5ff262017-01-03 23:55:21 +02001707 mutex_init(&bfregi->lock);
Eli Cohenb037c292017-01-03 23:55:26 +02001708 bfregi->lib_uar_4k = lib_uar_4k;
Yishai Hadas31a78a52017-12-24 16:31:34 +02001709 bfregi->count = kcalloc(bfregi->total_num_bfregs, sizeof(*bfregi->count),
Eli Cohenb037c292017-01-03 23:55:26 +02001710 GFP_KERNEL);
1711 if (!bfregi->count) {
Eli Cohene126ba92013-07-07 17:25:49 +03001712 err = -ENOMEM;
1713 goto out_ctx;
1714 }
1715
Eli Cohenb037c292017-01-03 23:55:26 +02001716 bfregi->sys_pages = kcalloc(bfregi->num_sys_pages,
1717 sizeof(*bfregi->sys_pages),
1718 GFP_KERNEL);
1719 if (!bfregi->sys_pages) {
Eli Cohene126ba92013-07-07 17:25:49 +03001720 err = -ENOMEM;
Eli Cohenb037c292017-01-03 23:55:26 +02001721 goto out_count;
Eli Cohene126ba92013-07-07 17:25:49 +03001722 }
1723
Eli Cohenb037c292017-01-03 23:55:26 +02001724 err = allocate_uars(dev, context);
1725 if (err)
1726 goto out_sys_pages;
Eli Cohene126ba92013-07-07 17:25:49 +03001727
Haggai Eranb4cfe442014-12-11 17:04:26 +02001728#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
1729 context->ibucontext.invalidate_range = &mlx5_ib_invalidate_range;
1730#endif
1731
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001732 if (MLX5_CAP_GEN(dev->mdev, log_max_transport_domain)) {
Huy Nguyenc85023e2017-05-30 09:42:54 +03001733 err = mlx5_ib_alloc_transport_domain(dev, &context->tdn);
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001734 if (err)
Ilya Lesokhinc44ef992018-03-13 15:18:48 +02001735 goto out_uars;
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001736 }
1737
Yishai Hadasa8b92ca2018-06-17 12:59:57 +03001738 if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX) {
1739 /* Block DEVX on Infiniband as of SELinux */
1740 if (mlx5_ib_port_link_layer(ibdev, 1) != IB_LINK_LAYER_ETHERNET) {
1741 err = -EPERM;
1742 goto out_td;
1743 }
1744
1745 err = mlx5_ib_devx_create(dev, context);
1746 if (err)
1747 goto out_td;
1748 }
1749
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001750 INIT_LIST_HEAD(&context->vma_private_list);
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001751 mutex_init(&context->vma_private_list_mutex);
Eli Cohene126ba92013-07-07 17:25:49 +03001752 INIT_LIST_HEAD(&context->db_page_list);
1753 mutex_init(&context->db_page_mutex);
1754
Eli Cohen2f5ff262017-01-03 23:55:21 +02001755 resp.tot_bfregs = req.total_num_bfregs;
Daniel Jurgens508562d2018-01-04 17:25:34 +02001756 resp.num_ports = dev->num_ports;
Matan Barakb368d7c2015-12-15 20:30:12 +02001757
Haggai Abramovskyf72300c2016-01-14 19:12:58 +02001758 if (field_avail(typeof(resp), cqe_version, udata->outlen))
1759 resp.response_length += sizeof(resp.cqe_version);
Matan Barakb368d7c2015-12-15 20:30:12 +02001760
Bodong Wang402ca532016-06-17 15:02:20 +03001761 if (field_avail(typeof(resp), cmds_supp_uhw, udata->outlen)) {
Moni Shoua6ad279c52016-11-23 08:23:23 +02001762 resp.cmds_supp_uhw |= MLX5_USER_CMDS_SUPP_UHW_QUERY_DEVICE |
1763 MLX5_USER_CMDS_SUPP_UHW_CREATE_AH;
Bodong Wang402ca532016-06-17 15:02:20 +03001764 resp.response_length += sizeof(resp.cmds_supp_uhw);
1765 }
1766
Or Gerlitz78984892016-11-30 20:33:33 +02001767 if (field_avail(typeof(resp), eth_min_inline, udata->outlen)) {
1768 if (mlx5_ib_port_link_layer(ibdev, 1) == IB_LINK_LAYER_ETHERNET) {
1769 mlx5_query_min_inline(dev->mdev, &resp.eth_min_inline);
1770 resp.eth_min_inline++;
1771 }
1772 resp.response_length += sizeof(resp.eth_min_inline);
1773 }
1774
Feras Daoud5c99eae2018-01-16 20:08:41 +02001775 if (field_avail(typeof(resp), clock_info_versions, udata->outlen)) {
1776 if (mdev->clock_info)
1777 resp.clock_info_versions = BIT(MLX5_IB_CLOCK_INFO_V1);
1778 resp.response_length += sizeof(resp.clock_info_versions);
1779 }
1780
Noa Osherovichbc5c6ee2016-06-04 15:15:31 +03001781 /*
1782 * We don't want to expose information from the PCI bar that is located
1783 * after 4096 bytes, so if the arch only supports larger pages, let's
1784 * pretend we don't support reading the HCA's core clock. This is also
1785 * forced by mmap function.
1786 */
Eli Cohende8d6e02017-01-03 23:55:19 +02001787 if (field_avail(typeof(resp), hca_core_clock_offset, udata->outlen)) {
1788 if (PAGE_SIZE <= 4096) {
1789 resp.comp_mask |=
1790 MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_CORE_CLOCK_OFFSET;
1791 resp.hca_core_clock_offset =
1792 offsetof(struct mlx5_init_seg, internal_timer_h) % PAGE_SIZE;
1793 }
Feras Daoud5c99eae2018-01-16 20:08:41 +02001794 resp.response_length += sizeof(resp.hca_core_clock_offset);
Matan Barakb368d7c2015-12-15 20:30:12 +02001795 }
1796
Eli Cohen30aa60b2017-01-03 23:55:27 +02001797 if (field_avail(typeof(resp), log_uar_size, udata->outlen))
1798 resp.response_length += sizeof(resp.log_uar_size);
1799
1800 if (field_avail(typeof(resp), num_uars_per_page, udata->outlen))
1801 resp.response_length += sizeof(resp.num_uars_per_page);
1802
Yishai Hadas31a78a52017-12-24 16:31:34 +02001803 if (field_avail(typeof(resp), num_dyn_bfregs, udata->outlen)) {
1804 resp.num_dyn_bfregs = bfregi->num_dyn_bfregs;
1805 resp.response_length += sizeof(resp.num_dyn_bfregs);
1806 }
1807
Matan Barakb368d7c2015-12-15 20:30:12 +02001808 err = ib_copy_to_udata(udata, &resp, resp.response_length);
Eli Cohene126ba92013-07-07 17:25:49 +03001809 if (err)
Yishai Hadasa8b92ca2018-06-17 12:59:57 +03001810 goto out_mdev;
Eli Cohene126ba92013-07-07 17:25:49 +03001811
Eli Cohen2f5ff262017-01-03 23:55:21 +02001812 bfregi->ver = ver;
1813 bfregi->num_low_latency_bfregs = req.num_low_latency_bfregs;
Haggai Abramovskyf72300c2016-01-14 19:12:58 +02001814 context->cqe_version = resp.cqe_version;
Eli Cohen30aa60b2017-01-03 23:55:27 +02001815 context->lib_caps = req.lib_caps;
1816 print_lib_caps(dev, context->lib_caps);
Haggai Abramovskyf72300c2016-01-14 19:12:58 +02001817
Eli Cohene126ba92013-07-07 17:25:49 +03001818 return &context->ibucontext;
1819
Yishai Hadasa8b92ca2018-06-17 12:59:57 +03001820out_mdev:
1821 if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX)
1822 mlx5_ib_devx_destroy(dev, context);
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001823out_td:
1824 if (MLX5_CAP_GEN(dev->mdev, log_max_transport_domain))
Huy Nguyenc85023e2017-05-30 09:42:54 +03001825 mlx5_ib_dealloc_transport_domain(dev, context->tdn);
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001826
Eli Cohene126ba92013-07-07 17:25:49 +03001827out_uars:
Eli Cohenb037c292017-01-03 23:55:26 +02001828 deallocate_uars(dev, context);
1829
1830out_sys_pages:
1831 kfree(bfregi->sys_pages);
1832
Eli Cohene126ba92013-07-07 17:25:49 +03001833out_count:
Eli Cohen2f5ff262017-01-03 23:55:21 +02001834 kfree(bfregi->count);
Eli Cohene126ba92013-07-07 17:25:49 +03001835
Eli Cohene126ba92013-07-07 17:25:49 +03001836out_ctx:
1837 kfree(context);
Eli Cohenb037c292017-01-03 23:55:26 +02001838
Eli Cohene126ba92013-07-07 17:25:49 +03001839 return ERR_PTR(err);
1840}
1841
1842static int mlx5_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)
1843{
1844 struct mlx5_ib_ucontext *context = to_mucontext(ibcontext);
1845 struct mlx5_ib_dev *dev = to_mdev(ibcontext->device);
Eli Cohenb037c292017-01-03 23:55:26 +02001846 struct mlx5_bfreg_info *bfregi;
Eli Cohene126ba92013-07-07 17:25:49 +03001847
Yishai Hadasa8b92ca2018-06-17 12:59:57 +03001848 if (context->devx_uid)
1849 mlx5_ib_devx_destroy(dev, context);
1850
Eli Cohenb037c292017-01-03 23:55:26 +02001851 bfregi = &context->bfregi;
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001852 if (MLX5_CAP_GEN(dev->mdev, log_max_transport_domain))
Huy Nguyenc85023e2017-05-30 09:42:54 +03001853 mlx5_ib_dealloc_transport_domain(dev, context->tdn);
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001854
Eli Cohenb037c292017-01-03 23:55:26 +02001855 deallocate_uars(dev, context);
1856 kfree(bfregi->sys_pages);
Eli Cohen2f5ff262017-01-03 23:55:21 +02001857 kfree(bfregi->count);
Eli Cohene126ba92013-07-07 17:25:49 +03001858 kfree(context);
1859
1860 return 0;
1861}
1862
Eli Cohenb037c292017-01-03 23:55:26 +02001863static phys_addr_t uar_index2pfn(struct mlx5_ib_dev *dev,
Yishai Hadas4ed131d2017-12-24 16:31:35 +02001864 int uar_idx)
Eli Cohene126ba92013-07-07 17:25:49 +03001865{
Eli Cohenb037c292017-01-03 23:55:26 +02001866 int fw_uars_per_page;
1867
1868 fw_uars_per_page = MLX5_CAP_GEN(dev->mdev, uar_4k) ? MLX5_UARS_IN_PAGE : 1;
1869
Yishai Hadas4ed131d2017-12-24 16:31:35 +02001870 return (pci_resource_start(dev->mdev->pdev, 0) >> PAGE_SHIFT) + uar_idx / fw_uars_per_page;
Eli Cohene126ba92013-07-07 17:25:49 +03001871}
1872
1873static int get_command(unsigned long offset)
1874{
1875 return (offset >> MLX5_IB_MMAP_CMD_SHIFT) & MLX5_IB_MMAP_CMD_MASK;
1876}
1877
1878static int get_arg(unsigned long offset)
1879{
1880 return offset & ((1 << MLX5_IB_MMAP_CMD_SHIFT) - 1);
1881}
1882
1883static int get_index(unsigned long offset)
1884{
1885 return get_arg(offset);
1886}
1887
Yishai Hadas4ed131d2017-12-24 16:31:35 +02001888/* Index resides in an extra byte to enable larger values than 255 */
1889static int get_extended_index(unsigned long offset)
1890{
1891 return get_arg(offset) | ((offset >> 16) & 0xff) << 8;
1892}
1893
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001894static void mlx5_ib_vma_open(struct vm_area_struct *area)
1895{
1896 /* vma_open is called when a new VMA is created on top of our VMA. This
1897 * is done through either mremap flow or split_vma (usually due to
1898 * mlock, madvise, munmap, etc.) We do not support a clone of the VMA,
1899 * as this VMA is strongly hardware related. Therefore we set the
1900 * vm_ops of the newly created/cloned VMA to NULL, to prevent it from
1901 * calling us again and trying to do incorrect actions. We assume that
1902 * the original VMA size is exactly a single page, and therefore all
1903 * "splitting" operation will not happen to it.
1904 */
1905 area->vm_ops = NULL;
1906}
1907
1908static void mlx5_ib_vma_close(struct vm_area_struct *area)
1909{
1910 struct mlx5_ib_vma_private_data *mlx5_ib_vma_priv_data;
1911
1912 /* It's guaranteed that all VMAs opened on a FD are closed before the
1913 * file itself is closed, therefore no sync is needed with the regular
1914 * closing flow. (e.g. mlx5 ib_dealloc_ucontext)
1915 * However need a sync with accessing the vma as part of
1916 * mlx5_ib_disassociate_ucontext.
1917 * The close operation is usually called under mm->mmap_sem except when
1918 * process is exiting.
1919 * The exiting case is handled explicitly as part of
1920 * mlx5_ib_disassociate_ucontext.
1921 */
1922 mlx5_ib_vma_priv_data = (struct mlx5_ib_vma_private_data *)area->vm_private_data;
1923
1924 /* setting the vma context pointer to null in the mlx5_ib driver's
1925 * private data, to protect a race condition in
1926 * mlx5_ib_disassociate_ucontext().
1927 */
1928 mlx5_ib_vma_priv_data->vma = NULL;
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001929 mutex_lock(mlx5_ib_vma_priv_data->vma_private_list_mutex);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001930 list_del(&mlx5_ib_vma_priv_data->list);
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001931 mutex_unlock(mlx5_ib_vma_priv_data->vma_private_list_mutex);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001932 kfree(mlx5_ib_vma_priv_data);
1933}
1934
1935static const struct vm_operations_struct mlx5_ib_vm_ops = {
1936 .open = mlx5_ib_vma_open,
1937 .close = mlx5_ib_vma_close
1938};
1939
1940static int mlx5_ib_set_vma_data(struct vm_area_struct *vma,
1941 struct mlx5_ib_ucontext *ctx)
1942{
1943 struct mlx5_ib_vma_private_data *vma_prv;
1944 struct list_head *vma_head = &ctx->vma_private_list;
1945
1946 vma_prv = kzalloc(sizeof(*vma_prv), GFP_KERNEL);
1947 if (!vma_prv)
1948 return -ENOMEM;
1949
1950 vma_prv->vma = vma;
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001951 vma_prv->vma_private_list_mutex = &ctx->vma_private_list_mutex;
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001952 vma->vm_private_data = vma_prv;
1953 vma->vm_ops = &mlx5_ib_vm_ops;
1954
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001955 mutex_lock(&ctx->vma_private_list_mutex);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001956 list_add(&vma_prv->list, vma_head);
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001957 mutex_unlock(&ctx->vma_private_list_mutex);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001958
1959 return 0;
1960}
1961
1962static void mlx5_ib_disassociate_ucontext(struct ib_ucontext *ibcontext)
1963{
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001964 struct vm_area_struct *vma;
1965 struct mlx5_ib_vma_private_data *vma_private, *n;
1966 struct mlx5_ib_ucontext *context = to_mucontext(ibcontext);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001967
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001968 mutex_lock(&context->vma_private_list_mutex);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001969 list_for_each_entry_safe(vma_private, n, &context->vma_private_list,
1970 list) {
1971 vma = vma_private->vma;
Leon Romanovsky2cb40792018-05-29 15:14:05 +03001972 zap_vma_ptes(vma, vma->vm_start, PAGE_SIZE);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001973 /* context going to be destroyed, should
1974 * not access ops any more.
1975 */
Maor Gottlieb13776612017-03-29 06:03:03 +03001976 vma->vm_flags &= ~(VM_SHARED | VM_MAYSHARE);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001977 vma->vm_ops = NULL;
1978 list_del(&vma_private->list);
1979 kfree(vma_private);
1980 }
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001981 mutex_unlock(&context->vma_private_list_mutex);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001982}
1983
Guy Levi37aa5c32016-04-27 16:49:50 +03001984static inline char *mmap_cmd2str(enum mlx5_ib_mmap_cmd cmd)
1985{
1986 switch (cmd) {
1987 case MLX5_IB_MMAP_WC_PAGE:
1988 return "WC";
1989 case MLX5_IB_MMAP_REGULAR_PAGE:
1990 return "best effort WC";
1991 case MLX5_IB_MMAP_NC_PAGE:
1992 return "NC";
Ariel Levkovich24da0012018-04-05 18:53:27 +03001993 case MLX5_IB_MMAP_DEVICE_MEM:
1994 return "Device Memory";
Guy Levi37aa5c32016-04-27 16:49:50 +03001995 default:
1996 return NULL;
1997 }
1998}
1999
Feras Daoud5c99eae2018-01-16 20:08:41 +02002000static int mlx5_ib_mmap_clock_info_page(struct mlx5_ib_dev *dev,
2001 struct vm_area_struct *vma,
2002 struct mlx5_ib_ucontext *context)
2003{
2004 phys_addr_t pfn;
2005 int err;
2006
2007 if (vma->vm_end - vma->vm_start != PAGE_SIZE)
2008 return -EINVAL;
2009
2010 if (get_index(vma->vm_pgoff) != MLX5_IB_CLOCK_INFO_V1)
2011 return -EOPNOTSUPP;
2012
2013 if (vma->vm_flags & VM_WRITE)
2014 return -EPERM;
2015
2016 if (!dev->mdev->clock_info_page)
2017 return -EOPNOTSUPP;
2018
2019 pfn = page_to_pfn(dev->mdev->clock_info_page);
2020 err = remap_pfn_range(vma, vma->vm_start, pfn, PAGE_SIZE,
2021 vma->vm_page_prot);
2022 if (err)
2023 return err;
2024
Feras Daoud5c99eae2018-01-16 20:08:41 +02002025 return mlx5_ib_set_vma_data(vma, context);
2026}
2027
Guy Levi37aa5c32016-04-27 16:49:50 +03002028static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03002029 struct vm_area_struct *vma,
2030 struct mlx5_ib_ucontext *context)
Guy Levi37aa5c32016-04-27 16:49:50 +03002031{
Eli Cohen2f5ff262017-01-03 23:55:21 +02002032 struct mlx5_bfreg_info *bfregi = &context->bfregi;
Guy Levi37aa5c32016-04-27 16:49:50 +03002033 int err;
2034 unsigned long idx;
2035 phys_addr_t pfn, pa;
2036 pgprot_t prot;
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002037 u32 bfreg_dyn_idx = 0;
2038 u32 uar_index;
2039 int dyn_uar = (cmd == MLX5_IB_MMAP_ALLOC_WC);
2040 int max_valid_idx = dyn_uar ? bfregi->num_sys_pages :
2041 bfregi->num_static_sys_pages;
Eli Cohenb037c292017-01-03 23:55:26 +02002042
2043 if (vma->vm_end - vma->vm_start != PAGE_SIZE)
2044 return -EINVAL;
2045
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002046 if (dyn_uar)
2047 idx = get_extended_index(vma->vm_pgoff) + bfregi->num_static_sys_pages;
2048 else
2049 idx = get_index(vma->vm_pgoff);
2050
2051 if (idx >= max_valid_idx) {
2052 mlx5_ib_warn(dev, "invalid uar index %lu, max=%d\n",
2053 idx, max_valid_idx);
Eli Cohenb037c292017-01-03 23:55:26 +02002054 return -EINVAL;
2055 }
Guy Levi37aa5c32016-04-27 16:49:50 +03002056
2057 switch (cmd) {
2058 case MLX5_IB_MMAP_WC_PAGE:
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002059 case MLX5_IB_MMAP_ALLOC_WC:
Guy Levi37aa5c32016-04-27 16:49:50 +03002060/* Some architectures don't support WC memory */
2061#if defined(CONFIG_X86)
2062 if (!pat_enabled())
2063 return -EPERM;
2064#elif !(defined(CONFIG_PPC) || (defined(CONFIG_ARM) && defined(CONFIG_MMU)))
2065 return -EPERM;
2066#endif
2067 /* fall through */
2068 case MLX5_IB_MMAP_REGULAR_PAGE:
2069 /* For MLX5_IB_MMAP_REGULAR_PAGE do the best effort to get WC */
2070 prot = pgprot_writecombine(vma->vm_page_prot);
2071 break;
2072 case MLX5_IB_MMAP_NC_PAGE:
2073 prot = pgprot_noncached(vma->vm_page_prot);
2074 break;
2075 default:
2076 return -EINVAL;
2077 }
2078
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002079 if (dyn_uar) {
2080 int uars_per_page;
2081
2082 uars_per_page = get_uars_per_sys_page(dev, bfregi->lib_uar_4k);
2083 bfreg_dyn_idx = idx * (uars_per_page * MLX5_NON_FP_BFREGS_PER_UAR);
2084 if (bfreg_dyn_idx >= bfregi->total_num_bfregs) {
2085 mlx5_ib_warn(dev, "invalid bfreg_dyn_idx %u, max=%u\n",
2086 bfreg_dyn_idx, bfregi->total_num_bfregs);
2087 return -EINVAL;
2088 }
2089
2090 mutex_lock(&bfregi->lock);
2091 /* Fail if uar already allocated, first bfreg index of each
2092 * page holds its count.
2093 */
2094 if (bfregi->count[bfreg_dyn_idx]) {
2095 mlx5_ib_warn(dev, "wrong offset, idx %lu is busy, bfregn=%u\n", idx, bfreg_dyn_idx);
2096 mutex_unlock(&bfregi->lock);
2097 return -EINVAL;
2098 }
2099
2100 bfregi->count[bfreg_dyn_idx]++;
2101 mutex_unlock(&bfregi->lock);
2102
2103 err = mlx5_cmd_alloc_uar(dev->mdev, &uar_index);
2104 if (err) {
2105 mlx5_ib_warn(dev, "UAR alloc failed\n");
2106 goto free_bfreg;
2107 }
2108 } else {
2109 uar_index = bfregi->sys_pages[idx];
2110 }
2111
2112 pfn = uar_index2pfn(dev, uar_index);
Guy Levi37aa5c32016-04-27 16:49:50 +03002113 mlx5_ib_dbg(dev, "uar idx 0x%lx, pfn %pa\n", idx, &pfn);
2114
2115 vma->vm_page_prot = prot;
2116 err = io_remap_pfn_range(vma, vma->vm_start, pfn,
2117 PAGE_SIZE, vma->vm_page_prot);
2118 if (err) {
Leon Romanovsky8f062282018-05-22 08:31:03 +03002119 mlx5_ib_err(dev,
2120 "io_remap_pfn_range failed with error=%d, mmap_cmd=%s\n",
2121 err, mmap_cmd2str(cmd));
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002122 err = -EAGAIN;
2123 goto err;
Guy Levi37aa5c32016-04-27 16:49:50 +03002124 }
2125
2126 pa = pfn << PAGE_SHIFT;
Guy Levi37aa5c32016-04-27 16:49:50 +03002127
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002128 err = mlx5_ib_set_vma_data(vma, context);
2129 if (err)
2130 goto err;
2131
2132 if (dyn_uar)
2133 bfregi->sys_pages[idx] = uar_index;
2134 return 0;
2135
2136err:
2137 if (!dyn_uar)
2138 return err;
2139
2140 mlx5_cmd_free_uar(dev->mdev, idx);
2141
2142free_bfreg:
2143 mlx5_ib_free_bfreg(dev, bfregi, bfreg_dyn_idx);
2144
2145 return err;
Guy Levi37aa5c32016-04-27 16:49:50 +03002146}
2147
Ariel Levkovich24da0012018-04-05 18:53:27 +03002148static int dm_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
2149{
2150 struct mlx5_ib_ucontext *mctx = to_mucontext(context);
2151 struct mlx5_ib_dev *dev = to_mdev(context->device);
2152 u16 page_idx = get_extended_index(vma->vm_pgoff);
2153 size_t map_size = vma->vm_end - vma->vm_start;
2154 u32 npages = map_size >> PAGE_SHIFT;
2155 phys_addr_t pfn;
2156 pgprot_t prot;
2157
2158 if (find_next_zero_bit(mctx->dm_pages, page_idx + npages, page_idx) !=
2159 page_idx + npages)
2160 return -EINVAL;
2161
2162 pfn = ((pci_resource_start(dev->mdev->pdev, 0) +
2163 MLX5_CAP64_DEV_MEM(dev->mdev, memic_bar_start_addr)) >>
2164 PAGE_SHIFT) +
2165 page_idx;
2166 prot = pgprot_writecombine(vma->vm_page_prot);
2167 vma->vm_page_prot = prot;
2168
2169 if (io_remap_pfn_range(vma, vma->vm_start, pfn, map_size,
2170 vma->vm_page_prot))
2171 return -EAGAIN;
2172
2173 return mlx5_ib_set_vma_data(vma, mctx);
2174}
2175
Eli Cohene126ba92013-07-07 17:25:49 +03002176static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma)
2177{
2178 struct mlx5_ib_ucontext *context = to_mucontext(ibcontext);
2179 struct mlx5_ib_dev *dev = to_mdev(ibcontext->device);
Eli Cohene126ba92013-07-07 17:25:49 +03002180 unsigned long command;
Eli Cohene126ba92013-07-07 17:25:49 +03002181 phys_addr_t pfn;
2182
2183 command = get_command(vma->vm_pgoff);
2184 switch (command) {
Guy Levi37aa5c32016-04-27 16:49:50 +03002185 case MLX5_IB_MMAP_WC_PAGE:
2186 case MLX5_IB_MMAP_NC_PAGE:
Eli Cohene126ba92013-07-07 17:25:49 +03002187 case MLX5_IB_MMAP_REGULAR_PAGE:
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002188 case MLX5_IB_MMAP_ALLOC_WC:
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03002189 return uar_mmap(dev, command, vma, context);
Eli Cohene126ba92013-07-07 17:25:49 +03002190
2191 case MLX5_IB_MMAP_GET_CONTIGUOUS_PAGES:
2192 return -ENOSYS;
2193
Matan Barakd69e3bc2015-12-15 20:30:13 +02002194 case MLX5_IB_MMAP_CORE_CLOCK:
Matan Barakd69e3bc2015-12-15 20:30:13 +02002195 if (vma->vm_end - vma->vm_start != PAGE_SIZE)
2196 return -EINVAL;
2197
Matan Barak6cbac1e2016-04-14 16:52:10 +03002198 if (vma->vm_flags & VM_WRITE)
Matan Barakd69e3bc2015-12-15 20:30:13 +02002199 return -EPERM;
2200
2201 /* Don't expose to user-space information it shouldn't have */
2202 if (PAGE_SIZE > 4096)
2203 return -EOPNOTSUPP;
2204
2205 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
2206 pfn = (dev->mdev->iseg_base +
2207 offsetof(struct mlx5_init_seg, internal_timer_h)) >>
2208 PAGE_SHIFT;
2209 if (io_remap_pfn_range(vma, vma->vm_start, pfn,
2210 PAGE_SIZE, vma->vm_page_prot))
2211 return -EAGAIN;
Matan Barakd69e3bc2015-12-15 20:30:13 +02002212 break;
Feras Daoud5c99eae2018-01-16 20:08:41 +02002213 case MLX5_IB_MMAP_CLOCK_INFO:
2214 return mlx5_ib_mmap_clock_info_page(dev, vma, context);
Matan Barakd69e3bc2015-12-15 20:30:13 +02002215
Ariel Levkovich24da0012018-04-05 18:53:27 +03002216 case MLX5_IB_MMAP_DEVICE_MEM:
2217 return dm_mmap(ibcontext, vma);
2218
Eli Cohene126ba92013-07-07 17:25:49 +03002219 default:
2220 return -EINVAL;
2221 }
2222
2223 return 0;
2224}
2225
Ariel Levkovich24da0012018-04-05 18:53:27 +03002226struct ib_dm *mlx5_ib_alloc_dm(struct ib_device *ibdev,
2227 struct ib_ucontext *context,
2228 struct ib_dm_alloc_attr *attr,
2229 struct uverbs_attr_bundle *attrs)
2230{
2231 u64 act_size = roundup(attr->length, MLX5_MEMIC_BASE_SIZE);
2232 struct mlx5_memic *memic = &to_mdev(ibdev)->memic;
2233 phys_addr_t memic_addr;
2234 struct mlx5_ib_dm *dm;
2235 u64 start_offset;
2236 u32 page_idx;
2237 int err;
2238
2239 dm = kzalloc(sizeof(*dm), GFP_KERNEL);
2240 if (!dm)
2241 return ERR_PTR(-ENOMEM);
2242
2243 mlx5_ib_dbg(to_mdev(ibdev), "alloc_memic req: user_length=0x%llx act_length=0x%llx log_alignment=%d\n",
2244 attr->length, act_size, attr->alignment);
2245
2246 err = mlx5_cmd_alloc_memic(memic, &memic_addr,
2247 act_size, attr->alignment);
2248 if (err)
2249 goto err_free;
2250
2251 start_offset = memic_addr & ~PAGE_MASK;
2252 page_idx = (memic_addr - pci_resource_start(memic->dev->pdev, 0) -
2253 MLX5_CAP64_DEV_MEM(memic->dev, memic_bar_start_addr)) >>
2254 PAGE_SHIFT;
2255
2256 err = uverbs_copy_to(attrs,
2257 MLX5_IB_ATTR_ALLOC_DM_RESP_START_OFFSET,
2258 &start_offset, sizeof(start_offset));
2259 if (err)
2260 goto err_dealloc;
2261
2262 err = uverbs_copy_to(attrs,
2263 MLX5_IB_ATTR_ALLOC_DM_RESP_PAGE_INDEX,
2264 &page_idx, sizeof(page_idx));
2265 if (err)
2266 goto err_dealloc;
2267
2268 bitmap_set(to_mucontext(context)->dm_pages, page_idx,
2269 DIV_ROUND_UP(act_size, PAGE_SIZE));
2270
2271 dm->dev_addr = memic_addr;
2272
2273 return &dm->ibdm;
2274
2275err_dealloc:
2276 mlx5_cmd_dealloc_memic(memic, memic_addr,
2277 act_size);
2278err_free:
2279 kfree(dm);
2280 return ERR_PTR(err);
2281}
2282
2283int mlx5_ib_dealloc_dm(struct ib_dm *ibdm)
2284{
2285 struct mlx5_memic *memic = &to_mdev(ibdm->device)->memic;
2286 struct mlx5_ib_dm *dm = to_mdm(ibdm);
2287 u64 act_size = roundup(dm->ibdm.length, MLX5_MEMIC_BASE_SIZE);
2288 u32 page_idx;
2289 int ret;
2290
2291 ret = mlx5_cmd_dealloc_memic(memic, dm->dev_addr, act_size);
2292 if (ret)
2293 return ret;
2294
2295 page_idx = (dm->dev_addr - pci_resource_start(memic->dev->pdev, 0) -
2296 MLX5_CAP64_DEV_MEM(memic->dev, memic_bar_start_addr)) >>
2297 PAGE_SHIFT;
2298 bitmap_clear(to_mucontext(ibdm->uobject->context)->dm_pages,
2299 page_idx,
2300 DIV_ROUND_UP(act_size, PAGE_SIZE));
2301
2302 kfree(dm);
2303
2304 return 0;
2305}
2306
Eli Cohene126ba92013-07-07 17:25:49 +03002307static struct ib_pd *mlx5_ib_alloc_pd(struct ib_device *ibdev,
2308 struct ib_ucontext *context,
2309 struct ib_udata *udata)
2310{
2311 struct mlx5_ib_alloc_pd_resp resp;
2312 struct mlx5_ib_pd *pd;
2313 int err;
2314
2315 pd = kmalloc(sizeof(*pd), GFP_KERNEL);
2316 if (!pd)
2317 return ERR_PTR(-ENOMEM);
2318
Jack Morgenstein9603b612014-07-28 23:30:22 +03002319 err = mlx5_core_alloc_pd(to_mdev(ibdev)->mdev, &pd->pdn);
Eli Cohene126ba92013-07-07 17:25:49 +03002320 if (err) {
2321 kfree(pd);
2322 return ERR_PTR(err);
2323 }
2324
2325 if (context) {
2326 resp.pdn = pd->pdn;
2327 if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {
Jack Morgenstein9603b612014-07-28 23:30:22 +03002328 mlx5_core_dealloc_pd(to_mdev(ibdev)->mdev, pd->pdn);
Eli Cohene126ba92013-07-07 17:25:49 +03002329 kfree(pd);
2330 return ERR_PTR(-EFAULT);
2331 }
Eli Cohene126ba92013-07-07 17:25:49 +03002332 }
2333
2334 return &pd->ibpd;
2335}
2336
2337static int mlx5_ib_dealloc_pd(struct ib_pd *pd)
2338{
2339 struct mlx5_ib_dev *mdev = to_mdev(pd->device);
2340 struct mlx5_ib_pd *mpd = to_mpd(pd);
2341
Jack Morgenstein9603b612014-07-28 23:30:22 +03002342 mlx5_core_dealloc_pd(mdev->mdev, mpd->pdn);
Eli Cohene126ba92013-07-07 17:25:49 +03002343 kfree(mpd);
2344
2345 return 0;
2346}
2347
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002348enum {
2349 MATCH_CRITERIA_ENABLE_OUTER_BIT,
2350 MATCH_CRITERIA_ENABLE_MISC_BIT,
Ariel Levkovich71c6e862018-05-13 14:33:34 +03002351 MATCH_CRITERIA_ENABLE_INNER_BIT,
2352 MATCH_CRITERIA_ENABLE_MISC2_BIT
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002353};
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002354
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002355#define HEADER_IS_ZERO(match_criteria, headers) \
2356 !(memchr_inv(MLX5_ADDR_OF(fte_match_param, match_criteria, headers), \
2357 0, MLX5_FLD_SZ_BYTES(fte_match_param, headers))) \
2358
2359static u8 get_match_criteria_enable(u32 *match_criteria)
2360{
2361 u8 match_criteria_enable;
2362
2363 match_criteria_enable =
2364 (!HEADER_IS_ZERO(match_criteria, outer_headers)) <<
2365 MATCH_CRITERIA_ENABLE_OUTER_BIT;
2366 match_criteria_enable |=
2367 (!HEADER_IS_ZERO(match_criteria, misc_parameters)) <<
2368 MATCH_CRITERIA_ENABLE_MISC_BIT;
2369 match_criteria_enable |=
2370 (!HEADER_IS_ZERO(match_criteria, inner_headers)) <<
2371 MATCH_CRITERIA_ENABLE_INNER_BIT;
Ariel Levkovich71c6e862018-05-13 14:33:34 +03002372 match_criteria_enable |=
2373 (!HEADER_IS_ZERO(match_criteria, misc_parameters_2)) <<
2374 MATCH_CRITERIA_ENABLE_MISC2_BIT;
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002375
2376 return match_criteria_enable;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002377}
2378
Maor Gottliebca0d4752016-08-30 16:58:35 +03002379static void set_proto(void *outer_c, void *outer_v, u8 mask, u8 val)
2380{
2381 MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_protocol, mask);
2382 MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_protocol, val);
2383}
2384
Daria Velikovsky37da2a02018-05-07 10:20:02 +03002385static void set_flow_label(void *misc_c, void *misc_v, u32 mask, u32 val,
Moses Reuben2d1e6972016-11-14 19:04:52 +02002386 bool inner)
2387{
2388 if (inner) {
2389 MLX5_SET(fte_match_set_misc,
2390 misc_c, inner_ipv6_flow_label, mask);
2391 MLX5_SET(fte_match_set_misc,
2392 misc_v, inner_ipv6_flow_label, val);
2393 } else {
2394 MLX5_SET(fte_match_set_misc,
2395 misc_c, outer_ipv6_flow_label, mask);
2396 MLX5_SET(fte_match_set_misc,
2397 misc_v, outer_ipv6_flow_label, val);
2398 }
2399}
2400
Maor Gottliebca0d4752016-08-30 16:58:35 +03002401static void set_tos(void *outer_c, void *outer_v, u8 mask, u8 val)
2402{
2403 MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_ecn, mask);
2404 MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_ecn, val);
2405 MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_dscp, mask >> 2);
2406 MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_dscp, val >> 2);
2407}
2408
Ariel Levkovich71c6e862018-05-13 14:33:34 +03002409static int check_mpls_supp_fields(u32 field_support, const __be32 *set_mask)
2410{
2411 if (MLX5_GET(fte_match_mpls, set_mask, mpls_label) &&
2412 !(field_support & MLX5_FIELD_SUPPORT_MPLS_LABEL))
2413 return -EOPNOTSUPP;
2414
2415 if (MLX5_GET(fte_match_mpls, set_mask, mpls_exp) &&
2416 !(field_support & MLX5_FIELD_SUPPORT_MPLS_EXP))
2417 return -EOPNOTSUPP;
2418
2419 if (MLX5_GET(fte_match_mpls, set_mask, mpls_s_bos) &&
2420 !(field_support & MLX5_FIELD_SUPPORT_MPLS_S_BOS))
2421 return -EOPNOTSUPP;
2422
2423 if (MLX5_GET(fte_match_mpls, set_mask, mpls_ttl) &&
2424 !(field_support & MLX5_FIELD_SUPPORT_MPLS_TTL))
2425 return -EOPNOTSUPP;
2426
2427 return 0;
2428}
2429
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002430#define LAST_ETH_FIELD vlan_tag
2431#define LAST_IB_FIELD sl
Maor Gottliebca0d4752016-08-30 16:58:35 +03002432#define LAST_IPV4_FIELD tos
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002433#define LAST_IPV6_FIELD traffic_class
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002434#define LAST_TCP_UDP_FIELD src_port
Moses Reubenffb30d82016-11-14 19:04:50 +02002435#define LAST_TUNNEL_FIELD tunnel_id
Moses Reuben2ac693f2017-01-18 14:59:50 +02002436#define LAST_FLOW_TAG_FIELD tag_id
Slava Shwartsmana22ed862017-04-03 13:13:52 +03002437#define LAST_DROP_FIELD size
Raed Salem3b3233f2018-05-31 16:43:39 +03002438#define LAST_COUNTERS_FIELD counters
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002439
2440/* Field is the last supported field */
2441#define FIELDS_NOT_SUPPORTED(filter, field)\
2442 memchr_inv((void *)&filter.field +\
2443 sizeof(filter.field), 0,\
2444 sizeof(filter) -\
2445 offsetof(typeof(filter), field) -\
2446 sizeof(filter.field))
2447
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002448static int parse_flow_flow_action(const union ib_flow_spec *ib_spec,
2449 const struct ib_flow_attr *flow_attr,
2450 struct mlx5_flow_act *action)
2451{
2452 struct mlx5_ib_flow_action *maction = to_mflow_act(ib_spec->action.act);
2453
2454 switch (maction->ib_action.type) {
2455 case IB_FLOW_ACTION_ESP:
2456 /* Currently only AES_GCM keymat is supported by the driver */
2457 action->esp_id = (uintptr_t)maction->esp_aes_gcm.ctx;
2458 action->action |= flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS ?
2459 MLX5_FLOW_CONTEXT_ACTION_ENCRYPT :
2460 MLX5_FLOW_CONTEXT_ACTION_DECRYPT;
2461 return 0;
2462 default:
2463 return -EOPNOTSUPP;
2464 }
2465}
2466
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002467static int parse_flow_attr(struct mlx5_core_dev *mdev, u32 *match_c,
2468 u32 *match_v, const union ib_flow_spec *ib_spec,
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002469 const struct ib_flow_attr *flow_attr,
Ariel Levkovich71c6e862018-05-13 14:33:34 +03002470 struct mlx5_flow_act *action, u32 prev_type)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002471{
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002472 void *misc_params_c = MLX5_ADDR_OF(fte_match_param, match_c,
2473 misc_parameters);
2474 void *misc_params_v = MLX5_ADDR_OF(fte_match_param, match_v,
2475 misc_parameters);
Ariel Levkovich71c6e862018-05-13 14:33:34 +03002476 void *misc_params2_c = MLX5_ADDR_OF(fte_match_param, match_c,
2477 misc_parameters_2);
2478 void *misc_params2_v = MLX5_ADDR_OF(fte_match_param, match_v,
2479 misc_parameters_2);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002480 void *headers_c;
2481 void *headers_v;
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002482 int match_ipv;
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002483 int ret;
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002484
Moses Reuben2d1e6972016-11-14 19:04:52 +02002485 if (ib_spec->type & IB_FLOW_SPEC_INNER) {
2486 headers_c = MLX5_ADDR_OF(fte_match_param, match_c,
2487 inner_headers);
2488 headers_v = MLX5_ADDR_OF(fte_match_param, match_v,
2489 inner_headers);
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002490 match_ipv = MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
2491 ft_field_support.inner_ip_version);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002492 } else {
2493 headers_c = MLX5_ADDR_OF(fte_match_param, match_c,
2494 outer_headers);
2495 headers_v = MLX5_ADDR_OF(fte_match_param, match_v,
2496 outer_headers);
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002497 match_ipv = MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
2498 ft_field_support.outer_ip_version);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002499 }
2500
2501 switch (ib_spec->type & ~IB_FLOW_SPEC_INNER) {
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002502 case IB_FLOW_SPEC_ETH:
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002503 if (FIELDS_NOT_SUPPORTED(ib_spec->eth.mask, LAST_ETH_FIELD))
Leon Romanovsky1ffd3a22017-01-18 14:59:51 +02002504 return -EOPNOTSUPP;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002505
Moses Reuben2d1e6972016-11-14 19:04:52 +02002506 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002507 dmac_47_16),
2508 ib_spec->eth.mask.dst_mac);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002509 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002510 dmac_47_16),
2511 ib_spec->eth.val.dst_mac);
2512
Moses Reuben2d1e6972016-11-14 19:04:52 +02002513 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
Maor Gottliebee3da802016-09-12 19:16:24 +03002514 smac_47_16),
2515 ib_spec->eth.mask.src_mac);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002516 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
Maor Gottliebee3da802016-09-12 19:16:24 +03002517 smac_47_16),
2518 ib_spec->eth.val.src_mac);
2519
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002520 if (ib_spec->eth.mask.vlan_tag) {
Moses Reuben2d1e6972016-11-14 19:04:52 +02002521 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
Mohamad Haj Yahia10543362016-10-09 16:25:43 +03002522 cvlan_tag, 1);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002523 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Mohamad Haj Yahia10543362016-10-09 16:25:43 +03002524 cvlan_tag, 1);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002525
Moses Reuben2d1e6972016-11-14 19:04:52 +02002526 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002527 first_vid, ntohs(ib_spec->eth.mask.vlan_tag));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002528 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002529 first_vid, ntohs(ib_spec->eth.val.vlan_tag));
2530
Moses Reuben2d1e6972016-11-14 19:04:52 +02002531 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002532 first_cfi,
2533 ntohs(ib_spec->eth.mask.vlan_tag) >> 12);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002534 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002535 first_cfi,
2536 ntohs(ib_spec->eth.val.vlan_tag) >> 12);
2537
Moses Reuben2d1e6972016-11-14 19:04:52 +02002538 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002539 first_prio,
2540 ntohs(ib_spec->eth.mask.vlan_tag) >> 13);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002541 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002542 first_prio,
2543 ntohs(ib_spec->eth.val.vlan_tag) >> 13);
2544 }
Moses Reuben2d1e6972016-11-14 19:04:52 +02002545 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002546 ethertype, ntohs(ib_spec->eth.mask.ether_type));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002547 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002548 ethertype, ntohs(ib_spec->eth.val.ether_type));
2549 break;
2550 case IB_FLOW_SPEC_IPV4:
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002551 if (FIELDS_NOT_SUPPORTED(ib_spec->ipv4.mask, LAST_IPV4_FIELD))
Leon Romanovsky1ffd3a22017-01-18 14:59:51 +02002552 return -EOPNOTSUPP;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002553
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002554 if (match_ipv) {
2555 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
2556 ip_version, 0xf);
2557 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Boris Pismenny3346c482017-08-20 15:13:08 +03002558 ip_version, MLX5_FS_IPV4_VERSION);
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002559 } else {
2560 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
2561 ethertype, 0xffff);
2562 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
2563 ethertype, ETH_P_IP);
2564 }
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002565
Moses Reuben2d1e6972016-11-14 19:04:52 +02002566 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002567 src_ipv4_src_ipv6.ipv4_layout.ipv4),
2568 &ib_spec->ipv4.mask.src_ip,
2569 sizeof(ib_spec->ipv4.mask.src_ip));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002570 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002571 src_ipv4_src_ipv6.ipv4_layout.ipv4),
2572 &ib_spec->ipv4.val.src_ip,
2573 sizeof(ib_spec->ipv4.val.src_ip));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002574 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002575 dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
2576 &ib_spec->ipv4.mask.dst_ip,
2577 sizeof(ib_spec->ipv4.mask.dst_ip));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002578 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002579 dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
2580 &ib_spec->ipv4.val.dst_ip,
2581 sizeof(ib_spec->ipv4.val.dst_ip));
Maor Gottliebca0d4752016-08-30 16:58:35 +03002582
Moses Reuben2d1e6972016-11-14 19:04:52 +02002583 set_tos(headers_c, headers_v,
Maor Gottliebca0d4752016-08-30 16:58:35 +03002584 ib_spec->ipv4.mask.tos, ib_spec->ipv4.val.tos);
2585
Moses Reuben2d1e6972016-11-14 19:04:52 +02002586 set_proto(headers_c, headers_v,
Maor Gottliebca0d4752016-08-30 16:58:35 +03002587 ib_spec->ipv4.mask.proto, ib_spec->ipv4.val.proto);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002588 break;
Maor Gottlieb026bae02016-06-17 15:14:51 +03002589 case IB_FLOW_SPEC_IPV6:
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002590 if (FIELDS_NOT_SUPPORTED(ib_spec->ipv6.mask, LAST_IPV6_FIELD))
Leon Romanovsky1ffd3a22017-01-18 14:59:51 +02002591 return -EOPNOTSUPP;
Maor Gottlieb026bae02016-06-17 15:14:51 +03002592
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002593 if (match_ipv) {
2594 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
2595 ip_version, 0xf);
2596 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Boris Pismenny3346c482017-08-20 15:13:08 +03002597 ip_version, MLX5_FS_IPV6_VERSION);
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002598 } else {
2599 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
2600 ethertype, 0xffff);
2601 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
2602 ethertype, ETH_P_IPV6);
2603 }
Maor Gottlieb026bae02016-06-17 15:14:51 +03002604
Moses Reuben2d1e6972016-11-14 19:04:52 +02002605 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb026bae02016-06-17 15:14:51 +03002606 src_ipv4_src_ipv6.ipv6_layout.ipv6),
2607 &ib_spec->ipv6.mask.src_ip,
2608 sizeof(ib_spec->ipv6.mask.src_ip));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002609 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb026bae02016-06-17 15:14:51 +03002610 src_ipv4_src_ipv6.ipv6_layout.ipv6),
2611 &ib_spec->ipv6.val.src_ip,
2612 sizeof(ib_spec->ipv6.val.src_ip));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002613 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb026bae02016-06-17 15:14:51 +03002614 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
2615 &ib_spec->ipv6.mask.dst_ip,
2616 sizeof(ib_spec->ipv6.mask.dst_ip));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002617 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb026bae02016-06-17 15:14:51 +03002618 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
2619 &ib_spec->ipv6.val.dst_ip,
2620 sizeof(ib_spec->ipv6.val.dst_ip));
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002621
Moses Reuben2d1e6972016-11-14 19:04:52 +02002622 set_tos(headers_c, headers_v,
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002623 ib_spec->ipv6.mask.traffic_class,
2624 ib_spec->ipv6.val.traffic_class);
2625
Moses Reuben2d1e6972016-11-14 19:04:52 +02002626 set_proto(headers_c, headers_v,
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002627 ib_spec->ipv6.mask.next_hdr,
2628 ib_spec->ipv6.val.next_hdr);
2629
Moses Reuben2d1e6972016-11-14 19:04:52 +02002630 set_flow_label(misc_params_c, misc_params_v,
2631 ntohl(ib_spec->ipv6.mask.flow_label),
2632 ntohl(ib_spec->ipv6.val.flow_label),
2633 ib_spec->type & IB_FLOW_SPEC_INNER);
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002634 break;
2635 case IB_FLOW_SPEC_ESP:
2636 if (ib_spec->esp.mask.seq)
2637 return -EOPNOTSUPP;
Moses Reuben2d1e6972016-11-14 19:04:52 +02002638
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002639 MLX5_SET(fte_match_set_misc, misc_params_c, outer_esp_spi,
2640 ntohl(ib_spec->esp.mask.spi));
2641 MLX5_SET(fte_match_set_misc, misc_params_v, outer_esp_spi,
2642 ntohl(ib_spec->esp.val.spi));
Maor Gottlieb026bae02016-06-17 15:14:51 +03002643 break;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002644 case IB_FLOW_SPEC_TCP:
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002645 if (FIELDS_NOT_SUPPORTED(ib_spec->tcp_udp.mask,
2646 LAST_TCP_UDP_FIELD))
Leon Romanovsky1ffd3a22017-01-18 14:59:51 +02002647 return -EOPNOTSUPP;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002648
Moses Reuben2d1e6972016-11-14 19:04:52 +02002649 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002650 0xff);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002651 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002652 IPPROTO_TCP);
2653
Moses Reuben2d1e6972016-11-14 19:04:52 +02002654 MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_sport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002655 ntohs(ib_spec->tcp_udp.mask.src_port));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002656 MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_sport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002657 ntohs(ib_spec->tcp_udp.val.src_port));
2658
Moses Reuben2d1e6972016-11-14 19:04:52 +02002659 MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_dport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002660 ntohs(ib_spec->tcp_udp.mask.dst_port));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002661 MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_dport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002662 ntohs(ib_spec->tcp_udp.val.dst_port));
2663 break;
2664 case IB_FLOW_SPEC_UDP:
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002665 if (FIELDS_NOT_SUPPORTED(ib_spec->tcp_udp.mask,
2666 LAST_TCP_UDP_FIELD))
Leon Romanovsky1ffd3a22017-01-18 14:59:51 +02002667 return -EOPNOTSUPP;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002668
Moses Reuben2d1e6972016-11-14 19:04:52 +02002669 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002670 0xff);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002671 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002672 IPPROTO_UDP);
2673
Moses Reuben2d1e6972016-11-14 19:04:52 +02002674 MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_sport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002675 ntohs(ib_spec->tcp_udp.mask.src_port));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002676 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002677 ntohs(ib_spec->tcp_udp.val.src_port));
2678
Moses Reuben2d1e6972016-11-14 19:04:52 +02002679 MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_dport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002680 ntohs(ib_spec->tcp_udp.mask.dst_port));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002681 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002682 ntohs(ib_spec->tcp_udp.val.dst_port));
2683 break;
Ariel Levkovichda2f22a2018-05-13 14:33:33 +03002684 case IB_FLOW_SPEC_GRE:
2685 if (ib_spec->gre.mask.c_ks_res0_ver)
2686 return -EOPNOTSUPP;
2687
2688 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
2689 0xff);
2690 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
2691 IPPROTO_GRE);
2692
2693 MLX5_SET(fte_match_set_misc, misc_params_c, gre_protocol,
2694 0xffff);
2695 MLX5_SET(fte_match_set_misc, misc_params_v, gre_protocol,
2696 ntohs(ib_spec->gre.val.protocol));
2697
2698 memcpy(MLX5_ADDR_OF(fte_match_set_misc, misc_params_c,
2699 gre_key_h),
2700 &ib_spec->gre.mask.key,
2701 sizeof(ib_spec->gre.mask.key));
2702 memcpy(MLX5_ADDR_OF(fte_match_set_misc, misc_params_v,
2703 gre_key_h),
2704 &ib_spec->gre.val.key,
2705 sizeof(ib_spec->gre.val.key));
2706 break;
Ariel Levkovich71c6e862018-05-13 14:33:34 +03002707 case IB_FLOW_SPEC_MPLS:
2708 switch (prev_type) {
2709 case IB_FLOW_SPEC_UDP:
2710 if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
2711 ft_field_support.outer_first_mpls_over_udp),
2712 &ib_spec->mpls.mask.tag))
2713 return -EOPNOTSUPP;
2714
2715 memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v,
2716 outer_first_mpls_over_udp),
2717 &ib_spec->mpls.val.tag,
2718 sizeof(ib_spec->mpls.val.tag));
2719 memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c,
2720 outer_first_mpls_over_udp),
2721 &ib_spec->mpls.mask.tag,
2722 sizeof(ib_spec->mpls.mask.tag));
2723 break;
2724 case IB_FLOW_SPEC_GRE:
2725 if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
2726 ft_field_support.outer_first_mpls_over_gre),
2727 &ib_spec->mpls.mask.tag))
2728 return -EOPNOTSUPP;
2729
2730 memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v,
2731 outer_first_mpls_over_gre),
2732 &ib_spec->mpls.val.tag,
2733 sizeof(ib_spec->mpls.val.tag));
2734 memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c,
2735 outer_first_mpls_over_gre),
2736 &ib_spec->mpls.mask.tag,
2737 sizeof(ib_spec->mpls.mask.tag));
2738 break;
2739 default:
2740 if (ib_spec->type & IB_FLOW_SPEC_INNER) {
2741 if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
2742 ft_field_support.inner_first_mpls),
2743 &ib_spec->mpls.mask.tag))
2744 return -EOPNOTSUPP;
2745
2746 memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v,
2747 inner_first_mpls),
2748 &ib_spec->mpls.val.tag,
2749 sizeof(ib_spec->mpls.val.tag));
2750 memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c,
2751 inner_first_mpls),
2752 &ib_spec->mpls.mask.tag,
2753 sizeof(ib_spec->mpls.mask.tag));
2754 } else {
2755 if (check_mpls_supp_fields(MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
2756 ft_field_support.outer_first_mpls),
2757 &ib_spec->mpls.mask.tag))
2758 return -EOPNOTSUPP;
2759
2760 memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_v,
2761 outer_first_mpls),
2762 &ib_spec->mpls.val.tag,
2763 sizeof(ib_spec->mpls.val.tag));
2764 memcpy(MLX5_ADDR_OF(fte_match_set_misc2, misc_params2_c,
2765 outer_first_mpls),
2766 &ib_spec->mpls.mask.tag,
2767 sizeof(ib_spec->mpls.mask.tag));
2768 }
2769 }
2770 break;
Moses Reubenffb30d82016-11-14 19:04:50 +02002771 case IB_FLOW_SPEC_VXLAN_TUNNEL:
2772 if (FIELDS_NOT_SUPPORTED(ib_spec->tunnel.mask,
2773 LAST_TUNNEL_FIELD))
Leon Romanovsky1ffd3a22017-01-18 14:59:51 +02002774 return -EOPNOTSUPP;
Moses Reubenffb30d82016-11-14 19:04:50 +02002775
2776 MLX5_SET(fte_match_set_misc, misc_params_c, vxlan_vni,
2777 ntohl(ib_spec->tunnel.mask.tunnel_id));
2778 MLX5_SET(fte_match_set_misc, misc_params_v, vxlan_vni,
2779 ntohl(ib_spec->tunnel.val.tunnel_id));
2780 break;
Moses Reuben2ac693f2017-01-18 14:59:50 +02002781 case IB_FLOW_SPEC_ACTION_TAG:
2782 if (FIELDS_NOT_SUPPORTED(ib_spec->flow_tag,
2783 LAST_FLOW_TAG_FIELD))
2784 return -EOPNOTSUPP;
2785 if (ib_spec->flow_tag.tag_id >= BIT(24))
2786 return -EINVAL;
2787
Boris Pismenny075572d2017-08-16 09:33:30 +03002788 action->flow_tag = ib_spec->flow_tag.tag_id;
Matan Baraka9db0ec2017-08-16 09:43:48 +03002789 action->has_flow_tag = true;
Moses Reuben2ac693f2017-01-18 14:59:50 +02002790 break;
Slava Shwartsmana22ed862017-04-03 13:13:52 +03002791 case IB_FLOW_SPEC_ACTION_DROP:
2792 if (FIELDS_NOT_SUPPORTED(ib_spec->drop,
2793 LAST_DROP_FIELD))
2794 return -EOPNOTSUPP;
Boris Pismenny075572d2017-08-16 09:33:30 +03002795 action->action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
Slava Shwartsmana22ed862017-04-03 13:13:52 +03002796 break;
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002797 case IB_FLOW_SPEC_ACTION_HANDLE:
2798 ret = parse_flow_flow_action(ib_spec, flow_attr, action);
2799 if (ret)
2800 return ret;
2801 break;
Raed Salem3b3233f2018-05-31 16:43:39 +03002802 case IB_FLOW_SPEC_ACTION_COUNT:
2803 if (FIELDS_NOT_SUPPORTED(ib_spec->flow_count,
2804 LAST_COUNTERS_FIELD))
2805 return -EOPNOTSUPP;
2806
2807 /* for now support only one counters spec per flow */
2808 if (action->action & MLX5_FLOW_CONTEXT_ACTION_COUNT)
2809 return -EINVAL;
2810
2811 action->counters = ib_spec->flow_count.counters;
2812 action->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
2813 break;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002814 default:
2815 return -EINVAL;
2816 }
2817
2818 return 0;
2819}
2820
2821/* If a flow could catch both multicast and unicast packets,
2822 * it won't fall into the multicast flow steering table and this rule
2823 * could steal other multicast packets.
2824 */
Yishai Hadasa550ddf2017-08-17 15:52:33 +03002825static bool flow_is_multicast_only(const struct ib_flow_attr *ib_attr)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002826{
Yishai Hadas81e30882017-06-08 16:15:09 +03002827 union ib_flow_spec *flow_spec;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002828
2829 if (ib_attr->type != IB_FLOW_ATTR_NORMAL ||
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002830 ib_attr->num_of_specs < 1)
2831 return false;
2832
Yishai Hadas81e30882017-06-08 16:15:09 +03002833 flow_spec = (union ib_flow_spec *)(ib_attr + 1);
2834 if (flow_spec->type == IB_FLOW_SPEC_IPV4) {
2835 struct ib_flow_spec_ipv4 *ipv4_spec;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002836
Yishai Hadas81e30882017-06-08 16:15:09 +03002837 ipv4_spec = (struct ib_flow_spec_ipv4 *)flow_spec;
2838 if (ipv4_is_multicast(ipv4_spec->val.dst_ip))
2839 return true;
2840
2841 return false;
2842 }
2843
2844 if (flow_spec->type == IB_FLOW_SPEC_ETH) {
2845 struct ib_flow_spec_eth *eth_spec;
2846
2847 eth_spec = (struct ib_flow_spec_eth *)flow_spec;
2848 return is_multicast_ether_addr(eth_spec->mask.dst_mac) &&
2849 is_multicast_ether_addr(eth_spec->val.dst_mac);
2850 }
2851
2852 return false;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002853}
2854
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002855enum valid_spec {
2856 VALID_SPEC_INVALID,
2857 VALID_SPEC_VALID,
2858 VALID_SPEC_NA,
2859};
2860
2861static enum valid_spec
2862is_valid_esp_aes_gcm(struct mlx5_core_dev *mdev,
2863 const struct mlx5_flow_spec *spec,
2864 const struct mlx5_flow_act *flow_act,
2865 bool egress)
2866{
2867 const u32 *match_c = spec->match_criteria;
2868 bool is_crypto =
2869 (flow_act->action & (MLX5_FLOW_CONTEXT_ACTION_ENCRYPT |
2870 MLX5_FLOW_CONTEXT_ACTION_DECRYPT));
2871 bool is_ipsec = mlx5_fs_is_ipsec_flow(match_c);
2872 bool is_drop = flow_act->action & MLX5_FLOW_CONTEXT_ACTION_DROP;
2873
2874 /*
2875 * Currently only crypto is supported in egress, when regular egress
2876 * rules would be supported, always return VALID_SPEC_NA.
2877 */
2878 if (!is_crypto)
2879 return egress ? VALID_SPEC_INVALID : VALID_SPEC_NA;
2880
2881 return is_crypto && is_ipsec &&
2882 (!egress || (!is_drop && !flow_act->has_flow_tag)) ?
2883 VALID_SPEC_VALID : VALID_SPEC_INVALID;
2884}
2885
2886static bool is_valid_spec(struct mlx5_core_dev *mdev,
2887 const struct mlx5_flow_spec *spec,
2888 const struct mlx5_flow_act *flow_act,
2889 bool egress)
2890{
2891 /* We curretly only support ipsec egress flow */
2892 return is_valid_esp_aes_gcm(mdev, spec, flow_act, egress) != VALID_SPEC_INVALID;
2893}
2894
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002895static bool is_valid_ethertype(struct mlx5_core_dev *mdev,
2896 const struct ib_flow_attr *flow_attr,
Ariel Levkovich0f750962017-04-03 13:11:02 +03002897 bool check_inner)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002898{
2899 union ib_flow_spec *ib_spec = (union ib_flow_spec *)(flow_attr + 1);
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002900 int match_ipv = check_inner ?
2901 MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
2902 ft_field_support.inner_ip_version) :
2903 MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
2904 ft_field_support.outer_ip_version);
Ariel Levkovich0f750962017-04-03 13:11:02 +03002905 int inner_bit = check_inner ? IB_FLOW_SPEC_INNER : 0;
2906 bool ipv4_spec_valid, ipv6_spec_valid;
2907 unsigned int ip_spec_type = 0;
2908 bool has_ethertype = false;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002909 unsigned int spec_index;
Ariel Levkovich0f750962017-04-03 13:11:02 +03002910 bool mask_valid = true;
2911 u16 eth_type = 0;
2912 bool type_valid;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002913
2914 /* Validate that ethertype is correct */
2915 for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
Ariel Levkovich0f750962017-04-03 13:11:02 +03002916 if ((ib_spec->type == (IB_FLOW_SPEC_ETH | inner_bit)) &&
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002917 ib_spec->eth.mask.ether_type) {
Ariel Levkovich0f750962017-04-03 13:11:02 +03002918 mask_valid = (ib_spec->eth.mask.ether_type ==
2919 htons(0xffff));
2920 has_ethertype = true;
2921 eth_type = ntohs(ib_spec->eth.val.ether_type);
2922 } else if ((ib_spec->type == (IB_FLOW_SPEC_IPV4 | inner_bit)) ||
2923 (ib_spec->type == (IB_FLOW_SPEC_IPV6 | inner_bit))) {
2924 ip_spec_type = ib_spec->type;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002925 }
2926 ib_spec = (void *)ib_spec + ib_spec->size;
2927 }
Ariel Levkovich0f750962017-04-03 13:11:02 +03002928
2929 type_valid = (!has_ethertype) || (!ip_spec_type);
2930 if (!type_valid && mask_valid) {
2931 ipv4_spec_valid = (eth_type == ETH_P_IP) &&
2932 (ip_spec_type == (IB_FLOW_SPEC_IPV4 | inner_bit));
2933 ipv6_spec_valid = (eth_type == ETH_P_IPV6) &&
2934 (ip_spec_type == (IB_FLOW_SPEC_IPV6 | inner_bit));
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002935
2936 type_valid = (ipv4_spec_valid) || (ipv6_spec_valid) ||
2937 (((eth_type == ETH_P_MPLS_UC) ||
2938 (eth_type == ETH_P_MPLS_MC)) && match_ipv);
Ariel Levkovich0f750962017-04-03 13:11:02 +03002939 }
2940
2941 return type_valid;
2942}
2943
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002944static bool is_valid_attr(struct mlx5_core_dev *mdev,
2945 const struct ib_flow_attr *flow_attr)
Ariel Levkovich0f750962017-04-03 13:11:02 +03002946{
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002947 return is_valid_ethertype(mdev, flow_attr, false) &&
2948 is_valid_ethertype(mdev, flow_attr, true);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002949}
2950
2951static void put_flow_table(struct mlx5_ib_dev *dev,
2952 struct mlx5_ib_flow_prio *prio, bool ft_added)
2953{
2954 prio->refcount -= !!ft_added;
2955 if (!prio->refcount) {
2956 mlx5_destroy_flow_table(prio->flow_table);
2957 prio->flow_table = NULL;
2958 }
2959}
2960
Raed Salem3b3233f2018-05-31 16:43:39 +03002961static void counters_clear_description(struct ib_counters *counters)
2962{
2963 struct mlx5_ib_mcounters *mcounters = to_mcounters(counters);
2964
2965 mutex_lock(&mcounters->mcntrs_mutex);
2966 kfree(mcounters->counters_data);
2967 mcounters->counters_data = NULL;
2968 mcounters->cntrs_max_index = 0;
2969 mutex_unlock(&mcounters->mcntrs_mutex);
2970}
2971
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002972static int mlx5_ib_destroy_flow(struct ib_flow *flow_id)
2973{
2974 struct mlx5_ib_dev *dev = to_mdev(flow_id->qp->device);
2975 struct mlx5_ib_flow_handler *handler = container_of(flow_id,
2976 struct mlx5_ib_flow_handler,
2977 ibflow);
2978 struct mlx5_ib_flow_handler *iter, *tmp;
2979
Mark Bloch9a4ca382018-01-16 14:42:35 +00002980 mutex_lock(&dev->flow_db->lock);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002981
2982 list_for_each_entry_safe(iter, tmp, &handler->list, list) {
Mark Bloch74491de2016-08-31 11:24:25 +00002983 mlx5_del_flow_rules(iter->rule);
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03002984 put_flow_table(dev, iter->prio, true);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002985 list_del(&iter->list);
2986 kfree(iter);
2987 }
2988
Mark Bloch74491de2016-08-31 11:24:25 +00002989 mlx5_del_flow_rules(handler->rule);
Maor Gottlieb5497adc2016-08-28 14:16:31 +03002990 put_flow_table(dev, handler->prio, true);
Raed Salem3b3233f2018-05-31 16:43:39 +03002991 if (handler->ibcounters &&
2992 atomic_read(&handler->ibcounters->usecnt) == 1)
2993 counters_clear_description(handler->ibcounters);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002994
Raed Salem3b3233f2018-05-31 16:43:39 +03002995 mutex_unlock(&dev->flow_db->lock);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002996 kfree(handler);
2997
2998 return 0;
2999}
3000
Maor Gottlieb35d190112016-03-07 18:51:47 +02003001static int ib_prio_to_core_prio(unsigned int priority, bool dont_trap)
3002{
3003 priority *= 2;
3004 if (!dont_trap)
3005 priority++;
3006 return priority;
3007}
3008
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003009enum flow_table_type {
3010 MLX5_IB_FT_RX,
3011 MLX5_IB_FT_TX
3012};
3013
Maor Gottlieb00b7c2a2017-03-29 06:09:01 +03003014#define MLX5_FS_MAX_TYPES 6
3015#define MLX5_FS_MAX_ENTRIES BIT(16)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003016static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003017 struct ib_flow_attr *flow_attr,
3018 enum flow_table_type ft_type)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003019{
Maor Gottlieb35d190112016-03-07 18:51:47 +02003020 bool dont_trap = flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003021 struct mlx5_flow_namespace *ns = NULL;
3022 struct mlx5_ib_flow_prio *prio;
3023 struct mlx5_flow_table *ft;
Maor Gottliebdac388e2017-03-29 06:09:00 +03003024 int max_table_size;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003025 int num_entries;
3026 int num_groups;
3027 int priority;
3028 int err = 0;
3029
Maor Gottliebdac388e2017-03-29 06:09:00 +03003030 max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
3031 log_max_ft_size));
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003032 if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003033 if (ft_type == MLX5_IB_FT_TX)
3034 priority = 0;
3035 else if (flow_is_multicast_only(flow_attr) &&
3036 !dont_trap)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003037 priority = MLX5_IB_FLOW_MCAST_PRIO;
3038 else
Maor Gottlieb35d190112016-03-07 18:51:47 +02003039 priority = ib_prio_to_core_prio(flow_attr->priority,
3040 dont_trap);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003041 ns = mlx5_get_flow_namespace(dev->mdev,
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003042 ft_type == MLX5_IB_FT_TX ?
3043 MLX5_FLOW_NAMESPACE_EGRESS :
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003044 MLX5_FLOW_NAMESPACE_BYPASS);
3045 num_entries = MLX5_FS_MAX_ENTRIES;
3046 num_groups = MLX5_FS_MAX_TYPES;
Mark Bloch9a4ca382018-01-16 14:42:35 +00003047 prio = &dev->flow_db->prios[priority];
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003048 } else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
3049 flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) {
3050 ns = mlx5_get_flow_namespace(dev->mdev,
3051 MLX5_FLOW_NAMESPACE_LEFTOVERS);
3052 build_leftovers_ft_param(&priority,
3053 &num_entries,
3054 &num_groups);
Mark Bloch9a4ca382018-01-16 14:42:35 +00003055 prio = &dev->flow_db->prios[MLX5_IB_FLOW_LEFTOVERS_PRIO];
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003056 } else if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) {
3057 if (!MLX5_CAP_FLOWTABLE(dev->mdev,
3058 allow_sniffer_and_nic_rx_shared_tir))
3059 return ERR_PTR(-ENOTSUPP);
3060
3061 ns = mlx5_get_flow_namespace(dev->mdev, ft_type == MLX5_IB_FT_RX ?
3062 MLX5_FLOW_NAMESPACE_SNIFFER_RX :
3063 MLX5_FLOW_NAMESPACE_SNIFFER_TX);
3064
Mark Bloch9a4ca382018-01-16 14:42:35 +00003065 prio = &dev->flow_db->sniffer[ft_type];
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003066 priority = 0;
3067 num_entries = 1;
3068 num_groups = 1;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003069 }
3070
3071 if (!ns)
3072 return ERR_PTR(-ENOTSUPP);
3073
Maor Gottliebdac388e2017-03-29 06:09:00 +03003074 if (num_entries > max_table_size)
3075 return ERR_PTR(-ENOMEM);
3076
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003077 ft = prio->flow_table;
3078 if (!ft) {
3079 ft = mlx5_create_auto_grouped_flow_table(ns, priority,
3080 num_entries,
Maor Gottliebd63cd282016-04-29 01:36:35 +03003081 num_groups,
Hadar Hen Zionc9f1b072016-11-07 15:14:44 +02003082 0, 0);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003083
3084 if (!IS_ERR(ft)) {
3085 prio->refcount = 0;
3086 prio->flow_table = ft;
3087 } else {
3088 err = PTR_ERR(ft);
3089 }
3090 }
3091
3092 return err ? ERR_PTR(err) : prio;
3093}
3094
Yishai Hadasa550ddf2017-08-17 15:52:33 +03003095static void set_underlay_qp(struct mlx5_ib_dev *dev,
3096 struct mlx5_flow_spec *spec,
3097 u32 underlay_qpn)
3098{
3099 void *misc_params_c = MLX5_ADDR_OF(fte_match_param,
3100 spec->match_criteria,
3101 misc_parameters);
3102 void *misc_params_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
3103 misc_parameters);
3104
3105 if (underlay_qpn &&
3106 MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
3107 ft_field_support.bth_dst_qp)) {
3108 MLX5_SET(fte_match_set_misc,
3109 misc_params_v, bth_dst_qp, underlay_qpn);
3110 MLX5_SET(fte_match_set_misc,
3111 misc_params_c, bth_dst_qp, 0xffffff);
3112 }
3113}
3114
Raed Salem5e95af52018-05-31 16:43:40 +03003115static int read_flow_counters(struct ib_device *ibdev,
3116 struct mlx5_read_counters_attr *read_attr)
3117{
3118 struct mlx5_fc *fc = read_attr->hw_cntrs_hndl;
3119 struct mlx5_ib_dev *dev = to_mdev(ibdev);
3120
3121 return mlx5_fc_query(dev->mdev, fc,
3122 &read_attr->out[IB_COUNTER_PACKETS],
3123 &read_attr->out[IB_COUNTER_BYTES]);
3124}
3125
3126/* flow counters currently expose two counters packets and bytes */
3127#define FLOW_COUNTERS_NUM 2
Raed Salem3b3233f2018-05-31 16:43:39 +03003128static int counters_set_description(struct ib_counters *counters,
3129 enum mlx5_ib_counters_type counters_type,
3130 struct mlx5_ib_flow_counters_desc *desc_data,
3131 u32 ncounters)
3132{
3133 struct mlx5_ib_mcounters *mcounters = to_mcounters(counters);
3134 u32 cntrs_max_index = 0;
3135 int i;
3136
3137 if (counters_type != MLX5_IB_COUNTERS_FLOW)
3138 return -EINVAL;
3139
3140 /* init the fields for the object */
3141 mcounters->type = counters_type;
Raed Salem5e95af52018-05-31 16:43:40 +03003142 mcounters->read_counters = read_flow_counters;
3143 mcounters->counters_num = FLOW_COUNTERS_NUM;
Raed Salem3b3233f2018-05-31 16:43:39 +03003144 mcounters->ncounters = ncounters;
3145 /* each counter entry have both description and index pair */
3146 for (i = 0; i < ncounters; i++) {
3147 if (desc_data[i].description > IB_COUNTER_BYTES)
3148 return -EINVAL;
3149
3150 if (cntrs_max_index <= desc_data[i].index)
3151 cntrs_max_index = desc_data[i].index + 1;
3152 }
3153
3154 mutex_lock(&mcounters->mcntrs_mutex);
3155 mcounters->counters_data = desc_data;
3156 mcounters->cntrs_max_index = cntrs_max_index;
3157 mutex_unlock(&mcounters->mcntrs_mutex);
3158
3159 return 0;
3160}
3161
3162#define MAX_COUNTERS_NUM (USHRT_MAX / (sizeof(u32) * 2))
3163static int flow_counters_set_data(struct ib_counters *ibcounters,
3164 struct mlx5_ib_create_flow *ucmd)
3165{
3166 struct mlx5_ib_mcounters *mcounters = to_mcounters(ibcounters);
3167 struct mlx5_ib_flow_counters_data *cntrs_data = NULL;
3168 struct mlx5_ib_flow_counters_desc *desc_data = NULL;
3169 bool hw_hndl = false;
3170 int ret = 0;
3171
3172 if (ucmd && ucmd->ncounters_data != 0) {
3173 cntrs_data = ucmd->data;
3174 if (cntrs_data->ncounters > MAX_COUNTERS_NUM)
3175 return -EINVAL;
3176
3177 desc_data = kcalloc(cntrs_data->ncounters,
3178 sizeof(*desc_data),
3179 GFP_KERNEL);
3180 if (!desc_data)
3181 return -ENOMEM;
3182
3183 if (copy_from_user(desc_data,
3184 u64_to_user_ptr(cntrs_data->counters_data),
3185 sizeof(*desc_data) * cntrs_data->ncounters)) {
3186 ret = -EFAULT;
3187 goto free;
3188 }
3189 }
3190
3191 if (!mcounters->hw_cntrs_hndl) {
3192 mcounters->hw_cntrs_hndl = mlx5_fc_create(
3193 to_mdev(ibcounters->device)->mdev, false);
3194 if (!mcounters->hw_cntrs_hndl) {
3195 ret = -ENOMEM;
3196 goto free;
3197 }
3198 hw_hndl = true;
3199 }
3200
3201 if (desc_data) {
3202 /* counters already bound to at least one flow */
3203 if (mcounters->cntrs_max_index) {
3204 ret = -EINVAL;
3205 goto free_hndl;
3206 }
3207
3208 ret = counters_set_description(ibcounters,
3209 MLX5_IB_COUNTERS_FLOW,
3210 desc_data,
3211 cntrs_data->ncounters);
3212 if (ret)
3213 goto free_hndl;
3214
3215 } else if (!mcounters->cntrs_max_index) {
3216 /* counters not bound yet, must have udata passed */
3217 ret = -EINVAL;
3218 goto free_hndl;
3219 }
3220
3221 return 0;
3222
3223free_hndl:
3224 if (hw_hndl) {
3225 mlx5_fc_destroy(to_mdev(ibcounters->device)->mdev,
3226 mcounters->hw_cntrs_hndl);
3227 mcounters->hw_cntrs_hndl = NULL;
3228 }
3229free:
3230 kfree(desc_data);
3231 return ret;
3232}
3233
Yishai Hadasa550ddf2017-08-17 15:52:33 +03003234static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
3235 struct mlx5_ib_flow_prio *ft_prio,
3236 const struct ib_flow_attr *flow_attr,
3237 struct mlx5_flow_destination *dst,
Raed Salem3b3233f2018-05-31 16:43:39 +03003238 u32 underlay_qpn,
3239 struct mlx5_ib_create_flow *ucmd)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003240{
3241 struct mlx5_flow_table *ft = ft_prio->flow_table;
3242 struct mlx5_ib_flow_handler *handler;
Boris Pismenny075572d2017-08-16 09:33:30 +03003243 struct mlx5_flow_act flow_act = {.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG};
Maor Gottliebc5bb1732016-07-04 17:23:05 +03003244 struct mlx5_flow_spec *spec;
Raed Salem3b3233f2018-05-31 16:43:39 +03003245 struct mlx5_flow_destination dest_arr[2] = {};
3246 struct mlx5_flow_destination *rule_dst = dest_arr;
Maor Gottliebdd063d02016-08-28 14:16:32 +03003247 const void *ib_flow = (const void *)flow_attr + sizeof(*flow_attr);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003248 unsigned int spec_index;
Ariel Levkovich71c6e862018-05-13 14:33:34 +03003249 u32 prev_type = 0;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003250 int err = 0;
Raed Salem3b3233f2018-05-31 16:43:39 +03003251 int dest_num = 0;
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003252 bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003253
Ariel Levkovich19cc7522017-04-03 13:11:03 +03003254 if (!is_valid_attr(dev->mdev, flow_attr))
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003255 return ERR_PTR(-EINVAL);
3256
Leon Romanovsky1b9a07e2017-05-10 21:32:18 +03003257 spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003258 handler = kzalloc(sizeof(*handler), GFP_KERNEL);
Maor Gottliebc5bb1732016-07-04 17:23:05 +03003259 if (!handler || !spec) {
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003260 err = -ENOMEM;
3261 goto free;
3262 }
3263
3264 INIT_LIST_HEAD(&handler->list);
Raed Salem3b3233f2018-05-31 16:43:39 +03003265 if (dst) {
3266 memcpy(&dest_arr[0], dst, sizeof(*dst));
3267 dest_num++;
3268 }
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003269
3270 for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
Ariel Levkovich19cc7522017-04-03 13:11:03 +03003271 err = parse_flow_attr(dev->mdev, spec->match_criteria,
Slava Shwartsmana22ed862017-04-03 13:13:52 +03003272 spec->match_value,
Ariel Levkovich71c6e862018-05-13 14:33:34 +03003273 ib_flow, flow_attr, &flow_act,
3274 prev_type);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003275 if (err < 0)
3276 goto free;
3277
Ariel Levkovich71c6e862018-05-13 14:33:34 +03003278 prev_type = ((union ib_flow_spec *)ib_flow)->type;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003279 ib_flow += ((union ib_flow_spec *)ib_flow)->size;
3280 }
3281
Yishai Hadasa550ddf2017-08-17 15:52:33 +03003282 if (!flow_is_multicast_only(flow_attr))
3283 set_underlay_qp(dev, spec, underlay_qpn);
3284
Mark Bloch018a94e2018-01-16 14:44:29 +00003285 if (dev->rep) {
3286 void *misc;
3287
3288 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
3289 misc_parameters);
3290 MLX5_SET(fte_match_set_misc, misc, source_port,
3291 dev->rep->vport);
3292 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
3293 misc_parameters);
3294 MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
3295 }
3296
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03003297 spec->match_criteria_enable = get_match_criteria_enable(spec->match_criteria);
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003298
3299 if (is_egress &&
3300 !is_valid_spec(dev->mdev, spec, &flow_act, is_egress)) {
3301 err = -EINVAL;
3302 goto free;
3303 }
3304
Raed Salem3b3233f2018-05-31 16:43:39 +03003305 if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
3306 err = flow_counters_set_data(flow_act.counters, ucmd);
3307 if (err)
3308 goto free;
3309
3310 handler->ibcounters = flow_act.counters;
3311 dest_arr[dest_num].type =
3312 MLX5_FLOW_DESTINATION_TYPE_COUNTER;
3313 dest_arr[dest_num].counter =
3314 to_mcounters(flow_act.counters)->hw_cntrs_hndl;
3315 dest_num++;
3316 }
3317
Boris Pismenny075572d2017-08-16 09:33:30 +03003318 if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP) {
Raed Salem3b3233f2018-05-31 16:43:39 +03003319 if (!(flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT)) {
3320 rule_dst = NULL;
3321 dest_num = 0;
3322 }
Slava Shwartsmana22ed862017-04-03 13:13:52 +03003323 } else {
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003324 if (is_egress)
3325 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW;
3326 else
3327 flow_act.action |=
Raed Salem3b3233f2018-05-31 16:43:39 +03003328 dest_num ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST :
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003329 MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
Slava Shwartsmana22ed862017-04-03 13:13:52 +03003330 }
Moses Reuben2ac693f2017-01-18 14:59:50 +02003331
Matan Baraka9db0ec2017-08-16 09:43:48 +03003332 if (flow_act.has_flow_tag &&
Moses Reuben2ac693f2017-01-18 14:59:50 +02003333 (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
3334 flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT)) {
3335 mlx5_ib_warn(dev, "Flow tag %u and attribute type %x isn't allowed in leftovers\n",
Boris Pismenny075572d2017-08-16 09:33:30 +03003336 flow_act.flow_tag, flow_attr->type);
Moses Reuben2ac693f2017-01-18 14:59:50 +02003337 err = -EINVAL;
3338 goto free;
3339 }
Mark Bloch74491de2016-08-31 11:24:25 +00003340 handler->rule = mlx5_add_flow_rules(ft, spec,
Hadar Hen Zion66958ed2016-11-07 15:14:45 +02003341 &flow_act,
Slava Shwartsmana22ed862017-04-03 13:13:52 +03003342 rule_dst, dest_num);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003343
3344 if (IS_ERR(handler->rule)) {
3345 err = PTR_ERR(handler->rule);
3346 goto free;
3347 }
3348
Maor Gottliebd9d49802016-08-28 14:16:33 +03003349 ft_prio->refcount++;
Maor Gottlieb5497adc2016-08-28 14:16:31 +03003350 handler->prio = ft_prio;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003351
3352 ft_prio->flow_table = ft;
3353free:
Raed Salem3b3233f2018-05-31 16:43:39 +03003354 if (err && handler) {
3355 if (handler->ibcounters &&
3356 atomic_read(&handler->ibcounters->usecnt) == 1)
3357 counters_clear_description(handler->ibcounters);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003358 kfree(handler);
Raed Salem3b3233f2018-05-31 16:43:39 +03003359 }
Maor Gottliebc5bb1732016-07-04 17:23:05 +03003360 kvfree(spec);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003361 return err ? ERR_PTR(err) : handler;
3362}
3363
Yishai Hadasa550ddf2017-08-17 15:52:33 +03003364static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev,
3365 struct mlx5_ib_flow_prio *ft_prio,
3366 const struct ib_flow_attr *flow_attr,
3367 struct mlx5_flow_destination *dst)
3368{
Raed Salem3b3233f2018-05-31 16:43:39 +03003369 return _create_flow_rule(dev, ft_prio, flow_attr, dst, 0, NULL);
Yishai Hadasa550ddf2017-08-17 15:52:33 +03003370}
3371
Maor Gottlieb35d190112016-03-07 18:51:47 +02003372static struct mlx5_ib_flow_handler *create_dont_trap_rule(struct mlx5_ib_dev *dev,
3373 struct mlx5_ib_flow_prio *ft_prio,
3374 struct ib_flow_attr *flow_attr,
3375 struct mlx5_flow_destination *dst)
3376{
3377 struct mlx5_ib_flow_handler *handler_dst = NULL;
3378 struct mlx5_ib_flow_handler *handler = NULL;
3379
3380 handler = create_flow_rule(dev, ft_prio, flow_attr, NULL);
3381 if (!IS_ERR(handler)) {
3382 handler_dst = create_flow_rule(dev, ft_prio,
3383 flow_attr, dst);
3384 if (IS_ERR(handler_dst)) {
Mark Bloch74491de2016-08-31 11:24:25 +00003385 mlx5_del_flow_rules(handler->rule);
Maor Gottliebd9d49802016-08-28 14:16:33 +03003386 ft_prio->refcount--;
Maor Gottlieb35d190112016-03-07 18:51:47 +02003387 kfree(handler);
3388 handler = handler_dst;
3389 } else {
3390 list_add(&handler_dst->list, &handler->list);
3391 }
3392 }
3393
3394 return handler;
3395}
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003396enum {
3397 LEFTOVERS_MC,
3398 LEFTOVERS_UC,
3399};
3400
3401static struct mlx5_ib_flow_handler *create_leftovers_rule(struct mlx5_ib_dev *dev,
3402 struct mlx5_ib_flow_prio *ft_prio,
3403 struct ib_flow_attr *flow_attr,
3404 struct mlx5_flow_destination *dst)
3405{
3406 struct mlx5_ib_flow_handler *handler_ucast = NULL;
3407 struct mlx5_ib_flow_handler *handler = NULL;
3408
3409 static struct {
3410 struct ib_flow_attr flow_attr;
3411 struct ib_flow_spec_eth eth_flow;
3412 } leftovers_specs[] = {
3413 [LEFTOVERS_MC] = {
3414 .flow_attr = {
3415 .num_of_specs = 1,
3416 .size = sizeof(leftovers_specs[0])
3417 },
3418 .eth_flow = {
3419 .type = IB_FLOW_SPEC_ETH,
3420 .size = sizeof(struct ib_flow_spec_eth),
3421 .mask = {.dst_mac = {0x1} },
3422 .val = {.dst_mac = {0x1} }
3423 }
3424 },
3425 [LEFTOVERS_UC] = {
3426 .flow_attr = {
3427 .num_of_specs = 1,
3428 .size = sizeof(leftovers_specs[0])
3429 },
3430 .eth_flow = {
3431 .type = IB_FLOW_SPEC_ETH,
3432 .size = sizeof(struct ib_flow_spec_eth),
3433 .mask = {.dst_mac = {0x1} },
3434 .val = {.dst_mac = {} }
3435 }
3436 }
3437 };
3438
3439 handler = create_flow_rule(dev, ft_prio,
3440 &leftovers_specs[LEFTOVERS_MC].flow_attr,
3441 dst);
3442 if (!IS_ERR(handler) &&
3443 flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT) {
3444 handler_ucast = create_flow_rule(dev, ft_prio,
3445 &leftovers_specs[LEFTOVERS_UC].flow_attr,
3446 dst);
3447 if (IS_ERR(handler_ucast)) {
Mark Bloch74491de2016-08-31 11:24:25 +00003448 mlx5_del_flow_rules(handler->rule);
Maor Gottliebd9d49802016-08-28 14:16:33 +03003449 ft_prio->refcount--;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003450 kfree(handler);
3451 handler = handler_ucast;
3452 } else {
3453 list_add(&handler_ucast->list, &handler->list);
3454 }
3455 }
3456
3457 return handler;
3458}
3459
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003460static struct mlx5_ib_flow_handler *create_sniffer_rule(struct mlx5_ib_dev *dev,
3461 struct mlx5_ib_flow_prio *ft_rx,
3462 struct mlx5_ib_flow_prio *ft_tx,
3463 struct mlx5_flow_destination *dst)
3464{
3465 struct mlx5_ib_flow_handler *handler_rx;
3466 struct mlx5_ib_flow_handler *handler_tx;
3467 int err;
3468 static const struct ib_flow_attr flow_attr = {
3469 .num_of_specs = 0,
3470 .size = sizeof(flow_attr)
3471 };
3472
3473 handler_rx = create_flow_rule(dev, ft_rx, &flow_attr, dst);
3474 if (IS_ERR(handler_rx)) {
3475 err = PTR_ERR(handler_rx);
3476 goto err;
3477 }
3478
3479 handler_tx = create_flow_rule(dev, ft_tx, &flow_attr, dst);
3480 if (IS_ERR(handler_tx)) {
3481 err = PTR_ERR(handler_tx);
3482 goto err_tx;
3483 }
3484
3485 list_add(&handler_tx->list, &handler_rx->list);
3486
3487 return handler_rx;
3488
3489err_tx:
Mark Bloch74491de2016-08-31 11:24:25 +00003490 mlx5_del_flow_rules(handler_rx->rule);
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003491 ft_rx->refcount--;
3492 kfree(handler_rx);
3493err:
3494 return ERR_PTR(err);
3495}
3496
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003497static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
3498 struct ib_flow_attr *flow_attr,
Matan Barak59082a32018-05-31 16:43:35 +03003499 int domain,
3500 struct ib_udata *udata)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003501{
3502 struct mlx5_ib_dev *dev = to_mdev(qp->device);
Yishai Hadasd9f88e52016-08-28 10:58:37 +03003503 struct mlx5_ib_qp *mqp = to_mqp(qp);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003504 struct mlx5_ib_flow_handler *handler = NULL;
3505 struct mlx5_flow_destination *dst = NULL;
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003506 struct mlx5_ib_flow_prio *ft_prio_tx = NULL;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003507 struct mlx5_ib_flow_prio *ft_prio;
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003508 bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS;
Raed Salem3b3233f2018-05-31 16:43:39 +03003509 struct mlx5_ib_create_flow *ucmd = NULL, ucmd_hdr;
3510 size_t min_ucmd_sz, required_ucmd_sz;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003511 int err;
Yishai Hadasa550ddf2017-08-17 15:52:33 +03003512 int underlay_qpn;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003513
Raed Salem3b3233f2018-05-31 16:43:39 +03003514 if (udata && udata->inlen) {
3515 min_ucmd_sz = offsetof(typeof(ucmd_hdr), reserved) +
3516 sizeof(ucmd_hdr.reserved);
3517 if (udata->inlen < min_ucmd_sz)
3518 return ERR_PTR(-EOPNOTSUPP);
3519
3520 err = ib_copy_from_udata(&ucmd_hdr, udata, min_ucmd_sz);
3521 if (err)
3522 return ERR_PTR(err);
3523
3524 /* currently supports only one counters data */
3525 if (ucmd_hdr.ncounters_data > 1)
3526 return ERR_PTR(-EINVAL);
3527
3528 required_ucmd_sz = min_ucmd_sz +
3529 sizeof(struct mlx5_ib_flow_counters_data) *
3530 ucmd_hdr.ncounters_data;
3531 if (udata->inlen > required_ucmd_sz &&
3532 !ib_is_udata_cleared(udata, required_ucmd_sz,
3533 udata->inlen - required_ucmd_sz))
3534 return ERR_PTR(-EOPNOTSUPP);
3535
3536 ucmd = kzalloc(required_ucmd_sz, GFP_KERNEL);
3537 if (!ucmd)
3538 return ERR_PTR(-ENOMEM);
3539
3540 err = ib_copy_from_udata(ucmd, udata, required_ucmd_sz);
3541 if (err) {
3542 kfree(ucmd);
3543 return ERR_PTR(err);
3544 }
3545 }
Matan Barak59082a32018-05-31 16:43:35 +03003546
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003547 if (flow_attr->priority > MLX5_IB_FLOW_LAST_PRIO)
Maor Gottliebdac388e2017-03-29 06:09:00 +03003548 return ERR_PTR(-ENOMEM);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003549
3550 if (domain != IB_FLOW_DOMAIN_USER ||
Daniel Jurgens508562d2018-01-04 17:25:34 +02003551 flow_attr->port > dev->num_ports ||
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003552 (flow_attr->flags & ~(IB_FLOW_ATTR_FLAGS_DONT_TRAP |
3553 IB_FLOW_ATTR_FLAGS_EGRESS)))
3554 return ERR_PTR(-EINVAL);
3555
3556 if (is_egress &&
3557 (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
3558 flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT))
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003559 return ERR_PTR(-EINVAL);
3560
3561 dst = kzalloc(sizeof(*dst), GFP_KERNEL);
3562 if (!dst)
3563 return ERR_PTR(-ENOMEM);
3564
Mark Bloch9a4ca382018-01-16 14:42:35 +00003565 mutex_lock(&dev->flow_db->lock);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003566
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003567 ft_prio = get_flow_table(dev, flow_attr,
3568 is_egress ? MLX5_IB_FT_TX : MLX5_IB_FT_RX);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003569 if (IS_ERR(ft_prio)) {
3570 err = PTR_ERR(ft_prio);
3571 goto unlock;
3572 }
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003573 if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) {
3574 ft_prio_tx = get_flow_table(dev, flow_attr, MLX5_IB_FT_TX);
3575 if (IS_ERR(ft_prio_tx)) {
3576 err = PTR_ERR(ft_prio_tx);
3577 ft_prio_tx = NULL;
3578 goto destroy_ft;
3579 }
3580 }
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003581
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003582 if (is_egress) {
3583 dst->type = MLX5_FLOW_DESTINATION_TYPE_PORT;
3584 } else {
3585 dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR;
3586 if (mqp->flags & MLX5_IB_QP_RSS)
3587 dst->tir_num = mqp->rss_qp.tirn;
3588 else
3589 dst->tir_num = mqp->raw_packet_qp.rq.tirn;
3590 }
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003591
3592 if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
Maor Gottlieb35d190112016-03-07 18:51:47 +02003593 if (flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP) {
3594 handler = create_dont_trap_rule(dev, ft_prio,
3595 flow_attr, dst);
3596 } else {
Yishai Hadasa550ddf2017-08-17 15:52:33 +03003597 underlay_qpn = (mqp->flags & MLX5_IB_QP_UNDERLAY) ?
3598 mqp->underlay_qpn : 0;
3599 handler = _create_flow_rule(dev, ft_prio, flow_attr,
Raed Salem3b3233f2018-05-31 16:43:39 +03003600 dst, underlay_qpn, ucmd);
Maor Gottlieb35d190112016-03-07 18:51:47 +02003601 }
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003602 } else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
3603 flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) {
3604 handler = create_leftovers_rule(dev, ft_prio, flow_attr,
3605 dst);
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003606 } else if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) {
3607 handler = create_sniffer_rule(dev, ft_prio, ft_prio_tx, dst);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003608 } else {
3609 err = -EINVAL;
3610 goto destroy_ft;
3611 }
3612
3613 if (IS_ERR(handler)) {
3614 err = PTR_ERR(handler);
3615 handler = NULL;
3616 goto destroy_ft;
3617 }
3618
Mark Bloch9a4ca382018-01-16 14:42:35 +00003619 mutex_unlock(&dev->flow_db->lock);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003620 kfree(dst);
Raed Salem3b3233f2018-05-31 16:43:39 +03003621 kfree(ucmd);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003622
3623 return &handler->ibflow;
3624
3625destroy_ft:
3626 put_flow_table(dev, ft_prio, false);
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003627 if (ft_prio_tx)
3628 put_flow_table(dev, ft_prio_tx, false);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003629unlock:
Mark Bloch9a4ca382018-01-16 14:42:35 +00003630 mutex_unlock(&dev->flow_db->lock);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003631 kfree(dst);
Raed Salem3b3233f2018-05-31 16:43:39 +03003632 kfree(ucmd);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003633 kfree(handler);
3634 return ERR_PTR(err);
3635}
3636
Aviad Yehezkelc6475a02018-03-28 09:27:50 +03003637static u32 mlx5_ib_flow_action_flags_to_accel_xfrm_flags(u32 mlx5_flags)
3638{
3639 u32 flags = 0;
3640
3641 if (mlx5_flags & MLX5_IB_UAPI_FLOW_ACTION_FLAGS_REQUIRE_METADATA)
3642 flags |= MLX5_ACCEL_XFRM_FLAG_REQUIRE_METADATA;
3643
3644 return flags;
3645}
3646
3647#define MLX5_FLOW_ACTION_ESP_CREATE_LAST_SUPPORTED MLX5_IB_UAPI_FLOW_ACTION_FLAGS_REQUIRE_METADATA
3648static struct ib_flow_action *
3649mlx5_ib_create_flow_action_esp(struct ib_device *device,
3650 const struct ib_flow_action_attrs_esp *attr,
3651 struct uverbs_attr_bundle *attrs)
3652{
3653 struct mlx5_ib_dev *mdev = to_mdev(device);
3654 struct ib_uverbs_flow_action_esp_keymat_aes_gcm *aes_gcm;
3655 struct mlx5_accel_esp_xfrm_attrs accel_attrs = {};
3656 struct mlx5_ib_flow_action *action;
3657 u64 action_flags;
3658 u64 flags;
3659 int err = 0;
3660
3661 if (IS_UVERBS_COPY_ERR(uverbs_copy_from(&action_flags, attrs,
3662 MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS)))
3663 return ERR_PTR(-EFAULT);
3664
3665 if (action_flags >= (MLX5_FLOW_ACTION_ESP_CREATE_LAST_SUPPORTED << 1))
3666 return ERR_PTR(-EOPNOTSUPP);
3667
3668 flags = mlx5_ib_flow_action_flags_to_accel_xfrm_flags(action_flags);
3669
3670 /* We current only support a subset of the standard features. Only a
3671 * keymat of type AES_GCM, with icv_len == 16, iv_algo == SEQ and esn
3672 * (with overlap). Full offload mode isn't supported.
3673 */
3674 if (!attr->keymat || attr->replay || attr->encap ||
3675 attr->spi || attr->seq || attr->tfc_pad ||
3676 attr->hard_limit_pkts ||
3677 (attr->flags & ~(IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED |
3678 IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ENCRYPT)))
3679 return ERR_PTR(-EOPNOTSUPP);
3680
3681 if (attr->keymat->protocol !=
3682 IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM)
3683 return ERR_PTR(-EOPNOTSUPP);
3684
3685 aes_gcm = &attr->keymat->keymat.aes_gcm;
3686
3687 if (aes_gcm->icv_len != 16 ||
3688 aes_gcm->iv_algo != IB_UVERBS_FLOW_ACTION_IV_ALGO_SEQ)
3689 return ERR_PTR(-EOPNOTSUPP);
3690
3691 action = kmalloc(sizeof(*action), GFP_KERNEL);
3692 if (!action)
3693 return ERR_PTR(-ENOMEM);
3694
3695 action->esp_aes_gcm.ib_flags = attr->flags;
3696 memcpy(&accel_attrs.keymat.aes_gcm.aes_key, &aes_gcm->aes_key,
3697 sizeof(accel_attrs.keymat.aes_gcm.aes_key));
3698 accel_attrs.keymat.aes_gcm.key_len = aes_gcm->key_len * 8;
3699 memcpy(&accel_attrs.keymat.aes_gcm.salt, &aes_gcm->salt,
3700 sizeof(accel_attrs.keymat.aes_gcm.salt));
3701 memcpy(&accel_attrs.keymat.aes_gcm.seq_iv, &aes_gcm->iv,
3702 sizeof(accel_attrs.keymat.aes_gcm.seq_iv));
3703 accel_attrs.keymat.aes_gcm.icv_len = aes_gcm->icv_len * 8;
3704 accel_attrs.keymat.aes_gcm.iv_algo = MLX5_ACCEL_ESP_AES_GCM_IV_ALGO_SEQ;
3705 accel_attrs.keymat_type = MLX5_ACCEL_ESP_KEYMAT_AES_GCM;
3706
3707 accel_attrs.esn = attr->esn;
3708 if (attr->flags & IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED)
3709 accel_attrs.flags |= MLX5_ACCEL_ESP_FLAGS_ESN_TRIGGERED;
3710 if (attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW)
3711 accel_attrs.flags |= MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP;
3712
3713 if (attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ENCRYPT)
3714 accel_attrs.action |= MLX5_ACCEL_ESP_ACTION_ENCRYPT;
3715
3716 action->esp_aes_gcm.ctx =
3717 mlx5_accel_esp_create_xfrm(mdev->mdev, &accel_attrs, flags);
3718 if (IS_ERR(action->esp_aes_gcm.ctx)) {
3719 err = PTR_ERR(action->esp_aes_gcm.ctx);
3720 goto err_parse;
3721 }
3722
3723 action->esp_aes_gcm.ib_flags = attr->flags;
3724
3725 return &action->ib_action;
3726
3727err_parse:
3728 kfree(action);
3729 return ERR_PTR(err);
3730}
3731
Matan Barak349705c2018-03-28 09:27:51 +03003732static int
3733mlx5_ib_modify_flow_action_esp(struct ib_flow_action *action,
3734 const struct ib_flow_action_attrs_esp *attr,
3735 struct uverbs_attr_bundle *attrs)
3736{
3737 struct mlx5_ib_flow_action *maction = to_mflow_act(action);
3738 struct mlx5_accel_esp_xfrm_attrs accel_attrs;
3739 int err = 0;
3740
3741 if (attr->keymat || attr->replay || attr->encap ||
3742 attr->spi || attr->seq || attr->tfc_pad ||
3743 attr->hard_limit_pkts ||
3744 (attr->flags & ~(IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED |
3745 IB_FLOW_ACTION_ESP_FLAGS_MOD_ESP_ATTRS |
3746 IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW)))
3747 return -EOPNOTSUPP;
3748
3749 /* Only the ESN value or the MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP can
3750 * be modified.
3751 */
3752 if (!(maction->esp_aes_gcm.ib_flags &
3753 IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED) &&
3754 attr->flags & (IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED |
3755 IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW))
3756 return -EINVAL;
3757
3758 memcpy(&accel_attrs, &maction->esp_aes_gcm.ctx->attrs,
3759 sizeof(accel_attrs));
3760
3761 accel_attrs.esn = attr->esn;
3762 if (attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW)
3763 accel_attrs.flags |= MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP;
3764 else
3765 accel_attrs.flags &= ~MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP;
3766
3767 err = mlx5_accel_esp_modify_xfrm(maction->esp_aes_gcm.ctx,
3768 &accel_attrs);
3769 if (err)
3770 return err;
3771
3772 maction->esp_aes_gcm.ib_flags &=
3773 ~IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW;
3774 maction->esp_aes_gcm.ib_flags |=
3775 attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW;
3776
3777 return 0;
3778}
3779
Aviad Yehezkelc6475a02018-03-28 09:27:50 +03003780static int mlx5_ib_destroy_flow_action(struct ib_flow_action *action)
3781{
3782 struct mlx5_ib_flow_action *maction = to_mflow_act(action);
3783
3784 switch (action->type) {
3785 case IB_FLOW_ACTION_ESP:
3786 /*
3787 * We only support aes_gcm by now, so we implicitly know this is
3788 * the underline crypto.
3789 */
3790 mlx5_accel_esp_destroy_xfrm(maction->esp_aes_gcm.ctx);
3791 break;
3792 default:
3793 WARN_ON(true);
3794 break;
3795 }
3796
3797 kfree(maction);
3798 return 0;
3799}
3800
Eli Cohene126ba92013-07-07 17:25:49 +03003801static int mlx5_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
3802{
3803 struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
Yishai Hadas81e30882017-06-08 16:15:09 +03003804 struct mlx5_ib_qp *mqp = to_mqp(ibqp);
Eli Cohene126ba92013-07-07 17:25:49 +03003805 int err;
3806
Yishai Hadas81e30882017-06-08 16:15:09 +03003807 if (mqp->flags & MLX5_IB_QP_UNDERLAY) {
3808 mlx5_ib_dbg(dev, "Attaching a multi cast group to underlay QP is not supported\n");
3809 return -EOPNOTSUPP;
3810 }
3811
Jack Morgenstein9603b612014-07-28 23:30:22 +03003812 err = mlx5_core_attach_mcg(dev->mdev, gid, ibqp->qp_num);
Eli Cohene126ba92013-07-07 17:25:49 +03003813 if (err)
3814 mlx5_ib_warn(dev, "failed attaching QPN 0x%x, MGID %pI6\n",
3815 ibqp->qp_num, gid->raw);
3816
3817 return err;
3818}
3819
3820static int mlx5_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
3821{
3822 struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
3823 int err;
3824
Jack Morgenstein9603b612014-07-28 23:30:22 +03003825 err = mlx5_core_detach_mcg(dev->mdev, gid, ibqp->qp_num);
Eli Cohene126ba92013-07-07 17:25:49 +03003826 if (err)
3827 mlx5_ib_warn(dev, "failed detaching QPN 0x%x, MGID %pI6\n",
3828 ibqp->qp_num, gid->raw);
3829
3830 return err;
3831}
3832
3833static int init_node_data(struct mlx5_ib_dev *dev)
3834{
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03003835 int err;
Eli Cohene126ba92013-07-07 17:25:49 +03003836
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03003837 err = mlx5_query_node_desc(dev, dev->ib_dev.node_desc);
Eli Cohene126ba92013-07-07 17:25:49 +03003838 if (err)
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03003839 return err;
Eli Cohene126ba92013-07-07 17:25:49 +03003840
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03003841 dev->mdev->rev_id = dev->mdev->pdev->revision;
Eli Cohene126ba92013-07-07 17:25:49 +03003842
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03003843 return mlx5_query_node_guid(dev, &dev->ib_dev.node_guid);
Eli Cohene126ba92013-07-07 17:25:49 +03003844}
3845
3846static ssize_t show_fw_pages(struct device *device, struct device_attribute *attr,
3847 char *buf)
3848{
3849 struct mlx5_ib_dev *dev =
3850 container_of(device, struct mlx5_ib_dev, ib_dev.dev);
3851
Jack Morgenstein9603b612014-07-28 23:30:22 +03003852 return sprintf(buf, "%d\n", dev->mdev->priv.fw_pages);
Eli Cohene126ba92013-07-07 17:25:49 +03003853}
3854
3855static ssize_t show_reg_pages(struct device *device,
3856 struct device_attribute *attr, char *buf)
3857{
3858 struct mlx5_ib_dev *dev =
3859 container_of(device, struct mlx5_ib_dev, ib_dev.dev);
3860
Haggai Eran6aec21f2014-12-11 17:04:23 +02003861 return sprintf(buf, "%d\n", atomic_read(&dev->mdev->priv.reg_pages));
Eli Cohene126ba92013-07-07 17:25:49 +03003862}
3863
3864static ssize_t show_hca(struct device *device, struct device_attribute *attr,
3865 char *buf)
3866{
3867 struct mlx5_ib_dev *dev =
3868 container_of(device, struct mlx5_ib_dev, ib_dev.dev);
Jack Morgenstein9603b612014-07-28 23:30:22 +03003869 return sprintf(buf, "MT%d\n", dev->mdev->pdev->device);
Eli Cohene126ba92013-07-07 17:25:49 +03003870}
3871
Eli Cohene126ba92013-07-07 17:25:49 +03003872static ssize_t show_rev(struct device *device, struct device_attribute *attr,
3873 char *buf)
3874{
3875 struct mlx5_ib_dev *dev =
3876 container_of(device, struct mlx5_ib_dev, ib_dev.dev);
Jack Morgenstein9603b612014-07-28 23:30:22 +03003877 return sprintf(buf, "%x\n", dev->mdev->rev_id);
Eli Cohene126ba92013-07-07 17:25:49 +03003878}
3879
3880static ssize_t show_board(struct device *device, struct device_attribute *attr,
3881 char *buf)
3882{
3883 struct mlx5_ib_dev *dev =
3884 container_of(device, struct mlx5_ib_dev, ib_dev.dev);
3885 return sprintf(buf, "%.*s\n", MLX5_BOARD_ID_LEN,
Jack Morgenstein9603b612014-07-28 23:30:22 +03003886 dev->mdev->board_id);
Eli Cohene126ba92013-07-07 17:25:49 +03003887}
3888
3889static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
Eli Cohene126ba92013-07-07 17:25:49 +03003890static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
3891static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
3892static DEVICE_ATTR(fw_pages, S_IRUGO, show_fw_pages, NULL);
3893static DEVICE_ATTR(reg_pages, S_IRUGO, show_reg_pages, NULL);
3894
3895static struct device_attribute *mlx5_class_attributes[] = {
3896 &dev_attr_hw_rev,
Eli Cohene126ba92013-07-07 17:25:49 +03003897 &dev_attr_hca_type,
3898 &dev_attr_board_id,
3899 &dev_attr_fw_pages,
3900 &dev_attr_reg_pages,
3901};
3902
Haggai Eran7722f472016-02-29 15:45:07 +02003903static void pkey_change_handler(struct work_struct *work)
3904{
3905 struct mlx5_ib_port_resources *ports =
3906 container_of(work, struct mlx5_ib_port_resources,
3907 pkey_change_work);
3908
3909 mutex_lock(&ports->devr->mutex);
3910 mlx5_ib_gsi_pkey_change(ports->gsi);
3911 mutex_unlock(&ports->devr->mutex);
3912}
3913
Maor Gottlieb89ea94a72016-06-17 15:01:38 +03003914static void mlx5_ib_handle_internal_error(struct mlx5_ib_dev *ibdev)
3915{
3916 struct mlx5_ib_qp *mqp;
3917 struct mlx5_ib_cq *send_mcq, *recv_mcq;
3918 struct mlx5_core_cq *mcq;
3919 struct list_head cq_armed_list;
3920 unsigned long flags_qp;
3921 unsigned long flags_cq;
3922 unsigned long flags;
3923
3924 INIT_LIST_HEAD(&cq_armed_list);
3925
3926 /* Go over qp list reside on that ibdev, sync with create/destroy qp.*/
3927 spin_lock_irqsave(&ibdev->reset_flow_resource_lock, flags);
3928 list_for_each_entry(mqp, &ibdev->qp_list, qps_list) {
3929 spin_lock_irqsave(&mqp->sq.lock, flags_qp);
3930 if (mqp->sq.tail != mqp->sq.head) {
3931 send_mcq = to_mcq(mqp->ibqp.send_cq);
3932 spin_lock_irqsave(&send_mcq->lock, flags_cq);
3933 if (send_mcq->mcq.comp &&
3934 mqp->ibqp.send_cq->comp_handler) {
3935 if (!send_mcq->mcq.reset_notify_added) {
3936 send_mcq->mcq.reset_notify_added = 1;
3937 list_add_tail(&send_mcq->mcq.reset_notify,
3938 &cq_armed_list);
3939 }
3940 }
3941 spin_unlock_irqrestore(&send_mcq->lock, flags_cq);
3942 }
3943 spin_unlock_irqrestore(&mqp->sq.lock, flags_qp);
3944 spin_lock_irqsave(&mqp->rq.lock, flags_qp);
3945 /* no handling is needed for SRQ */
3946 if (!mqp->ibqp.srq) {
3947 if (mqp->rq.tail != mqp->rq.head) {
3948 recv_mcq = to_mcq(mqp->ibqp.recv_cq);
3949 spin_lock_irqsave(&recv_mcq->lock, flags_cq);
3950 if (recv_mcq->mcq.comp &&
3951 mqp->ibqp.recv_cq->comp_handler) {
3952 if (!recv_mcq->mcq.reset_notify_added) {
3953 recv_mcq->mcq.reset_notify_added = 1;
3954 list_add_tail(&recv_mcq->mcq.reset_notify,
3955 &cq_armed_list);
3956 }
3957 }
3958 spin_unlock_irqrestore(&recv_mcq->lock,
3959 flags_cq);
3960 }
3961 }
3962 spin_unlock_irqrestore(&mqp->rq.lock, flags_qp);
3963 }
3964 /*At that point all inflight post send were put to be executed as of we
3965 * lock/unlock above locks Now need to arm all involved CQs.
3966 */
3967 list_for_each_entry(mcq, &cq_armed_list, reset_notify) {
3968 mcq->comp(mcq);
3969 }
3970 spin_unlock_irqrestore(&ibdev->reset_flow_resource_lock, flags);
3971}
3972
Maor Gottlieb03404e82017-05-30 10:29:13 +03003973static void delay_drop_handler(struct work_struct *work)
3974{
3975 int err;
3976 struct mlx5_ib_delay_drop *delay_drop =
3977 container_of(work, struct mlx5_ib_delay_drop,
3978 delay_drop_work);
3979
Maor Gottliebfe248c32017-05-30 10:29:14 +03003980 atomic_inc(&delay_drop->events_cnt);
3981
Maor Gottlieb03404e82017-05-30 10:29:13 +03003982 mutex_lock(&delay_drop->lock);
3983 err = mlx5_core_set_delay_drop(delay_drop->dev->mdev,
3984 delay_drop->timeout);
3985 if (err) {
3986 mlx5_ib_warn(delay_drop->dev, "Failed to set delay drop, timeout=%u\n",
3987 delay_drop->timeout);
3988 delay_drop->activate = false;
3989 }
3990 mutex_unlock(&delay_drop->lock);
3991}
3992
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02003993static void mlx5_ib_handle_event(struct work_struct *_work)
Eli Cohene126ba92013-07-07 17:25:49 +03003994{
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02003995 struct mlx5_ib_event_work *work =
3996 container_of(_work, struct mlx5_ib_event_work, work);
3997 struct mlx5_ib_dev *ibdev;
Eli Cohene126ba92013-07-07 17:25:49 +03003998 struct ib_event ibev;
Eli Cohendbaaff22016-10-27 16:36:44 +03003999 bool fatal = false;
Daniel Jurgensaba46212018-02-25 13:39:53 +02004000 u8 port = (u8)work->param;
Eli Cohene126ba92013-07-07 17:25:49 +03004001
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02004002 if (mlx5_core_is_mp_slave(work->dev)) {
4003 ibdev = mlx5_ib_get_ibdev_from_mpi(work->context);
4004 if (!ibdev)
4005 goto out;
4006 } else {
4007 ibdev = work->context;
4008 }
4009
4010 switch (work->event) {
Eli Cohene126ba92013-07-07 17:25:49 +03004011 case MLX5_DEV_EVENT_SYS_ERROR:
Eli Cohene126ba92013-07-07 17:25:49 +03004012 ibev.event = IB_EVENT_DEVICE_FATAL;
Maor Gottlieb89ea94a72016-06-17 15:01:38 +03004013 mlx5_ib_handle_internal_error(ibdev);
Eli Cohendbaaff22016-10-27 16:36:44 +03004014 fatal = true;
Eli Cohene126ba92013-07-07 17:25:49 +03004015 break;
4016
4017 case MLX5_DEV_EVENT_PORT_UP:
Eli Cohene126ba92013-07-07 17:25:49 +03004018 case MLX5_DEV_EVENT_PORT_DOWN:
Noa Osherovich2788cf32016-06-04 15:15:29 +03004019 case MLX5_DEV_EVENT_PORT_INITIALIZED:
Aviv Heller5ec8c832016-09-18 20:48:00 +03004020 /* In RoCE, port up/down events are handled in
4021 * mlx5_netdev_event().
4022 */
4023 if (mlx5_ib_port_link_layer(&ibdev->ib_dev, port) ==
4024 IB_LINK_LAYER_ETHERNET)
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02004025 goto out;
Aviv Heller5ec8c832016-09-18 20:48:00 +03004026
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02004027 ibev.event = (work->event == MLX5_DEV_EVENT_PORT_UP) ?
Aviv Heller5ec8c832016-09-18 20:48:00 +03004028 IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
Eli Cohene126ba92013-07-07 17:25:49 +03004029 break;
4030
Eli Cohene126ba92013-07-07 17:25:49 +03004031 case MLX5_DEV_EVENT_LID_CHANGE:
4032 ibev.event = IB_EVENT_LID_CHANGE;
Eli Cohene126ba92013-07-07 17:25:49 +03004033 break;
4034
4035 case MLX5_DEV_EVENT_PKEY_CHANGE:
4036 ibev.event = IB_EVENT_PKEY_CHANGE;
Haggai Eran7722f472016-02-29 15:45:07 +02004037 schedule_work(&ibdev->devr.ports[port - 1].pkey_change_work);
Eli Cohene126ba92013-07-07 17:25:49 +03004038 break;
4039
4040 case MLX5_DEV_EVENT_GUID_CHANGE:
4041 ibev.event = IB_EVENT_GID_CHANGE;
Eli Cohene126ba92013-07-07 17:25:49 +03004042 break;
4043
4044 case MLX5_DEV_EVENT_CLIENT_REREG:
4045 ibev.event = IB_EVENT_CLIENT_REREGISTER;
Eli Cohene126ba92013-07-07 17:25:49 +03004046 break;
Maor Gottlieb03404e82017-05-30 10:29:13 +03004047 case MLX5_DEV_EVENT_DELAY_DROP_TIMEOUT:
4048 schedule_work(&ibdev->delay_drop.delay_drop_work);
4049 goto out;
Saeed Mahameedbdc37922016-09-29 19:35:38 +03004050 default:
Maor Gottlieb03404e82017-05-30 10:29:13 +03004051 goto out;
Eli Cohene126ba92013-07-07 17:25:49 +03004052 }
4053
4054 ibev.device = &ibdev->ib_dev;
4055 ibev.element.port_num = port;
4056
Daniel Jurgensaba46212018-02-25 13:39:53 +02004057 if (!rdma_is_port_valid(&ibdev->ib_dev, port)) {
Eli Cohena0c84c32013-09-11 16:35:27 +03004058 mlx5_ib_warn(ibdev, "warning: event on port %d\n", port);
Maor Gottlieb03404e82017-05-30 10:29:13 +03004059 goto out;
Eli Cohena0c84c32013-09-11 16:35:27 +03004060 }
4061
Eli Cohene126ba92013-07-07 17:25:49 +03004062 if (ibdev->ib_active)
4063 ib_dispatch_event(&ibev);
Eli Cohendbaaff22016-10-27 16:36:44 +03004064
4065 if (fatal)
4066 ibdev->ib_active = false;
Maor Gottlieb03404e82017-05-30 10:29:13 +03004067out:
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02004068 kfree(work);
4069}
4070
4071static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
4072 enum mlx5_dev_event event, unsigned long param)
4073{
4074 struct mlx5_ib_event_work *work;
4075
4076 work = kmalloc(sizeof(*work), GFP_ATOMIC);
Leon Romanovsky10bea9c2018-01-19 13:07:11 +02004077 if (!work)
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02004078 return;
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02004079
Leon Romanovsky10bea9c2018-01-19 13:07:11 +02004080 INIT_WORK(&work->work, mlx5_ib_handle_event);
4081 work->dev = dev;
4082 work->param = param;
4083 work->context = context;
4084 work->event = event;
4085
4086 queue_work(mlx5_ib_event_wq, &work->work);
Eli Cohene126ba92013-07-07 17:25:49 +03004087}
4088
Maor Gottliebc43f1112017-01-18 14:10:33 +02004089static int set_has_smi_cap(struct mlx5_ib_dev *dev)
4090{
4091 struct mlx5_hca_vport_context vport_ctx;
4092 int err;
4093 int port;
4094
Daniel Jurgens508562d2018-01-04 17:25:34 +02004095 for (port = 1; port <= dev->num_ports; port++) {
Maor Gottliebc43f1112017-01-18 14:10:33 +02004096 dev->mdev->port_caps[port - 1].has_smi = false;
4097 if (MLX5_CAP_GEN(dev->mdev, port_type) ==
4098 MLX5_CAP_PORT_TYPE_IB) {
4099 if (MLX5_CAP_GEN(dev->mdev, ib_virt)) {
4100 err = mlx5_query_hca_vport_context(dev->mdev, 0,
4101 port, 0,
4102 &vport_ctx);
4103 if (err) {
4104 mlx5_ib_err(dev, "query_hca_vport_context for port=%d failed %d\n",
4105 port, err);
4106 return err;
4107 }
4108 dev->mdev->port_caps[port - 1].has_smi =
4109 vport_ctx.has_smi;
4110 } else {
4111 dev->mdev->port_caps[port - 1].has_smi = true;
4112 }
4113 }
4114 }
4115 return 0;
4116}
4117
Eli Cohene126ba92013-07-07 17:25:49 +03004118static void get_ext_port_caps(struct mlx5_ib_dev *dev)
4119{
4120 int port;
4121
Daniel Jurgens508562d2018-01-04 17:25:34 +02004122 for (port = 1; port <= dev->num_ports; port++)
Eli Cohene126ba92013-07-07 17:25:49 +03004123 mlx5_query_ext_port_caps(dev, port);
4124}
4125
Daniel Jurgens32f69e42018-01-04 17:25:36 +02004126static int get_port_caps(struct mlx5_ib_dev *dev, u8 port)
Eli Cohene126ba92013-07-07 17:25:49 +03004127{
4128 struct ib_device_attr *dprops = NULL;
4129 struct ib_port_attr *pprops = NULL;
Dan Carpenterf614fc12015-01-12 11:56:58 +03004130 int err = -ENOMEM;
Matan Barak2528e332015-06-11 16:35:25 +03004131 struct ib_udata uhw = {.inlen = 0, .outlen = 0};
Eli Cohene126ba92013-07-07 17:25:49 +03004132
4133 pprops = kmalloc(sizeof(*pprops), GFP_KERNEL);
4134 if (!pprops)
4135 goto out;
4136
4137 dprops = kmalloc(sizeof(*dprops), GFP_KERNEL);
4138 if (!dprops)
4139 goto out;
4140
Maor Gottliebc43f1112017-01-18 14:10:33 +02004141 err = set_has_smi_cap(dev);
4142 if (err)
4143 goto out;
4144
Matan Barak2528e332015-06-11 16:35:25 +03004145 err = mlx5_ib_query_device(&dev->ib_dev, dprops, &uhw);
Eli Cohene126ba92013-07-07 17:25:49 +03004146 if (err) {
4147 mlx5_ib_warn(dev, "query_device failed %d\n", err);
4148 goto out;
4149 }
4150
Daniel Jurgens32f69e42018-01-04 17:25:36 +02004151 memset(pprops, 0, sizeof(*pprops));
4152 err = mlx5_ib_query_port(&dev->ib_dev, port, pprops);
4153 if (err) {
4154 mlx5_ib_warn(dev, "query_port %d failed %d\n",
4155 port, err);
4156 goto out;
Eli Cohene126ba92013-07-07 17:25:49 +03004157 }
4158
Daniel Jurgens32f69e42018-01-04 17:25:36 +02004159 dev->mdev->port_caps[port - 1].pkey_table_len =
4160 dprops->max_pkeys;
4161 dev->mdev->port_caps[port - 1].gid_table_len =
4162 pprops->gid_tbl_len;
4163 mlx5_ib_dbg(dev, "port %d: pkey_table_len %d, gid_table_len %d\n",
4164 port, dprops->max_pkeys, pprops->gid_tbl_len);
4165
Eli Cohene126ba92013-07-07 17:25:49 +03004166out:
4167 kfree(pprops);
4168 kfree(dprops);
4169
4170 return err;
4171}
4172
4173static void destroy_umrc_res(struct mlx5_ib_dev *dev)
4174{
4175 int err;
4176
4177 err = mlx5_mr_cache_cleanup(dev);
4178 if (err)
4179 mlx5_ib_warn(dev, "mr cache cleanup failed\n");
4180
Mark Bloch32927e22018-03-20 15:45:37 +02004181 if (dev->umrc.qp)
4182 mlx5_ib_destroy_qp(dev->umrc.qp);
4183 if (dev->umrc.cq)
4184 ib_free_cq(dev->umrc.cq);
4185 if (dev->umrc.pd)
4186 ib_dealloc_pd(dev->umrc.pd);
Eli Cohene126ba92013-07-07 17:25:49 +03004187}
4188
4189enum {
4190 MAX_UMR_WR = 128,
4191};
4192
4193static int create_umr_res(struct mlx5_ib_dev *dev)
4194{
4195 struct ib_qp_init_attr *init_attr = NULL;
4196 struct ib_qp_attr *attr = NULL;
4197 struct ib_pd *pd;
4198 struct ib_cq *cq;
4199 struct ib_qp *qp;
Eli Cohene126ba92013-07-07 17:25:49 +03004200 int ret;
4201
4202 attr = kzalloc(sizeof(*attr), GFP_KERNEL);
4203 init_attr = kzalloc(sizeof(*init_attr), GFP_KERNEL);
4204 if (!attr || !init_attr) {
4205 ret = -ENOMEM;
4206 goto error_0;
4207 }
4208
Christoph Hellwiged082d32016-09-05 12:56:17 +02004209 pd = ib_alloc_pd(&dev->ib_dev, 0);
Eli Cohene126ba92013-07-07 17:25:49 +03004210 if (IS_ERR(pd)) {
4211 mlx5_ib_dbg(dev, "Couldn't create PD for sync UMR QP\n");
4212 ret = PTR_ERR(pd);
4213 goto error_0;
4214 }
4215
Christoph Hellwigadd08d72016-03-03 09:38:22 +01004216 cq = ib_alloc_cq(&dev->ib_dev, NULL, 128, 0, IB_POLL_SOFTIRQ);
Eli Cohene126ba92013-07-07 17:25:49 +03004217 if (IS_ERR(cq)) {
4218 mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n");
4219 ret = PTR_ERR(cq);
4220 goto error_2;
4221 }
Eli Cohene126ba92013-07-07 17:25:49 +03004222
4223 init_attr->send_cq = cq;
4224 init_attr->recv_cq = cq;
4225 init_attr->sq_sig_type = IB_SIGNAL_ALL_WR;
4226 init_attr->cap.max_send_wr = MAX_UMR_WR;
4227 init_attr->cap.max_send_sge = 1;
4228 init_attr->qp_type = MLX5_IB_QPT_REG_UMR;
4229 init_attr->port_num = 1;
4230 qp = mlx5_ib_create_qp(pd, init_attr, NULL);
4231 if (IS_ERR(qp)) {
4232 mlx5_ib_dbg(dev, "Couldn't create sync UMR QP\n");
4233 ret = PTR_ERR(qp);
4234 goto error_3;
4235 }
4236 qp->device = &dev->ib_dev;
4237 qp->real_qp = qp;
4238 qp->uobject = NULL;
4239 qp->qp_type = MLX5_IB_QPT_REG_UMR;
Majd Dibbiny31fde032017-10-30 14:23:13 +02004240 qp->send_cq = init_attr->send_cq;
4241 qp->recv_cq = init_attr->recv_cq;
Eli Cohene126ba92013-07-07 17:25:49 +03004242
4243 attr->qp_state = IB_QPS_INIT;
4244 attr->port_num = 1;
4245 ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE | IB_QP_PKEY_INDEX |
4246 IB_QP_PORT, NULL);
4247 if (ret) {
4248 mlx5_ib_dbg(dev, "Couldn't modify UMR QP\n");
4249 goto error_4;
4250 }
4251
4252 memset(attr, 0, sizeof(*attr));
4253 attr->qp_state = IB_QPS_RTR;
4254 attr->path_mtu = IB_MTU_256;
4255
4256 ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL);
4257 if (ret) {
4258 mlx5_ib_dbg(dev, "Couldn't modify umr QP to rtr\n");
4259 goto error_4;
4260 }
4261
4262 memset(attr, 0, sizeof(*attr));
4263 attr->qp_state = IB_QPS_RTS;
4264 ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL);
4265 if (ret) {
4266 mlx5_ib_dbg(dev, "Couldn't modify umr QP to rts\n");
4267 goto error_4;
4268 }
4269
4270 dev->umrc.qp = qp;
4271 dev->umrc.cq = cq;
Eli Cohene126ba92013-07-07 17:25:49 +03004272 dev->umrc.pd = pd;
4273
4274 sema_init(&dev->umrc.sem, MAX_UMR_WR);
4275 ret = mlx5_mr_cache_init(dev);
4276 if (ret) {
4277 mlx5_ib_warn(dev, "mr cache init failed %d\n", ret);
4278 goto error_4;
4279 }
4280
4281 kfree(attr);
4282 kfree(init_attr);
4283
4284 return 0;
4285
4286error_4:
4287 mlx5_ib_destroy_qp(qp);
Mark Bloch32927e22018-03-20 15:45:37 +02004288 dev->umrc.qp = NULL;
Eli Cohene126ba92013-07-07 17:25:49 +03004289
4290error_3:
Christoph Hellwigadd08d72016-03-03 09:38:22 +01004291 ib_free_cq(cq);
Mark Bloch32927e22018-03-20 15:45:37 +02004292 dev->umrc.cq = NULL;
Eli Cohene126ba92013-07-07 17:25:49 +03004293
4294error_2:
Eli Cohene126ba92013-07-07 17:25:49 +03004295 ib_dealloc_pd(pd);
Mark Bloch32927e22018-03-20 15:45:37 +02004296 dev->umrc.pd = NULL;
Eli Cohene126ba92013-07-07 17:25:49 +03004297
4298error_0:
4299 kfree(attr);
4300 kfree(init_attr);
4301 return ret;
4302}
4303
Max Gurtovoy6e8484c2017-05-28 10:53:11 +03004304static u8 mlx5_get_umr_fence(u8 umr_fence_cap)
4305{
4306 switch (umr_fence_cap) {
4307 case MLX5_CAP_UMR_FENCE_NONE:
4308 return MLX5_FENCE_MODE_NONE;
4309 case MLX5_CAP_UMR_FENCE_SMALL:
4310 return MLX5_FENCE_MODE_INITIATOR_SMALL;
4311 default:
4312 return MLX5_FENCE_MODE_STRONG_ORDERING;
4313 }
4314}
4315
Eli Cohene126ba92013-07-07 17:25:49 +03004316static int create_dev_resources(struct mlx5_ib_resources *devr)
4317{
4318 struct ib_srq_init_attr attr;
4319 struct mlx5_ib_dev *dev;
Matan Barakbcf4c1e2015-06-11 16:35:20 +03004320 struct ib_cq_init_attr cq_attr = {.cqe = 1};
Haggai Eran7722f472016-02-29 15:45:07 +02004321 int port;
Eli Cohene126ba92013-07-07 17:25:49 +03004322 int ret = 0;
4323
4324 dev = container_of(devr, struct mlx5_ib_dev, devr);
4325
Haggai Erand16e91d2016-02-29 15:45:05 +02004326 mutex_init(&devr->mutex);
4327
Eli Cohene126ba92013-07-07 17:25:49 +03004328 devr->p0 = mlx5_ib_alloc_pd(&dev->ib_dev, NULL, NULL);
4329 if (IS_ERR(devr->p0)) {
4330 ret = PTR_ERR(devr->p0);
4331 goto error0;
4332 }
4333 devr->p0->device = &dev->ib_dev;
4334 devr->p0->uobject = NULL;
4335 atomic_set(&devr->p0->usecnt, 0);
4336
Matan Barakbcf4c1e2015-06-11 16:35:20 +03004337 devr->c0 = mlx5_ib_create_cq(&dev->ib_dev, &cq_attr, NULL, NULL);
Eli Cohene126ba92013-07-07 17:25:49 +03004338 if (IS_ERR(devr->c0)) {
4339 ret = PTR_ERR(devr->c0);
4340 goto error1;
4341 }
4342 devr->c0->device = &dev->ib_dev;
4343 devr->c0->uobject = NULL;
4344 devr->c0->comp_handler = NULL;
4345 devr->c0->event_handler = NULL;
4346 devr->c0->cq_context = NULL;
4347 atomic_set(&devr->c0->usecnt, 0);
4348
4349 devr->x0 = mlx5_ib_alloc_xrcd(&dev->ib_dev, NULL, NULL);
4350 if (IS_ERR(devr->x0)) {
4351 ret = PTR_ERR(devr->x0);
4352 goto error2;
4353 }
4354 devr->x0->device = &dev->ib_dev;
4355 devr->x0->inode = NULL;
4356 atomic_set(&devr->x0->usecnt, 0);
4357 mutex_init(&devr->x0->tgt_qp_mutex);
4358 INIT_LIST_HEAD(&devr->x0->tgt_qp_list);
4359
4360 devr->x1 = mlx5_ib_alloc_xrcd(&dev->ib_dev, NULL, NULL);
4361 if (IS_ERR(devr->x1)) {
4362 ret = PTR_ERR(devr->x1);
4363 goto error3;
4364 }
4365 devr->x1->device = &dev->ib_dev;
4366 devr->x1->inode = NULL;
4367 atomic_set(&devr->x1->usecnt, 0);
4368 mutex_init(&devr->x1->tgt_qp_mutex);
4369 INIT_LIST_HEAD(&devr->x1->tgt_qp_list);
4370
4371 memset(&attr, 0, sizeof(attr));
4372 attr.attr.max_sge = 1;
4373 attr.attr.max_wr = 1;
4374 attr.srq_type = IB_SRQT_XRC;
Artemy Kovalyov1a56ff62017-08-17 15:52:04 +03004375 attr.ext.cq = devr->c0;
Eli Cohene126ba92013-07-07 17:25:49 +03004376 attr.ext.xrc.xrcd = devr->x0;
4377
4378 devr->s0 = mlx5_ib_create_srq(devr->p0, &attr, NULL);
4379 if (IS_ERR(devr->s0)) {
4380 ret = PTR_ERR(devr->s0);
4381 goto error4;
4382 }
4383 devr->s0->device = &dev->ib_dev;
4384 devr->s0->pd = devr->p0;
4385 devr->s0->uobject = NULL;
4386 devr->s0->event_handler = NULL;
4387 devr->s0->srq_context = NULL;
4388 devr->s0->srq_type = IB_SRQT_XRC;
4389 devr->s0->ext.xrc.xrcd = devr->x0;
Artemy Kovalyov1a56ff62017-08-17 15:52:04 +03004390 devr->s0->ext.cq = devr->c0;
Eli Cohene126ba92013-07-07 17:25:49 +03004391 atomic_inc(&devr->s0->ext.xrc.xrcd->usecnt);
Artemy Kovalyov1a56ff62017-08-17 15:52:04 +03004392 atomic_inc(&devr->s0->ext.cq->usecnt);
Eli Cohene126ba92013-07-07 17:25:49 +03004393 atomic_inc(&devr->p0->usecnt);
4394 atomic_set(&devr->s0->usecnt, 0);
4395
Haggai Abramonvsky4aa17b22015-06-04 19:30:48 +03004396 memset(&attr, 0, sizeof(attr));
4397 attr.attr.max_sge = 1;
4398 attr.attr.max_wr = 1;
4399 attr.srq_type = IB_SRQT_BASIC;
4400 devr->s1 = mlx5_ib_create_srq(devr->p0, &attr, NULL);
4401 if (IS_ERR(devr->s1)) {
4402 ret = PTR_ERR(devr->s1);
4403 goto error5;
4404 }
4405 devr->s1->device = &dev->ib_dev;
4406 devr->s1->pd = devr->p0;
4407 devr->s1->uobject = NULL;
4408 devr->s1->event_handler = NULL;
4409 devr->s1->srq_context = NULL;
4410 devr->s1->srq_type = IB_SRQT_BASIC;
Artemy Kovalyov1a56ff62017-08-17 15:52:04 +03004411 devr->s1->ext.cq = devr->c0;
Haggai Abramonvsky4aa17b22015-06-04 19:30:48 +03004412 atomic_inc(&devr->p0->usecnt);
Artemy Kovalyov1a56ff62017-08-17 15:52:04 +03004413 atomic_set(&devr->s1->usecnt, 0);
Haggai Abramonvsky4aa17b22015-06-04 19:30:48 +03004414
Haggai Eran7722f472016-02-29 15:45:07 +02004415 for (port = 0; port < ARRAY_SIZE(devr->ports); ++port) {
4416 INIT_WORK(&devr->ports[port].pkey_change_work,
4417 pkey_change_handler);
4418 devr->ports[port].devr = devr;
4419 }
4420
Eli Cohene126ba92013-07-07 17:25:49 +03004421 return 0;
4422
Haggai Abramonvsky4aa17b22015-06-04 19:30:48 +03004423error5:
4424 mlx5_ib_destroy_srq(devr->s0);
Eli Cohene126ba92013-07-07 17:25:49 +03004425error4:
4426 mlx5_ib_dealloc_xrcd(devr->x1);
4427error3:
4428 mlx5_ib_dealloc_xrcd(devr->x0);
4429error2:
4430 mlx5_ib_destroy_cq(devr->c0);
4431error1:
4432 mlx5_ib_dealloc_pd(devr->p0);
4433error0:
4434 return ret;
4435}
4436
4437static void destroy_dev_resources(struct mlx5_ib_resources *devr)
4438{
Haggai Eran7722f472016-02-29 15:45:07 +02004439 struct mlx5_ib_dev *dev =
4440 container_of(devr, struct mlx5_ib_dev, devr);
4441 int port;
4442
Haggai Abramonvsky4aa17b22015-06-04 19:30:48 +03004443 mlx5_ib_destroy_srq(devr->s1);
Eli Cohene126ba92013-07-07 17:25:49 +03004444 mlx5_ib_destroy_srq(devr->s0);
4445 mlx5_ib_dealloc_xrcd(devr->x0);
4446 mlx5_ib_dealloc_xrcd(devr->x1);
4447 mlx5_ib_destroy_cq(devr->c0);
4448 mlx5_ib_dealloc_pd(devr->p0);
Haggai Eran7722f472016-02-29 15:45:07 +02004449
4450 /* Make sure no change P_Key work items are still executing */
4451 for (port = 0; port < dev->num_ports; ++port)
4452 cancel_work_sync(&devr->ports[port].pkey_change_work);
Eli Cohene126ba92013-07-07 17:25:49 +03004453}
4454
Achiad Shochate53505a2015-12-23 18:47:25 +02004455static u32 get_core_cap_flags(struct ib_device *ibdev)
4456{
4457 struct mlx5_ib_dev *dev = to_mdev(ibdev);
4458 enum rdma_link_layer ll = mlx5_ib_port_link_layer(ibdev, 1);
4459 u8 l3_type_cap = MLX5_CAP_ROCE(dev->mdev, l3_type);
4460 u8 roce_version_cap = MLX5_CAP_ROCE(dev->mdev, roce_version);
Daniel Jurgens85c7c012018-01-04 17:25:43 +02004461 bool raw_support = !mlx5_core_mp_enabled(dev->mdev);
Achiad Shochate53505a2015-12-23 18:47:25 +02004462 u32 ret = 0;
4463
4464 if (ll == IB_LINK_LAYER_INFINIBAND)
4465 return RDMA_CORE_PORT_IBA_IB;
4466
Daniel Jurgens85c7c012018-01-04 17:25:43 +02004467 if (raw_support)
4468 ret = RDMA_CORE_PORT_RAW_PACKET;
Or Gerlitz72cd5712017-01-24 13:02:36 +02004469
Achiad Shochate53505a2015-12-23 18:47:25 +02004470 if (!(l3_type_cap & MLX5_ROCE_L3_TYPE_IPV4_CAP))
Or Gerlitz72cd5712017-01-24 13:02:36 +02004471 return ret;
Achiad Shochate53505a2015-12-23 18:47:25 +02004472
4473 if (!(l3_type_cap & MLX5_ROCE_L3_TYPE_IPV6_CAP))
Or Gerlitz72cd5712017-01-24 13:02:36 +02004474 return ret;
Achiad Shochate53505a2015-12-23 18:47:25 +02004475
4476 if (roce_version_cap & MLX5_ROCE_VERSION_1_CAP)
4477 ret |= RDMA_CORE_PORT_IBA_ROCE;
4478
4479 if (roce_version_cap & MLX5_ROCE_VERSION_2_CAP)
4480 ret |= RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;
4481
4482 return ret;
4483}
4484
Ira Weiny77386132015-05-13 20:02:58 -04004485static int mlx5_port_immutable(struct ib_device *ibdev, u8 port_num,
4486 struct ib_port_immutable *immutable)
4487{
4488 struct ib_port_attr attr;
Or Gerlitzca5b91d2016-11-27 16:51:36 +02004489 struct mlx5_ib_dev *dev = to_mdev(ibdev);
4490 enum rdma_link_layer ll = mlx5_ib_port_link_layer(ibdev, port_num);
Ira Weiny77386132015-05-13 20:02:58 -04004491 int err;
4492
Or Gerlitzc4550c62017-01-24 13:02:39 +02004493 immutable->core_cap_flags = get_core_cap_flags(ibdev);
4494
4495 err = ib_query_port(ibdev, port_num, &attr);
Ira Weiny77386132015-05-13 20:02:58 -04004496 if (err)
4497 return err;
4498
4499 immutable->pkey_tbl_len = attr.pkey_tbl_len;
4500 immutable->gid_tbl_len = attr.gid_tbl_len;
Achiad Shochate53505a2015-12-23 18:47:25 +02004501 immutable->core_cap_flags = get_core_cap_flags(ibdev);
Or Gerlitzca5b91d2016-11-27 16:51:36 +02004502 if ((ll == IB_LINK_LAYER_INFINIBAND) || MLX5_CAP_GEN(dev->mdev, roce))
4503 immutable->max_mad_size = IB_MGMT_MAD_SIZE;
Ira Weiny77386132015-05-13 20:02:58 -04004504
4505 return 0;
4506}
4507
Mark Bloch8e6efa32017-11-06 12:22:13 +00004508static int mlx5_port_rep_immutable(struct ib_device *ibdev, u8 port_num,
4509 struct ib_port_immutable *immutable)
4510{
4511 struct ib_port_attr attr;
4512 int err;
4513
4514 immutable->core_cap_flags = RDMA_CORE_PORT_RAW_PACKET;
4515
4516 err = ib_query_port(ibdev, port_num, &attr);
4517 if (err)
4518 return err;
4519
4520 immutable->pkey_tbl_len = attr.pkey_tbl_len;
4521 immutable->gid_tbl_len = attr.gid_tbl_len;
4522 immutable->core_cap_flags = RDMA_CORE_PORT_RAW_PACKET;
4523
4524 return 0;
4525}
4526
Leon Romanovsky9abb0d12017-06-27 16:49:53 +03004527static void get_dev_fw_str(struct ib_device *ibdev, char *str)
Ira Weinyc7342822016-06-15 02:22:01 -04004528{
4529 struct mlx5_ib_dev *dev =
4530 container_of(ibdev, struct mlx5_ib_dev, ib_dev);
Leon Romanovsky9abb0d12017-06-27 16:49:53 +03004531 snprintf(str, IB_FW_VERSION_NAME_MAX, "%d.%d.%04d",
4532 fw_rev_maj(dev->mdev), fw_rev_min(dev->mdev),
4533 fw_rev_sub(dev->mdev));
Ira Weinyc7342822016-06-15 02:22:01 -04004534}
4535
Or Gerlitz45f95ac2016-11-27 16:51:35 +02004536static int mlx5_eth_lag_init(struct mlx5_ib_dev *dev)
Aviv Heller9ef9c642016-09-18 20:48:01 +03004537{
4538 struct mlx5_core_dev *mdev = dev->mdev;
4539 struct mlx5_flow_namespace *ns = mlx5_get_flow_namespace(mdev,
4540 MLX5_FLOW_NAMESPACE_LAG);
4541 struct mlx5_flow_table *ft;
4542 int err;
4543
4544 if (!ns || !mlx5_lag_is_active(mdev))
4545 return 0;
4546
4547 err = mlx5_cmd_create_vport_lag(mdev);
4548 if (err)
4549 return err;
4550
4551 ft = mlx5_create_lag_demux_flow_table(ns, 0, 0);
4552 if (IS_ERR(ft)) {
4553 err = PTR_ERR(ft);
4554 goto err_destroy_vport_lag;
4555 }
4556
Mark Bloch9a4ca382018-01-16 14:42:35 +00004557 dev->flow_db->lag_demux_ft = ft;
Aviv Heller9ef9c642016-09-18 20:48:01 +03004558 return 0;
4559
4560err_destroy_vport_lag:
4561 mlx5_cmd_destroy_vport_lag(mdev);
4562 return err;
4563}
4564
Or Gerlitz45f95ac2016-11-27 16:51:35 +02004565static void mlx5_eth_lag_cleanup(struct mlx5_ib_dev *dev)
Aviv Heller9ef9c642016-09-18 20:48:01 +03004566{
4567 struct mlx5_core_dev *mdev = dev->mdev;
4568
Mark Bloch9a4ca382018-01-16 14:42:35 +00004569 if (dev->flow_db->lag_demux_ft) {
4570 mlx5_destroy_flow_table(dev->flow_db->lag_demux_ft);
4571 dev->flow_db->lag_demux_ft = NULL;
Aviv Heller9ef9c642016-09-18 20:48:01 +03004572
4573 mlx5_cmd_destroy_vport_lag(mdev);
4574 }
4575}
4576
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +02004577static int mlx5_add_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num)
Achiad Shochatfc24fc52015-12-23 18:47:17 +02004578{
Achiad Shochate53505a2015-12-23 18:47:25 +02004579 int err;
4580
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +02004581 dev->roce[port_num].nb.notifier_call = mlx5_netdev_event;
4582 err = register_netdevice_notifier(&dev->roce[port_num].nb);
Aviv Heller5ec8c832016-09-18 20:48:00 +03004583 if (err) {
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +02004584 dev->roce[port_num].nb.notifier_call = NULL;
Achiad Shochate53505a2015-12-23 18:47:25 +02004585 return err;
Aviv Heller5ec8c832016-09-18 20:48:00 +03004586 }
Achiad Shochate53505a2015-12-23 18:47:25 +02004587
Or Gerlitzd012f5d2016-11-27 16:51:34 +02004588 return 0;
4589}
Achiad Shochate53505a2015-12-23 18:47:25 +02004590
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +02004591static void mlx5_remove_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num)
Eli Cohene126ba92013-07-07 17:25:49 +03004592{
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +02004593 if (dev->roce[port_num].nb.notifier_call) {
4594 unregister_netdevice_notifier(&dev->roce[port_num].nb);
4595 dev->roce[port_num].nb.notifier_call = NULL;
Eli Cohene126ba92013-07-07 17:25:49 +03004596 }
4597}
4598
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +02004599static int mlx5_enable_eth(struct mlx5_ib_dev *dev, u8 port_num)
Eli Cohene126ba92013-07-07 17:25:49 +03004600{
Eli Cohene126ba92013-07-07 17:25:49 +03004601 int err;
4602
Or Gerlitzca5b91d2016-11-27 16:51:36 +02004603 if (MLX5_CAP_GEN(dev->mdev, roce)) {
4604 err = mlx5_nic_vport_enable_roce(dev->mdev);
4605 if (err)
Mark Bloch8e6efa32017-11-06 12:22:13 +00004606 return err;
Or Gerlitzca5b91d2016-11-27 16:51:36 +02004607 }
Achiad Shochate53505a2015-12-23 18:47:25 +02004608
Or Gerlitz45f95ac2016-11-27 16:51:35 +02004609 err = mlx5_eth_lag_init(dev);
Aviv Heller9ef9c642016-09-18 20:48:01 +03004610 if (err)
4611 goto err_disable_roce;
4612
Achiad Shochate53505a2015-12-23 18:47:25 +02004613 return 0;
4614
Aviv Heller9ef9c642016-09-18 20:48:01 +03004615err_disable_roce:
Or Gerlitzca5b91d2016-11-27 16:51:36 +02004616 if (MLX5_CAP_GEN(dev->mdev, roce))
4617 mlx5_nic_vport_disable_roce(dev->mdev);
Aviv Heller9ef9c642016-09-18 20:48:01 +03004618
Achiad Shochate53505a2015-12-23 18:47:25 +02004619 return err;
Achiad Shochatfc24fc52015-12-23 18:47:17 +02004620}
4621
Or Gerlitz45f95ac2016-11-27 16:51:35 +02004622static void mlx5_disable_eth(struct mlx5_ib_dev *dev)
Achiad Shochatfc24fc52015-12-23 18:47:17 +02004623{
Or Gerlitz45f95ac2016-11-27 16:51:35 +02004624 mlx5_eth_lag_cleanup(dev);
Or Gerlitzca5b91d2016-11-27 16:51:36 +02004625 if (MLX5_CAP_GEN(dev->mdev, roce))
4626 mlx5_nic_vport_disable_roce(dev->mdev);
Achiad Shochatfc24fc52015-12-23 18:47:17 +02004627}
4628
Parav Pandite1f24a72017-04-16 07:29:29 +03004629struct mlx5_ib_counter {
Kamal Heib7c16f472017-01-18 15:25:09 +02004630 const char *name;
4631 size_t offset;
4632};
4633
4634#define INIT_Q_COUNTER(_name) \
4635 { .name = #_name, .offset = MLX5_BYTE_OFF(query_q_counter_out, _name)}
4636
Parav Pandite1f24a72017-04-16 07:29:29 +03004637static const struct mlx5_ib_counter basic_q_cnts[] = {
Kamal Heib7c16f472017-01-18 15:25:09 +02004638 INIT_Q_COUNTER(rx_write_requests),
4639 INIT_Q_COUNTER(rx_read_requests),
4640 INIT_Q_COUNTER(rx_atomic_requests),
4641 INIT_Q_COUNTER(out_of_buffer),
4642};
4643
Parav Pandite1f24a72017-04-16 07:29:29 +03004644static const struct mlx5_ib_counter out_of_seq_q_cnts[] = {
Kamal Heib7c16f472017-01-18 15:25:09 +02004645 INIT_Q_COUNTER(out_of_sequence),
4646};
4647
Parav Pandite1f24a72017-04-16 07:29:29 +03004648static const struct mlx5_ib_counter retrans_q_cnts[] = {
Kamal Heib7c16f472017-01-18 15:25:09 +02004649 INIT_Q_COUNTER(duplicate_request),
4650 INIT_Q_COUNTER(rnr_nak_retry_err),
4651 INIT_Q_COUNTER(packet_seq_err),
4652 INIT_Q_COUNTER(implied_nak_seq_err),
4653 INIT_Q_COUNTER(local_ack_timeout_err),
4654};
4655
Parav Pandite1f24a72017-04-16 07:29:29 +03004656#define INIT_CONG_COUNTER(_name) \
4657 { .name = #_name, .offset = \
4658 MLX5_BYTE_OFF(query_cong_statistics_out, _name ## _high)}
4659
4660static const struct mlx5_ib_counter cong_cnts[] = {
4661 INIT_CONG_COUNTER(rp_cnp_ignored),
4662 INIT_CONG_COUNTER(rp_cnp_handled),
4663 INIT_CONG_COUNTER(np_ecn_marked_roce_packets),
4664 INIT_CONG_COUNTER(np_cnp_sent),
4665};
4666
Parav Pandit58dcb602017-06-19 07:19:37 +03004667static const struct mlx5_ib_counter extended_err_cnts[] = {
4668 INIT_Q_COUNTER(resp_local_length_error),
4669 INIT_Q_COUNTER(resp_cqe_error),
4670 INIT_Q_COUNTER(req_cqe_error),
4671 INIT_Q_COUNTER(req_remote_invalid_request),
4672 INIT_Q_COUNTER(req_remote_access_errors),
4673 INIT_Q_COUNTER(resp_remote_access_errors),
4674 INIT_Q_COUNTER(resp_cqe_flush_error),
4675 INIT_Q_COUNTER(req_cqe_flush_error),
4676};
4677
Parav Pandite1f24a72017-04-16 07:29:29 +03004678static void mlx5_ib_dealloc_counters(struct mlx5_ib_dev *dev)
Mark Bloch0837e862016-06-17 15:10:55 +03004679{
Daniel Jurgensaac44922018-01-04 17:25:40 +02004680 int i;
Mark Bloch0837e862016-06-17 15:10:55 +03004681
Kamal Heib7c16f472017-01-18 15:25:09 +02004682 for (i = 0; i < dev->num_ports; i++) {
Daniel Jurgensaac44922018-01-04 17:25:40 +02004683 if (dev->port[i].cnts.set_id)
4684 mlx5_core_dealloc_q_counter(dev->mdev,
4685 dev->port[i].cnts.set_id);
Parav Pandite1f24a72017-04-16 07:29:29 +03004686 kfree(dev->port[i].cnts.names);
4687 kfree(dev->port[i].cnts.offsets);
Kamal Heib7c16f472017-01-18 15:25:09 +02004688 }
4689}
4690
Parav Pandite1f24a72017-04-16 07:29:29 +03004691static int __mlx5_ib_alloc_counters(struct mlx5_ib_dev *dev,
4692 struct mlx5_ib_counters *cnts)
Kamal Heib7c16f472017-01-18 15:25:09 +02004693{
4694 u32 num_counters;
4695
4696 num_counters = ARRAY_SIZE(basic_q_cnts);
4697
4698 if (MLX5_CAP_GEN(dev->mdev, out_of_seq_cnt))
4699 num_counters += ARRAY_SIZE(out_of_seq_q_cnts);
4700
4701 if (MLX5_CAP_GEN(dev->mdev, retransmission_q_counters))
4702 num_counters += ARRAY_SIZE(retrans_q_cnts);
Parav Pandit58dcb602017-06-19 07:19:37 +03004703
4704 if (MLX5_CAP_GEN(dev->mdev, enhanced_error_q_counters))
4705 num_counters += ARRAY_SIZE(extended_err_cnts);
4706
Parav Pandite1f24a72017-04-16 07:29:29 +03004707 cnts->num_q_counters = num_counters;
Kamal Heib7c16f472017-01-18 15:25:09 +02004708
Parav Pandite1f24a72017-04-16 07:29:29 +03004709 if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) {
4710 cnts->num_cong_counters = ARRAY_SIZE(cong_cnts);
4711 num_counters += ARRAY_SIZE(cong_cnts);
4712 }
4713
4714 cnts->names = kcalloc(num_counters, sizeof(cnts->names), GFP_KERNEL);
4715 if (!cnts->names)
Kamal Heib7c16f472017-01-18 15:25:09 +02004716 return -ENOMEM;
4717
Parav Pandite1f24a72017-04-16 07:29:29 +03004718 cnts->offsets = kcalloc(num_counters,
4719 sizeof(cnts->offsets), GFP_KERNEL);
4720 if (!cnts->offsets)
Kamal Heib7c16f472017-01-18 15:25:09 +02004721 goto err_names;
4722
Kamal Heib7c16f472017-01-18 15:25:09 +02004723 return 0;
4724
4725err_names:
Parav Pandite1f24a72017-04-16 07:29:29 +03004726 kfree(cnts->names);
Daniel Jurgensaac44922018-01-04 17:25:40 +02004727 cnts->names = NULL;
Kamal Heib7c16f472017-01-18 15:25:09 +02004728 return -ENOMEM;
4729}
4730
Parav Pandite1f24a72017-04-16 07:29:29 +03004731static void mlx5_ib_fill_counters(struct mlx5_ib_dev *dev,
4732 const char **names,
4733 size_t *offsets)
Kamal Heib7c16f472017-01-18 15:25:09 +02004734{
4735 int i;
4736 int j = 0;
4737
4738 for (i = 0; i < ARRAY_SIZE(basic_q_cnts); i++, j++) {
4739 names[j] = basic_q_cnts[i].name;
4740 offsets[j] = basic_q_cnts[i].offset;
4741 }
4742
4743 if (MLX5_CAP_GEN(dev->mdev, out_of_seq_cnt)) {
4744 for (i = 0; i < ARRAY_SIZE(out_of_seq_q_cnts); i++, j++) {
4745 names[j] = out_of_seq_q_cnts[i].name;
4746 offsets[j] = out_of_seq_q_cnts[i].offset;
4747 }
4748 }
4749
4750 if (MLX5_CAP_GEN(dev->mdev, retransmission_q_counters)) {
4751 for (i = 0; i < ARRAY_SIZE(retrans_q_cnts); i++, j++) {
4752 names[j] = retrans_q_cnts[i].name;
4753 offsets[j] = retrans_q_cnts[i].offset;
4754 }
4755 }
Parav Pandite1f24a72017-04-16 07:29:29 +03004756
Parav Pandit58dcb602017-06-19 07:19:37 +03004757 if (MLX5_CAP_GEN(dev->mdev, enhanced_error_q_counters)) {
4758 for (i = 0; i < ARRAY_SIZE(extended_err_cnts); i++, j++) {
4759 names[j] = extended_err_cnts[i].name;
4760 offsets[j] = extended_err_cnts[i].offset;
4761 }
4762 }
4763
Parav Pandite1f24a72017-04-16 07:29:29 +03004764 if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) {
4765 for (i = 0; i < ARRAY_SIZE(cong_cnts); i++, j++) {
4766 names[j] = cong_cnts[i].name;
4767 offsets[j] = cong_cnts[i].offset;
4768 }
4769 }
Mark Bloch0837e862016-06-17 15:10:55 +03004770}
4771
Parav Pandite1f24a72017-04-16 07:29:29 +03004772static int mlx5_ib_alloc_counters(struct mlx5_ib_dev *dev)
Mark Bloch0837e862016-06-17 15:10:55 +03004773{
Daniel Jurgensaac44922018-01-04 17:25:40 +02004774 int err = 0;
Mark Bloch0837e862016-06-17 15:10:55 +03004775 int i;
Mark Bloch0837e862016-06-17 15:10:55 +03004776
4777 for (i = 0; i < dev->num_ports; i++) {
Daniel Jurgensaac44922018-01-04 17:25:40 +02004778 err = __mlx5_ib_alloc_counters(dev, &dev->port[i].cnts);
4779 if (err)
4780 goto err_alloc;
Kamal Heib7c16f472017-01-18 15:25:09 +02004781
Daniel Jurgensaac44922018-01-04 17:25:40 +02004782 mlx5_ib_fill_counters(dev, dev->port[i].cnts.names,
4783 dev->port[i].cnts.offsets);
4784
4785 err = mlx5_core_alloc_q_counter(dev->mdev,
4786 &dev->port[i].cnts.set_id);
4787 if (err) {
Mark Bloch0837e862016-06-17 15:10:55 +03004788 mlx5_ib_warn(dev,
4789 "couldn't allocate queue counter for port %d, err %d\n",
Daniel Jurgensaac44922018-01-04 17:25:40 +02004790 i + 1, err);
4791 goto err_alloc;
Mark Bloch0837e862016-06-17 15:10:55 +03004792 }
Daniel Jurgensaac44922018-01-04 17:25:40 +02004793 dev->port[i].cnts.set_id_valid = true;
Mark Bloch0837e862016-06-17 15:10:55 +03004794 }
4795
4796 return 0;
4797
Daniel Jurgensaac44922018-01-04 17:25:40 +02004798err_alloc:
4799 mlx5_ib_dealloc_counters(dev);
4800 return err;
Mark Bloch0837e862016-06-17 15:10:55 +03004801}
4802
Mark Bloch0ad17a82016-06-17 15:10:56 +03004803static struct rdma_hw_stats *mlx5_ib_alloc_hw_stats(struct ib_device *ibdev,
4804 u8 port_num)
4805{
Kamal Heib7c16f472017-01-18 15:25:09 +02004806 struct mlx5_ib_dev *dev = to_mdev(ibdev);
4807 struct mlx5_ib_port *port = &dev->port[port_num - 1];
Mark Bloch0ad17a82016-06-17 15:10:56 +03004808
4809 /* We support only per port stats */
4810 if (port_num == 0)
4811 return NULL;
4812
Parav Pandite1f24a72017-04-16 07:29:29 +03004813 return rdma_alloc_hw_stats_struct(port->cnts.names,
4814 port->cnts.num_q_counters +
4815 port->cnts.num_cong_counters,
Mark Bloch0ad17a82016-06-17 15:10:56 +03004816 RDMA_HW_STATS_DEFAULT_LIFESPAN);
4817}
4818
Daniel Jurgensaac44922018-01-04 17:25:40 +02004819static int mlx5_ib_query_q_counters(struct mlx5_core_dev *mdev,
Parav Pandite1f24a72017-04-16 07:29:29 +03004820 struct mlx5_ib_port *port,
4821 struct rdma_hw_stats *stats)
4822{
4823 int outlen = MLX5_ST_SZ_BYTES(query_q_counter_out);
4824 void *out;
4825 __be32 val;
4826 int ret, i;
4827
Leon Romanovsky1b9a07e2017-05-10 21:32:18 +03004828 out = kvzalloc(outlen, GFP_KERNEL);
Parav Pandite1f24a72017-04-16 07:29:29 +03004829 if (!out)
4830 return -ENOMEM;
4831
Daniel Jurgensaac44922018-01-04 17:25:40 +02004832 ret = mlx5_core_query_q_counter(mdev,
Parav Pandite1f24a72017-04-16 07:29:29 +03004833 port->cnts.set_id, 0,
4834 out, outlen);
4835 if (ret)
4836 goto free;
4837
4838 for (i = 0; i < port->cnts.num_q_counters; i++) {
4839 val = *(__be32 *)(out + port->cnts.offsets[i]);
4840 stats->value[i] = (u64)be32_to_cpu(val);
4841 }
4842
4843free:
4844 kvfree(out);
4845 return ret;
4846}
4847
Mark Bloch0ad17a82016-06-17 15:10:56 +03004848static int mlx5_ib_get_hw_stats(struct ib_device *ibdev,
4849 struct rdma_hw_stats *stats,
Kamal Heib7c16f472017-01-18 15:25:09 +02004850 u8 port_num, int index)
Mark Bloch0ad17a82016-06-17 15:10:56 +03004851{
4852 struct mlx5_ib_dev *dev = to_mdev(ibdev);
Kamal Heib7c16f472017-01-18 15:25:09 +02004853 struct mlx5_ib_port *port = &dev->port[port_num - 1];
Daniel Jurgensaac44922018-01-04 17:25:40 +02004854 struct mlx5_core_dev *mdev;
Parav Pandite1f24a72017-04-16 07:29:29 +03004855 int ret, num_counters;
Daniel Jurgensaac44922018-01-04 17:25:40 +02004856 u8 mdev_port_num;
Mark Bloch0ad17a82016-06-17 15:10:56 +03004857
Kamal Heib7c16f472017-01-18 15:25:09 +02004858 if (!stats)
Parav Pandite1f24a72017-04-16 07:29:29 +03004859 return -EINVAL;
Mark Bloch0ad17a82016-06-17 15:10:56 +03004860
Daniel Jurgensaac44922018-01-04 17:25:40 +02004861 num_counters = port->cnts.num_q_counters + port->cnts.num_cong_counters;
4862
4863 /* q_counters are per IB device, query the master mdev */
4864 ret = mlx5_ib_query_q_counters(dev->mdev, port, stats);
Mark Bloch0ad17a82016-06-17 15:10:56 +03004865 if (ret)
Parav Pandite1f24a72017-04-16 07:29:29 +03004866 return ret;
Mark Bloch0ad17a82016-06-17 15:10:56 +03004867
Parav Pandite1f24a72017-04-16 07:29:29 +03004868 if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) {
Daniel Jurgensaac44922018-01-04 17:25:40 +02004869 mdev = mlx5_ib_get_native_port_mdev(dev, port_num,
4870 &mdev_port_num);
4871 if (!mdev) {
4872 /* If port is not affiliated yet, its in down state
4873 * which doesn't have any counters yet, so it would be
4874 * zero. So no need to read from the HCA.
4875 */
4876 goto done;
4877 }
Majd Dibbiny71a0ff62017-12-21 17:38:26 +02004878 ret = mlx5_lag_query_cong_counters(dev->mdev,
4879 stats->value +
4880 port->cnts.num_q_counters,
4881 port->cnts.num_cong_counters,
4882 port->cnts.offsets +
4883 port->cnts.num_q_counters);
Daniel Jurgensaac44922018-01-04 17:25:40 +02004884
4885 mlx5_ib_put_native_port_mdev(dev, port_num);
Parav Pandite1f24a72017-04-16 07:29:29 +03004886 if (ret)
4887 return ret;
Mark Bloch0ad17a82016-06-17 15:10:56 +03004888 }
Kamal Heib7c16f472017-01-18 15:25:09 +02004889
Daniel Jurgensaac44922018-01-04 17:25:40 +02004890done:
Parav Pandite1f24a72017-04-16 07:29:29 +03004891 return num_counters;
Mark Bloch0ad17a82016-06-17 15:10:56 +03004892}
4893
Niranjana Vishwanathapura8e959602017-06-30 13:14:46 -07004894static void mlx5_ib_free_rdma_netdev(struct net_device *netdev)
4895{
4896 return mlx5_rdma_netdev_free(netdev);
4897}
4898
Erez Shitrit693dfd52017-04-27 17:01:34 +03004899static struct net_device*
4900mlx5_ib_alloc_rdma_netdev(struct ib_device *hca,
4901 u8 port_num,
4902 enum rdma_netdev_t type,
4903 const char *name,
4904 unsigned char name_assign_type,
4905 void (*setup)(struct net_device *))
4906{
Niranjana Vishwanathapura8e959602017-06-30 13:14:46 -07004907 struct net_device *netdev;
4908 struct rdma_netdev *rn;
4909
Erez Shitrit693dfd52017-04-27 17:01:34 +03004910 if (type != RDMA_NETDEV_IPOIB)
4911 return ERR_PTR(-EOPNOTSUPP);
4912
Niranjana Vishwanathapura8e959602017-06-30 13:14:46 -07004913 netdev = mlx5_rdma_netdev_alloc(to_mdev(hca)->mdev, hca,
4914 name, setup);
4915 if (likely(!IS_ERR_OR_NULL(netdev))) {
4916 rn = netdev_priv(netdev);
4917 rn->free_rdma_netdev = mlx5_ib_free_rdma_netdev;
4918 }
4919 return netdev;
Erez Shitrit693dfd52017-04-27 17:01:34 +03004920}
4921
Maor Gottliebfe248c32017-05-30 10:29:14 +03004922static void delay_drop_debugfs_cleanup(struct mlx5_ib_dev *dev)
4923{
4924 if (!dev->delay_drop.dbg)
4925 return;
4926 debugfs_remove_recursive(dev->delay_drop.dbg->dir_debugfs);
4927 kfree(dev->delay_drop.dbg);
4928 dev->delay_drop.dbg = NULL;
4929}
4930
Maor Gottlieb03404e82017-05-30 10:29:13 +03004931static void cancel_delay_drop(struct mlx5_ib_dev *dev)
4932{
4933 if (!(dev->ib_dev.attrs.raw_packet_caps & IB_RAW_PACKET_CAP_DELAY_DROP))
4934 return;
4935
4936 cancel_work_sync(&dev->delay_drop.delay_drop_work);
Maor Gottliebfe248c32017-05-30 10:29:14 +03004937 delay_drop_debugfs_cleanup(dev);
4938}
4939
4940static ssize_t delay_drop_timeout_read(struct file *filp, char __user *buf,
4941 size_t count, loff_t *pos)
4942{
4943 struct mlx5_ib_delay_drop *delay_drop = filp->private_data;
4944 char lbuf[20];
4945 int len;
4946
4947 len = snprintf(lbuf, sizeof(lbuf), "%u\n", delay_drop->timeout);
4948 return simple_read_from_buffer(buf, count, pos, lbuf, len);
4949}
4950
4951static ssize_t delay_drop_timeout_write(struct file *filp, const char __user *buf,
4952 size_t count, loff_t *pos)
4953{
4954 struct mlx5_ib_delay_drop *delay_drop = filp->private_data;
4955 u32 timeout;
4956 u32 var;
4957
4958 if (kstrtouint_from_user(buf, count, 0, &var))
4959 return -EFAULT;
4960
4961 timeout = min_t(u32, roundup(var, 100), MLX5_MAX_DELAY_DROP_TIMEOUT_MS *
4962 1000);
4963 if (timeout != var)
4964 mlx5_ib_dbg(delay_drop->dev, "Round delay drop timeout to %u usec\n",
4965 timeout);
4966
4967 delay_drop->timeout = timeout;
4968
4969 return count;
4970}
4971
4972static const struct file_operations fops_delay_drop_timeout = {
4973 .owner = THIS_MODULE,
4974 .open = simple_open,
4975 .write = delay_drop_timeout_write,
4976 .read = delay_drop_timeout_read,
4977};
4978
4979static int delay_drop_debugfs_init(struct mlx5_ib_dev *dev)
4980{
4981 struct mlx5_ib_dbg_delay_drop *dbg;
4982
4983 if (!mlx5_debugfs_root)
4984 return 0;
4985
4986 dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
4987 if (!dbg)
4988 return -ENOMEM;
4989
Sudip Mukherjeecbafad82017-09-18 12:28:48 +01004990 dev->delay_drop.dbg = dbg;
4991
Maor Gottliebfe248c32017-05-30 10:29:14 +03004992 dbg->dir_debugfs =
4993 debugfs_create_dir("delay_drop",
4994 dev->mdev->priv.dbg_root);
4995 if (!dbg->dir_debugfs)
Sudip Mukherjeecbafad82017-09-18 12:28:48 +01004996 goto out_debugfs;
Maor Gottliebfe248c32017-05-30 10:29:14 +03004997
4998 dbg->events_cnt_debugfs =
4999 debugfs_create_atomic_t("num_timeout_events", 0400,
5000 dbg->dir_debugfs,
5001 &dev->delay_drop.events_cnt);
5002 if (!dbg->events_cnt_debugfs)
5003 goto out_debugfs;
5004
5005 dbg->rqs_cnt_debugfs =
5006 debugfs_create_atomic_t("num_rqs", 0400,
5007 dbg->dir_debugfs,
5008 &dev->delay_drop.rqs_cnt);
5009 if (!dbg->rqs_cnt_debugfs)
5010 goto out_debugfs;
5011
5012 dbg->timeout_debugfs =
5013 debugfs_create_file("timeout", 0600,
5014 dbg->dir_debugfs,
5015 &dev->delay_drop,
5016 &fops_delay_drop_timeout);
5017 if (!dbg->timeout_debugfs)
5018 goto out_debugfs;
5019
5020 return 0;
5021
5022out_debugfs:
5023 delay_drop_debugfs_cleanup(dev);
5024 return -ENOMEM;
Maor Gottlieb03404e82017-05-30 10:29:13 +03005025}
5026
5027static void init_delay_drop(struct mlx5_ib_dev *dev)
5028{
5029 if (!(dev->ib_dev.attrs.raw_packet_caps & IB_RAW_PACKET_CAP_DELAY_DROP))
5030 return;
5031
5032 mutex_init(&dev->delay_drop.lock);
5033 dev->delay_drop.dev = dev;
5034 dev->delay_drop.activate = false;
5035 dev->delay_drop.timeout = MLX5_MAX_DELAY_DROP_TIMEOUT_MS * 1000;
5036 INIT_WORK(&dev->delay_drop.delay_drop_work, delay_drop_handler);
Maor Gottliebfe248c32017-05-30 10:29:14 +03005037 atomic_set(&dev->delay_drop.rqs_cnt, 0);
5038 atomic_set(&dev->delay_drop.events_cnt, 0);
5039
5040 if (delay_drop_debugfs_init(dev))
5041 mlx5_ib_warn(dev, "Failed to init delay drop debugfs\n");
Maor Gottlieb03404e82017-05-30 10:29:13 +03005042}
5043
Leon Romanovsky84305d712017-08-17 15:50:53 +03005044static const struct cpumask *
5045mlx5_ib_get_vector_affinity(struct ib_device *ibdev, int comp_vector)
Sagi Grimberg40b24402017-07-13 11:09:42 +03005046{
5047 struct mlx5_ib_dev *dev = to_mdev(ibdev);
5048
Israel Rukshin6082d9c2018-04-12 09:49:11 +00005049 return mlx5_get_vector_affinity_hint(dev->mdev, comp_vector);
Sagi Grimberg40b24402017-07-13 11:09:42 +03005050}
5051
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005052/* The mlx5_ib_multiport_mutex should be held when calling this function */
5053static void mlx5_ib_unbind_slave_port(struct mlx5_ib_dev *ibdev,
5054 struct mlx5_ib_multiport_info *mpi)
5055{
5056 u8 port_num = mlx5_core_native_port_num(mpi->mdev) - 1;
5057 struct mlx5_ib_port *port = &ibdev->port[port_num];
5058 int comps;
5059 int err;
5060 int i;
5061
Parav Pandita9e546e2018-01-04 17:25:39 +02005062 mlx5_ib_cleanup_cong_debugfs(ibdev, port_num);
5063
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005064 spin_lock(&port->mp.mpi_lock);
5065 if (!mpi->ibdev) {
5066 spin_unlock(&port->mp.mpi_lock);
5067 return;
5068 }
5069 mpi->ibdev = NULL;
5070
5071 spin_unlock(&port->mp.mpi_lock);
5072 mlx5_remove_netdev_notifier(ibdev, port_num);
5073 spin_lock(&port->mp.mpi_lock);
5074
5075 comps = mpi->mdev_refcnt;
5076 if (comps) {
5077 mpi->unaffiliate = true;
5078 init_completion(&mpi->unref_comp);
5079 spin_unlock(&port->mp.mpi_lock);
5080
5081 for (i = 0; i < comps; i++)
5082 wait_for_completion(&mpi->unref_comp);
5083
5084 spin_lock(&port->mp.mpi_lock);
5085 mpi->unaffiliate = false;
5086 }
5087
5088 port->mp.mpi = NULL;
5089
5090 list_add_tail(&mpi->list, &mlx5_ib_unaffiliated_port_list);
5091
5092 spin_unlock(&port->mp.mpi_lock);
5093
5094 err = mlx5_nic_vport_unaffiliate_multiport(mpi->mdev);
5095
5096 mlx5_ib_dbg(ibdev, "unaffiliated port %d\n", port_num + 1);
5097 /* Log an error, still needed to cleanup the pointers and add
5098 * it back to the list.
5099 */
5100 if (err)
5101 mlx5_ib_err(ibdev, "Failed to unaffiliate port %u\n",
5102 port_num + 1);
5103
5104 ibdev->roce[port_num].last_port_state = IB_PORT_DOWN;
5105}
5106
5107/* The mlx5_ib_multiport_mutex should be held when calling this function */
5108static bool mlx5_ib_bind_slave_port(struct mlx5_ib_dev *ibdev,
5109 struct mlx5_ib_multiport_info *mpi)
5110{
5111 u8 port_num = mlx5_core_native_port_num(mpi->mdev) - 1;
5112 int err;
5113
5114 spin_lock(&ibdev->port[port_num].mp.mpi_lock);
5115 if (ibdev->port[port_num].mp.mpi) {
5116 mlx5_ib_warn(ibdev, "port %d already affiliated.\n",
5117 port_num + 1);
5118 spin_unlock(&ibdev->port[port_num].mp.mpi_lock);
5119 return false;
5120 }
5121
5122 ibdev->port[port_num].mp.mpi = mpi;
5123 mpi->ibdev = ibdev;
5124 spin_unlock(&ibdev->port[port_num].mp.mpi_lock);
5125
5126 err = mlx5_nic_vport_affiliate_multiport(ibdev->mdev, mpi->mdev);
5127 if (err)
5128 goto unbind;
5129
5130 err = get_port_caps(ibdev, mlx5_core_native_port_num(mpi->mdev));
5131 if (err)
5132 goto unbind;
5133
5134 err = mlx5_add_netdev_notifier(ibdev, port_num);
5135 if (err) {
5136 mlx5_ib_err(ibdev, "failed adding netdev notifier for port %u\n",
5137 port_num + 1);
5138 goto unbind;
5139 }
5140
Parav Pandita9e546e2018-01-04 17:25:39 +02005141 err = mlx5_ib_init_cong_debugfs(ibdev, port_num);
5142 if (err)
5143 goto unbind;
5144
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005145 return true;
5146
5147unbind:
5148 mlx5_ib_unbind_slave_port(ibdev, mpi);
5149 return false;
5150}
5151
5152static int mlx5_ib_init_multiport_master(struct mlx5_ib_dev *dev)
5153{
5154 int port_num = mlx5_core_native_port_num(dev->mdev) - 1;
5155 enum rdma_link_layer ll = mlx5_ib_port_link_layer(&dev->ib_dev,
5156 port_num + 1);
5157 struct mlx5_ib_multiport_info *mpi;
5158 int err;
5159 int i;
5160
5161 if (!mlx5_core_is_mp_master(dev->mdev) || ll != IB_LINK_LAYER_ETHERNET)
5162 return 0;
5163
5164 err = mlx5_query_nic_vport_system_image_guid(dev->mdev,
5165 &dev->sys_image_guid);
5166 if (err)
5167 return err;
5168
5169 err = mlx5_nic_vport_enable_roce(dev->mdev);
5170 if (err)
5171 return err;
5172
5173 mutex_lock(&mlx5_ib_multiport_mutex);
5174 for (i = 0; i < dev->num_ports; i++) {
5175 bool bound = false;
5176
5177 /* build a stub multiport info struct for the native port. */
5178 if (i == port_num) {
5179 mpi = kzalloc(sizeof(*mpi), GFP_KERNEL);
5180 if (!mpi) {
5181 mutex_unlock(&mlx5_ib_multiport_mutex);
5182 mlx5_nic_vport_disable_roce(dev->mdev);
5183 return -ENOMEM;
5184 }
5185
5186 mpi->is_master = true;
5187 mpi->mdev = dev->mdev;
5188 mpi->sys_image_guid = dev->sys_image_guid;
5189 dev->port[i].mp.mpi = mpi;
5190 mpi->ibdev = dev;
5191 mpi = NULL;
5192 continue;
5193 }
5194
5195 list_for_each_entry(mpi, &mlx5_ib_unaffiliated_port_list,
5196 list) {
5197 if (dev->sys_image_guid == mpi->sys_image_guid &&
5198 (mlx5_core_native_port_num(mpi->mdev) - 1) == i) {
5199 bound = mlx5_ib_bind_slave_port(dev, mpi);
5200 }
5201
5202 if (bound) {
5203 dev_dbg(&mpi->mdev->pdev->dev, "removing port from unaffiliated list.\n");
5204 mlx5_ib_dbg(dev, "port %d bound\n", i + 1);
5205 list_del(&mpi->list);
5206 break;
5207 }
5208 }
5209 if (!bound) {
5210 get_port_caps(dev, i + 1);
5211 mlx5_ib_dbg(dev, "no free port found for port %d\n",
5212 i + 1);
5213 }
5214 }
5215
5216 list_add_tail(&dev->ib_dev_list, &mlx5_ib_dev_list);
5217 mutex_unlock(&mlx5_ib_multiport_mutex);
5218 return err;
5219}
5220
5221static void mlx5_ib_cleanup_multiport_master(struct mlx5_ib_dev *dev)
5222{
5223 int port_num = mlx5_core_native_port_num(dev->mdev) - 1;
5224 enum rdma_link_layer ll = mlx5_ib_port_link_layer(&dev->ib_dev,
5225 port_num + 1);
5226 int i;
5227
5228 if (!mlx5_core_is_mp_master(dev->mdev) || ll != IB_LINK_LAYER_ETHERNET)
5229 return;
5230
5231 mutex_lock(&mlx5_ib_multiport_mutex);
5232 for (i = 0; i < dev->num_ports; i++) {
5233 if (dev->port[i].mp.mpi) {
5234 /* Destroy the native port stub */
5235 if (i == port_num) {
5236 kfree(dev->port[i].mp.mpi);
5237 dev->port[i].mp.mpi = NULL;
5238 } else {
5239 mlx5_ib_dbg(dev, "unbinding port_num: %d\n", i + 1);
5240 mlx5_ib_unbind_slave_port(dev, dev->port[i].mp.mpi);
5241 }
5242 }
5243 }
5244
5245 mlx5_ib_dbg(dev, "removing from devlist\n");
5246 list_del(&dev->ib_dev_list);
5247 mutex_unlock(&mlx5_ib_multiport_mutex);
5248
5249 mlx5_nic_vport_disable_roce(dev->mdev);
5250}
5251
Ariel Levkovich24da0012018-04-05 18:53:27 +03005252ADD_UVERBS_ATTRIBUTES_SIMPLE(mlx5_ib_dm, UVERBS_OBJECT_DM,
5253 UVERBS_METHOD_DM_ALLOC,
5254 &UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_ALLOC_DM_RESP_START_OFFSET,
5255 UVERBS_ATTR_TYPE(u64),
5256 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)),
5257 &UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_ALLOC_DM_RESP_PAGE_INDEX,
5258 UVERBS_ATTR_TYPE(u16),
5259 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
5260
Aviad Yehezkelc6475a02018-03-28 09:27:50 +03005261ADD_UVERBS_ATTRIBUTES_SIMPLE(mlx5_ib_flow_action, UVERBS_OBJECT_FLOW_ACTION,
5262 UVERBS_METHOD_FLOW_ACTION_ESP_CREATE,
5263 &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS,
5264 UVERBS_ATTR_TYPE(u64),
5265 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
5266
Yishai Hadasc59450c2018-06-17 13:00:06 +03005267#define NUM_TREES 3
Matan Barak8c846602018-03-28 09:27:41 +03005268static int populate_specs_root(struct mlx5_ib_dev *dev)
5269{
5270 const struct uverbs_object_tree_def *default_root[NUM_TREES + 1] = {
5271 uverbs_default_get_objects()};
5272 size_t num_trees = 1;
5273
Aviad Yehezkelc6475a02018-03-28 09:27:50 +03005274 if (mlx5_accel_ipsec_device_caps(dev->mdev) & MLX5_ACCEL_IPSEC_CAP_DEVICE &&
5275 !WARN_ON(num_trees >= ARRAY_SIZE(default_root)))
5276 default_root[num_trees++] = &mlx5_ib_flow_action;
5277
Ariel Levkovich24da0012018-04-05 18:53:27 +03005278 if (MLX5_CAP_DEV_MEM(dev->mdev, memic) &&
5279 !WARN_ON(num_trees >= ARRAY_SIZE(default_root)))
5280 default_root[num_trees++] = &mlx5_ib_dm;
5281
Yishai Hadasc59450c2018-06-17 13:00:06 +03005282 if (MLX5_CAP_GEN_64(dev->mdev, general_obj_types) &
5283 MLX5_GENERAL_OBJ_TYPES_CAP_UCTX &&
5284 !WARN_ON(num_trees >= ARRAY_SIZE(default_root)))
5285 default_root[num_trees++] = mlx5_ib_get_devx_tree();
5286
Matan Barak8c846602018-03-28 09:27:41 +03005287 dev->ib_dev.specs_root =
5288 uverbs_alloc_spec_tree(num_trees, default_root);
5289
5290 return PTR_ERR_OR_ZERO(dev->ib_dev.specs_root);
5291}
5292
5293static void depopulate_specs_root(struct mlx5_ib_dev *dev)
5294{
5295 uverbs_free_spec_tree(dev->ib_dev.specs_root);
5296}
5297
Raed Salem1a1e03d2018-05-31 16:43:41 +03005298static int mlx5_ib_read_counters(struct ib_counters *counters,
5299 struct ib_counters_read_attr *read_attr,
5300 struct uverbs_attr_bundle *attrs)
5301{
5302 struct mlx5_ib_mcounters *mcounters = to_mcounters(counters);
5303 struct mlx5_read_counters_attr mread_attr = {};
5304 struct mlx5_ib_flow_counters_desc *desc;
5305 int ret, i;
5306
5307 mutex_lock(&mcounters->mcntrs_mutex);
5308 if (mcounters->cntrs_max_index > read_attr->ncounters) {
5309 ret = -EINVAL;
5310 goto err_bound;
5311 }
5312
5313 mread_attr.out = kcalloc(mcounters->counters_num, sizeof(u64),
5314 GFP_KERNEL);
5315 if (!mread_attr.out) {
5316 ret = -ENOMEM;
5317 goto err_bound;
5318 }
5319
5320 mread_attr.hw_cntrs_hndl = mcounters->hw_cntrs_hndl;
5321 mread_attr.flags = read_attr->flags;
5322 ret = mcounters->read_counters(counters->device, &mread_attr);
5323 if (ret)
5324 goto err_read;
5325
5326 /* do the pass over the counters data array to assign according to the
5327 * descriptions and indexing pairs
5328 */
5329 desc = mcounters->counters_data;
5330 for (i = 0; i < mcounters->ncounters; i++)
5331 read_attr->counters_buff[desc[i].index] += mread_attr.out[desc[i].description];
5332
5333err_read:
5334 kfree(mread_attr.out);
5335err_bound:
5336 mutex_unlock(&mcounters->mcntrs_mutex);
5337 return ret;
5338}
5339
Raed Salemb29e2a12018-05-31 16:43:38 +03005340static int mlx5_ib_destroy_counters(struct ib_counters *counters)
5341{
5342 struct mlx5_ib_mcounters *mcounters = to_mcounters(counters);
5343
Raed Salem3b3233f2018-05-31 16:43:39 +03005344 counters_clear_description(counters);
5345 if (mcounters->hw_cntrs_hndl)
5346 mlx5_fc_destroy(to_mdev(counters->device)->mdev,
5347 mcounters->hw_cntrs_hndl);
5348
Raed Salemb29e2a12018-05-31 16:43:38 +03005349 kfree(mcounters);
5350
5351 return 0;
5352}
5353
5354static struct ib_counters *mlx5_ib_create_counters(struct ib_device *device,
5355 struct uverbs_attr_bundle *attrs)
5356{
5357 struct mlx5_ib_mcounters *mcounters;
5358
5359 mcounters = kzalloc(sizeof(*mcounters), GFP_KERNEL);
5360 if (!mcounters)
5361 return ERR_PTR(-ENOMEM);
5362
Raed Salem3b3233f2018-05-31 16:43:39 +03005363 mutex_init(&mcounters->mcntrs_mutex);
5364
Raed Salemb29e2a12018-05-31 16:43:38 +03005365 return &mcounters->ibcntrs;
5366}
5367
Mark Blochb5ca15a2018-01-23 11:16:30 +00005368void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev)
Eli Cohene126ba92013-07-07 17:25:49 +03005369{
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005370 mlx5_ib_cleanup_multiport_master(dev);
Mark Bloch3cc297d2018-01-01 13:07:03 +02005371#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
5372 cleanup_srcu_struct(&dev->mr_srcu);
5373#endif
Mark Bloch16c19752018-01-01 13:06:58 +02005374 kfree(dev->port);
5375}
5376
Mark Blochb5ca15a2018-01-23 11:16:30 +00005377int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005378{
5379 struct mlx5_core_dev *mdev = dev->mdev;
Aviv Heller4babcf92016-09-18 20:48:03 +03005380 const char *name;
Eli Cohene126ba92013-07-07 17:25:49 +03005381 int err;
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005382 int i;
Eli Cohene126ba92013-07-07 17:25:49 +03005383
Daniel Jurgens508562d2018-01-04 17:25:34 +02005384 dev->port = kcalloc(dev->num_ports, sizeof(*dev->port),
Mark Bloch0837e862016-06-17 15:10:55 +03005385 GFP_KERNEL);
5386 if (!dev->port)
Mark Bloch16c19752018-01-01 13:06:58 +02005387 return -ENOMEM;
Mark Bloch0837e862016-06-17 15:10:55 +03005388
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005389 for (i = 0; i < dev->num_ports; i++) {
5390 spin_lock_init(&dev->port[i].mp.mpi_lock);
5391 rwlock_init(&dev->roce[i].netdev_lock);
5392 }
5393
5394 err = mlx5_ib_init_multiport_master(dev);
Eli Cohene126ba92013-07-07 17:25:49 +03005395 if (err)
Mark Bloch0837e862016-06-17 15:10:55 +03005396 goto err_free_port;
Eli Cohene126ba92013-07-07 17:25:49 +03005397
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005398 if (!mlx5_core_mp_enabled(mdev)) {
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005399 for (i = 1; i <= dev->num_ports; i++) {
5400 err = get_port_caps(dev, i);
5401 if (err)
5402 break;
5403 }
5404 } else {
5405 err = get_port_caps(dev, mlx5_core_native_port_num(mdev));
5406 }
5407 if (err)
5408 goto err_mp;
5409
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03005410 if (mlx5_use_mad_ifc(dev))
5411 get_ext_port_caps(dev);
Eli Cohene126ba92013-07-07 17:25:49 +03005412
Aviv Heller4babcf92016-09-18 20:48:03 +03005413 if (!mlx5_lag_is_active(mdev))
5414 name = "mlx5_%d";
5415 else
5416 name = "mlx5_bond_%d";
5417
5418 strlcpy(dev->ib_dev.name, name, IB_DEVICE_NAME_MAX);
Eli Cohene126ba92013-07-07 17:25:49 +03005419 dev->ib_dev.owner = THIS_MODULE;
5420 dev->ib_dev.node_type = RDMA_NODE_IB_CA;
Sagi Grimbergc6790aa2015-09-24 10:34:23 +03005421 dev->ib_dev.local_dma_lkey = 0 /* not supported for now */;
Daniel Jurgens508562d2018-01-04 17:25:34 +02005422 dev->ib_dev.phys_port_cnt = dev->num_ports;
Saeed Mahameed233d05d2015-04-02 17:07:32 +03005423 dev->ib_dev.num_comp_vectors =
5424 dev->mdev->priv.eq_table.num_comp_vectors;
Bart Van Assche9b0c2892017-01-20 13:04:21 -08005425 dev->ib_dev.dev.parent = &mdev->pdev->dev;
Eli Cohene126ba92013-07-07 17:25:49 +03005426
Mark Bloch3cc297d2018-01-01 13:07:03 +02005427 mutex_init(&dev->cap_mask_mutex);
5428 INIT_LIST_HEAD(&dev->qp_list);
5429 spin_lock_init(&dev->reset_flow_resource_lock);
5430
Ariel Levkovich24da0012018-04-05 18:53:27 +03005431 spin_lock_init(&dev->memic.memic_lock);
5432 dev->memic.dev = mdev;
5433
Mark Bloch3cc297d2018-01-01 13:07:03 +02005434#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
5435 err = init_srcu_struct(&dev->mr_srcu);
5436 if (err)
5437 goto err_free_port;
5438#endif
5439
Mark Bloch16c19752018-01-01 13:06:58 +02005440 return 0;
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005441err_mp:
5442 mlx5_ib_cleanup_multiport_master(dev);
Mark Bloch16c19752018-01-01 13:06:58 +02005443
5444err_free_port:
5445 kfree(dev->port);
5446
5447 return -ENOMEM;
5448}
5449
Mark Bloch9a4ca382018-01-16 14:42:35 +00005450static int mlx5_ib_stage_flow_db_init(struct mlx5_ib_dev *dev)
5451{
5452 dev->flow_db = kzalloc(sizeof(*dev->flow_db), GFP_KERNEL);
5453
5454 if (!dev->flow_db)
5455 return -ENOMEM;
5456
5457 mutex_init(&dev->flow_db->lock);
5458
5459 return 0;
5460}
5461
Mark Blochb5ca15a2018-01-23 11:16:30 +00005462int mlx5_ib_stage_rep_flow_db_init(struct mlx5_ib_dev *dev)
5463{
5464 struct mlx5_ib_dev *nic_dev;
5465
5466 nic_dev = mlx5_ib_get_uplink_ibdev(dev->mdev->priv.eswitch);
5467
5468 if (!nic_dev)
5469 return -EINVAL;
5470
5471 dev->flow_db = nic_dev->flow_db;
5472
5473 return 0;
5474}
5475
Mark Bloch9a4ca382018-01-16 14:42:35 +00005476static void mlx5_ib_stage_flow_db_cleanup(struct mlx5_ib_dev *dev)
5477{
5478 kfree(dev->flow_db);
5479}
5480
Mark Blochb5ca15a2018-01-23 11:16:30 +00005481int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005482{
5483 struct mlx5_core_dev *mdev = dev->mdev;
Mark Bloch16c19752018-01-01 13:06:58 +02005484 int err;
5485
Eli Cohene126ba92013-07-07 17:25:49 +03005486 dev->ib_dev.uverbs_abi_ver = MLX5_IB_UVERBS_ABI_VERSION;
5487 dev->ib_dev.uverbs_cmd_mask =
5488 (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
5489 (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) |
5490 (1ull << IB_USER_VERBS_CMD_QUERY_PORT) |
5491 (1ull << IB_USER_VERBS_CMD_ALLOC_PD) |
5492 (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) |
Moni Shoua41c450f2016-11-23 08:23:26 +02005493 (1ull << IB_USER_VERBS_CMD_CREATE_AH) |
5494 (1ull << IB_USER_VERBS_CMD_DESTROY_AH) |
Eli Cohene126ba92013-07-07 17:25:49 +03005495 (1ull << IB_USER_VERBS_CMD_REG_MR) |
Noa Osherovich56e11d62016-02-29 16:46:51 +02005496 (1ull << IB_USER_VERBS_CMD_REREG_MR) |
Eli Cohene126ba92013-07-07 17:25:49 +03005497 (1ull << IB_USER_VERBS_CMD_DEREG_MR) |
5498 (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
5499 (1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
5500 (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) |
5501 (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |
5502 (1ull << IB_USER_VERBS_CMD_CREATE_QP) |
5503 (1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
5504 (1ull << IB_USER_VERBS_CMD_QUERY_QP) |
5505 (1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
5506 (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) |
5507 (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) |
5508 (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
5509 (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
5510 (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
5511 (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ) |
5512 (1ull << IB_USER_VERBS_CMD_CREATE_XSRQ) |
5513 (1ull << IB_USER_VERBS_CMD_OPEN_QP);
Haggai Eran1707cb42015-02-08 13:28:52 +02005514 dev->ib_dev.uverbs_ex_cmd_mask =
Matan Barakd4584dd2016-01-28 17:51:46 +02005515 (1ull << IB_USER_VERBS_EX_CMD_QUERY_DEVICE) |
5516 (1ull << IB_USER_VERBS_EX_CMD_CREATE_CQ) |
Bodong Wang7d29f342016-12-01 13:43:16 +02005517 (1ull << IB_USER_VERBS_EX_CMD_CREATE_QP) |
Yonatan Cohenb0e9df62017-11-13 10:51:15 +02005518 (1ull << IB_USER_VERBS_EX_CMD_MODIFY_QP) |
5519 (1ull << IB_USER_VERBS_EX_CMD_MODIFY_CQ);
Eli Cohene126ba92013-07-07 17:25:49 +03005520
5521 dev->ib_dev.query_device = mlx5_ib_query_device;
Achiad Shochatebd61f62015-12-23 18:47:16 +02005522 dev->ib_dev.get_link_layer = mlx5_ib_port_link_layer;
Eli Cohene126ba92013-07-07 17:25:49 +03005523 dev->ib_dev.query_gid = mlx5_ib_query_gid;
Achiad Shochat3cca2602015-12-23 18:47:23 +02005524 dev->ib_dev.add_gid = mlx5_ib_add_gid;
5525 dev->ib_dev.del_gid = mlx5_ib_del_gid;
Eli Cohene126ba92013-07-07 17:25:49 +03005526 dev->ib_dev.query_pkey = mlx5_ib_query_pkey;
5527 dev->ib_dev.modify_device = mlx5_ib_modify_device;
5528 dev->ib_dev.modify_port = mlx5_ib_modify_port;
5529 dev->ib_dev.alloc_ucontext = mlx5_ib_alloc_ucontext;
5530 dev->ib_dev.dealloc_ucontext = mlx5_ib_dealloc_ucontext;
5531 dev->ib_dev.mmap = mlx5_ib_mmap;
5532 dev->ib_dev.alloc_pd = mlx5_ib_alloc_pd;
5533 dev->ib_dev.dealloc_pd = mlx5_ib_dealloc_pd;
5534 dev->ib_dev.create_ah = mlx5_ib_create_ah;
5535 dev->ib_dev.query_ah = mlx5_ib_query_ah;
5536 dev->ib_dev.destroy_ah = mlx5_ib_destroy_ah;
5537 dev->ib_dev.create_srq = mlx5_ib_create_srq;
5538 dev->ib_dev.modify_srq = mlx5_ib_modify_srq;
5539 dev->ib_dev.query_srq = mlx5_ib_query_srq;
5540 dev->ib_dev.destroy_srq = mlx5_ib_destroy_srq;
5541 dev->ib_dev.post_srq_recv = mlx5_ib_post_srq_recv;
5542 dev->ib_dev.create_qp = mlx5_ib_create_qp;
5543 dev->ib_dev.modify_qp = mlx5_ib_modify_qp;
5544 dev->ib_dev.query_qp = mlx5_ib_query_qp;
5545 dev->ib_dev.destroy_qp = mlx5_ib_destroy_qp;
5546 dev->ib_dev.post_send = mlx5_ib_post_send;
5547 dev->ib_dev.post_recv = mlx5_ib_post_recv;
5548 dev->ib_dev.create_cq = mlx5_ib_create_cq;
5549 dev->ib_dev.modify_cq = mlx5_ib_modify_cq;
5550 dev->ib_dev.resize_cq = mlx5_ib_resize_cq;
5551 dev->ib_dev.destroy_cq = mlx5_ib_destroy_cq;
5552 dev->ib_dev.poll_cq = mlx5_ib_poll_cq;
5553 dev->ib_dev.req_notify_cq = mlx5_ib_arm_cq;
5554 dev->ib_dev.get_dma_mr = mlx5_ib_get_dma_mr;
5555 dev->ib_dev.reg_user_mr = mlx5_ib_reg_user_mr;
Noa Osherovich56e11d62016-02-29 16:46:51 +02005556 dev->ib_dev.rereg_user_mr = mlx5_ib_rereg_user_mr;
Eli Cohene126ba92013-07-07 17:25:49 +03005557 dev->ib_dev.dereg_mr = mlx5_ib_dereg_mr;
5558 dev->ib_dev.attach_mcast = mlx5_ib_mcg_attach;
5559 dev->ib_dev.detach_mcast = mlx5_ib_mcg_detach;
5560 dev->ib_dev.process_mad = mlx5_ib_process_mad;
Sagi Grimberg9bee1782015-07-30 10:32:35 +03005561 dev->ib_dev.alloc_mr = mlx5_ib_alloc_mr;
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03005562 dev->ib_dev.map_mr_sg = mlx5_ib_map_mr_sg;
Sagi Grimbergd5436ba2014-02-23 14:19:12 +02005563 dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status;
Ira Weinyc7342822016-06-15 02:22:01 -04005564 dev->ib_dev.get_dev_fw_str = get_dev_fw_str;
Sagi Grimberg40b24402017-07-13 11:09:42 +03005565 dev->ib_dev.get_vector_affinity = mlx5_ib_get_vector_affinity;
Niranjana Vishwanathapura8e959602017-06-30 13:14:46 -07005566 if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads))
Alex Vesker022d0382017-06-14 09:59:06 +03005567 dev->ib_dev.alloc_rdma_netdev = mlx5_ib_alloc_rdma_netdev;
Niranjana Vishwanathapura8e959602017-06-30 13:14:46 -07005568
Eli Coheneff901d2016-03-11 22:58:42 +02005569 if (mlx5_core_is_pf(mdev)) {
5570 dev->ib_dev.get_vf_config = mlx5_ib_get_vf_config;
5571 dev->ib_dev.set_vf_link_state = mlx5_ib_set_vf_link_state;
5572 dev->ib_dev.get_vf_stats = mlx5_ib_get_vf_stats;
5573 dev->ib_dev.set_vf_guid = mlx5_ib_set_vf_guid;
5574 }
Eli Cohene126ba92013-07-07 17:25:49 +03005575
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03005576 dev->ib_dev.disassociate_ucontext = mlx5_ib_disassociate_ucontext;
5577
Max Gurtovoy6e8484c2017-05-28 10:53:11 +03005578 dev->umr_fence = mlx5_get_umr_fence(MLX5_CAP_GEN(mdev, umr_fence));
5579
Matan Barakd2370e02016-02-29 18:05:30 +02005580 if (MLX5_CAP_GEN(mdev, imaicl)) {
5581 dev->ib_dev.alloc_mw = mlx5_ib_alloc_mw;
5582 dev->ib_dev.dealloc_mw = mlx5_ib_dealloc_mw;
5583 dev->ib_dev.uverbs_cmd_mask |=
5584 (1ull << IB_USER_VERBS_CMD_ALLOC_MW) |
5585 (1ull << IB_USER_VERBS_CMD_DEALLOC_MW);
5586 }
5587
Saeed Mahameed938fe832015-05-28 22:28:41 +03005588 if (MLX5_CAP_GEN(mdev, xrc)) {
Eli Cohene126ba92013-07-07 17:25:49 +03005589 dev->ib_dev.alloc_xrcd = mlx5_ib_alloc_xrcd;
5590 dev->ib_dev.dealloc_xrcd = mlx5_ib_dealloc_xrcd;
5591 dev->ib_dev.uverbs_cmd_mask |=
5592 (1ull << IB_USER_VERBS_CMD_OPEN_XRCD) |
5593 (1ull << IB_USER_VERBS_CMD_CLOSE_XRCD);
5594 }
5595
Ariel Levkovich24da0012018-04-05 18:53:27 +03005596 if (MLX5_CAP_DEV_MEM(mdev, memic)) {
5597 dev->ib_dev.alloc_dm = mlx5_ib_alloc_dm;
5598 dev->ib_dev.dealloc_dm = mlx5_ib_dealloc_dm;
Ariel Levkovich6c29f572018-04-05 18:53:29 +03005599 dev->ib_dev.reg_dm_mr = mlx5_ib_reg_dm_mr;
Ariel Levkovich24da0012018-04-05 18:53:27 +03005600 }
5601
Yishai Hadas81e30882017-06-08 16:15:09 +03005602 dev->ib_dev.create_flow = mlx5_ib_create_flow;
5603 dev->ib_dev.destroy_flow = mlx5_ib_destroy_flow;
5604 dev->ib_dev.uverbs_ex_cmd_mask |=
5605 (1ull << IB_USER_VERBS_EX_CMD_CREATE_FLOW) |
5606 (1ull << IB_USER_VERBS_EX_CMD_DESTROY_FLOW);
Aviad Yehezkelc6475a02018-03-28 09:27:50 +03005607 dev->ib_dev.create_flow_action_esp = mlx5_ib_create_flow_action_esp;
5608 dev->ib_dev.destroy_flow_action = mlx5_ib_destroy_flow_action;
Matan Barak349705c2018-03-28 09:27:51 +03005609 dev->ib_dev.modify_flow_action_esp = mlx5_ib_modify_flow_action_esp;
Matan Barak0ede73b2018-03-19 15:02:34 +02005610 dev->ib_dev.driver_id = RDMA_DRIVER_MLX5;
Raed Salemb29e2a12018-05-31 16:43:38 +03005611 dev->ib_dev.create_counters = mlx5_ib_create_counters;
5612 dev->ib_dev.destroy_counters = mlx5_ib_destroy_counters;
Raed Salem1a1e03d2018-05-31 16:43:41 +03005613 dev->ib_dev.read_counters = mlx5_ib_read_counters;
Yishai Hadas81e30882017-06-08 16:15:09 +03005614
Eli Cohene126ba92013-07-07 17:25:49 +03005615 err = init_node_data(dev);
5616 if (err)
Mark Bloch16c19752018-01-01 13:06:58 +02005617 return err;
Eli Cohene126ba92013-07-07 17:25:49 +03005618
Mark Blochc8b89922018-01-01 13:07:02 +02005619 if ((MLX5_CAP_GEN(dev->mdev, port_type) == MLX5_CAP_PORT_TYPE_ETH) &&
Jason Gunthorpee7996a92018-01-29 13:26:40 -07005620 (MLX5_CAP_GEN(dev->mdev, disable_local_lb_uc) ||
5621 MLX5_CAP_GEN(dev->mdev, disable_local_lb_mc)))
Mark Blochc8b89922018-01-01 13:07:02 +02005622 mutex_init(&dev->lb_mutex);
5623
Mark Bloch16c19752018-01-01 13:06:58 +02005624 return 0;
5625}
5626
Mark Bloch8e6efa32017-11-06 12:22:13 +00005627static int mlx5_ib_stage_non_default_cb(struct mlx5_ib_dev *dev)
5628{
5629 dev->ib_dev.get_port_immutable = mlx5_port_immutable;
5630 dev->ib_dev.query_port = mlx5_ib_query_port;
5631
5632 return 0;
5633}
5634
Mark Blochb5ca15a2018-01-23 11:16:30 +00005635int mlx5_ib_stage_rep_non_default_cb(struct mlx5_ib_dev *dev)
Mark Bloch8e6efa32017-11-06 12:22:13 +00005636{
5637 dev->ib_dev.get_port_immutable = mlx5_port_rep_immutable;
5638 dev->ib_dev.query_port = mlx5_ib_rep_query_port;
5639
5640 return 0;
5641}
5642
5643static int mlx5_ib_stage_common_roce_init(struct mlx5_ib_dev *dev,
5644 u8 port_num)
5645{
5646 int i;
5647
5648 for (i = 0; i < dev->num_ports; i++) {
5649 dev->roce[i].dev = dev;
5650 dev->roce[i].native_port_num = i + 1;
5651 dev->roce[i].last_port_state = IB_PORT_DOWN;
5652 }
5653
5654 dev->ib_dev.get_netdev = mlx5_ib_get_netdev;
5655 dev->ib_dev.create_wq = mlx5_ib_create_wq;
5656 dev->ib_dev.modify_wq = mlx5_ib_modify_wq;
5657 dev->ib_dev.destroy_wq = mlx5_ib_destroy_wq;
5658 dev->ib_dev.create_rwq_ind_table = mlx5_ib_create_rwq_ind_table;
5659 dev->ib_dev.destroy_rwq_ind_table = mlx5_ib_destroy_rwq_ind_table;
5660
5661 dev->ib_dev.uverbs_ex_cmd_mask |=
5662 (1ull << IB_USER_VERBS_EX_CMD_CREATE_WQ) |
5663 (1ull << IB_USER_VERBS_EX_CMD_MODIFY_WQ) |
5664 (1ull << IB_USER_VERBS_EX_CMD_DESTROY_WQ) |
5665 (1ull << IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL) |
5666 (1ull << IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL);
5667
5668 return mlx5_add_netdev_notifier(dev, port_num);
5669}
5670
5671static void mlx5_ib_stage_common_roce_cleanup(struct mlx5_ib_dev *dev)
5672{
5673 u8 port_num = mlx5_core_native_port_num(dev->mdev) - 1;
5674
5675 mlx5_remove_netdev_notifier(dev, port_num);
5676}
5677
5678int mlx5_ib_stage_rep_roce_init(struct mlx5_ib_dev *dev)
5679{
5680 struct mlx5_core_dev *mdev = dev->mdev;
5681 enum rdma_link_layer ll;
5682 int port_type_cap;
5683 int err = 0;
5684 u8 port_num;
5685
5686 port_num = mlx5_core_native_port_num(dev->mdev) - 1;
5687 port_type_cap = MLX5_CAP_GEN(mdev, port_type);
5688 ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);
5689
5690 if (ll == IB_LINK_LAYER_ETHERNET)
5691 err = mlx5_ib_stage_common_roce_init(dev, port_num);
5692
5693 return err;
5694}
5695
5696void mlx5_ib_stage_rep_roce_cleanup(struct mlx5_ib_dev *dev)
5697{
5698 mlx5_ib_stage_common_roce_cleanup(dev);
5699}
5700
Mark Bloch16c19752018-01-01 13:06:58 +02005701static int mlx5_ib_stage_roce_init(struct mlx5_ib_dev *dev)
5702{
5703 struct mlx5_core_dev *mdev = dev->mdev;
5704 enum rdma_link_layer ll;
5705 int port_type_cap;
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005706 u8 port_num;
Mark Bloch16c19752018-01-01 13:06:58 +02005707 int err;
5708
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005709 port_num = mlx5_core_native_port_num(dev->mdev) - 1;
Mark Bloch16c19752018-01-01 13:06:58 +02005710 port_type_cap = MLX5_CAP_GEN(mdev, port_type);
5711 ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);
5712
Achiad Shochatfc24fc52015-12-23 18:47:17 +02005713 if (ll == IB_LINK_LAYER_ETHERNET) {
Mark Bloch8e6efa32017-11-06 12:22:13 +00005714 err = mlx5_ib_stage_common_roce_init(dev, port_num);
Achiad Shochatfc24fc52015-12-23 18:47:17 +02005715 if (err)
Mark Bloch16c19752018-01-01 13:06:58 +02005716 return err;
Mark Bloch8e6efa32017-11-06 12:22:13 +00005717
5718 err = mlx5_enable_eth(dev, port_num);
5719 if (err)
5720 goto cleanup;
Achiad Shochatfc24fc52015-12-23 18:47:17 +02005721 }
5722
Mark Bloch16c19752018-01-01 13:06:58 +02005723 return 0;
Mark Bloch8e6efa32017-11-06 12:22:13 +00005724cleanup:
5725 mlx5_ib_stage_common_roce_cleanup(dev);
5726
5727 return err;
Mark Bloch16c19752018-01-01 13:06:58 +02005728}
Eli Cohene126ba92013-07-07 17:25:49 +03005729
Mark Bloch16c19752018-01-01 13:06:58 +02005730static void mlx5_ib_stage_roce_cleanup(struct mlx5_ib_dev *dev)
5731{
5732 struct mlx5_core_dev *mdev = dev->mdev;
5733 enum rdma_link_layer ll;
5734 int port_type_cap;
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005735 u8 port_num;
Eli Cohene126ba92013-07-07 17:25:49 +03005736
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005737 port_num = mlx5_core_native_port_num(dev->mdev) - 1;
Mark Bloch16c19752018-01-01 13:06:58 +02005738 port_type_cap = MLX5_CAP_GEN(mdev, port_type);
5739 ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);
5740
5741 if (ll == IB_LINK_LAYER_ETHERNET) {
5742 mlx5_disable_eth(dev);
Mark Bloch8e6efa32017-11-06 12:22:13 +00005743 mlx5_ib_stage_common_roce_cleanup(dev);
Kamal Heib45bded22017-01-18 14:10:32 +02005744 }
Mark Bloch16c19752018-01-01 13:06:58 +02005745}
Haggai Eran6aec21f2014-12-11 17:04:23 +02005746
Mark Blochb5ca15a2018-01-23 11:16:30 +00005747int mlx5_ib_stage_dev_res_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005748{
5749 return create_dev_resources(&dev->devr);
5750}
Parav Pandit4a2da0b2017-05-30 10:05:15 +03005751
Mark Blochb5ca15a2018-01-23 11:16:30 +00005752void mlx5_ib_stage_dev_res_cleanup(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005753{
5754 destroy_dev_resources(&dev->devr);
5755}
5756
5757static int mlx5_ib_stage_odp_init(struct mlx5_ib_dev *dev)
5758{
Mark Bloch07321b32018-01-01 13:07:00 +02005759 mlx5_ib_internal_fill_odp_caps(dev);
5760
Mark Bloch16c19752018-01-01 13:06:58 +02005761 return mlx5_ib_odp_init_one(dev);
5762}
5763
Mark Blochb5ca15a2018-01-23 11:16:30 +00005764int mlx5_ib_stage_counters_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005765{
Mark Bloch5e1e7612018-01-01 13:07:01 +02005766 if (MLX5_CAP_GEN(dev->mdev, max_qp_cnt)) {
5767 dev->ib_dev.get_hw_stats = mlx5_ib_get_hw_stats;
5768 dev->ib_dev.alloc_hw_stats = mlx5_ib_alloc_hw_stats;
5769
5770 return mlx5_ib_alloc_counters(dev);
5771 }
Mark Bloch16c19752018-01-01 13:06:58 +02005772
5773 return 0;
5774}
5775
Mark Blochb5ca15a2018-01-23 11:16:30 +00005776void mlx5_ib_stage_counters_cleanup(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005777{
5778 if (MLX5_CAP_GEN(dev->mdev, max_qp_cnt))
5779 mlx5_ib_dealloc_counters(dev);
5780}
5781
5782static int mlx5_ib_stage_cong_debugfs_init(struct mlx5_ib_dev *dev)
5783{
Parav Pandita9e546e2018-01-04 17:25:39 +02005784 return mlx5_ib_init_cong_debugfs(dev,
5785 mlx5_core_native_port_num(dev->mdev) - 1);
Mark Bloch16c19752018-01-01 13:06:58 +02005786}
5787
5788static void mlx5_ib_stage_cong_debugfs_cleanup(struct mlx5_ib_dev *dev)
5789{
Parav Pandita9e546e2018-01-04 17:25:39 +02005790 mlx5_ib_cleanup_cong_debugfs(dev,
5791 mlx5_core_native_port_num(dev->mdev) - 1);
Mark Bloch16c19752018-01-01 13:06:58 +02005792}
5793
5794static int mlx5_ib_stage_uar_init(struct mlx5_ib_dev *dev)
5795{
Eli Cohen5fe9dec2017-01-03 23:55:25 +02005796 dev->mdev->priv.uar = mlx5_get_uars_page(dev->mdev);
Leon Romanovsky444261c2018-04-23 17:01:56 +03005797 return PTR_ERR_OR_ZERO(dev->mdev->priv.uar);
Mark Bloch16c19752018-01-01 13:06:58 +02005798}
5799
5800static void mlx5_ib_stage_uar_cleanup(struct mlx5_ib_dev *dev)
5801{
5802 mlx5_put_uars_page(dev->mdev, dev->mdev->priv.uar);
5803}
5804
Mark Blochb5ca15a2018-01-23 11:16:30 +00005805int mlx5_ib_stage_bfrag_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005806{
5807 int err;
Eli Cohen5fe9dec2017-01-03 23:55:25 +02005808
5809 err = mlx5_alloc_bfreg(dev->mdev, &dev->bfreg, false, false);
5810 if (err)
Mark Bloch16c19752018-01-01 13:06:58 +02005811 return err;
Eli Cohen5fe9dec2017-01-03 23:55:25 +02005812
5813 err = mlx5_alloc_bfreg(dev->mdev, &dev->fp_bfreg, false, true);
5814 if (err)
Mark Bloch16c19752018-01-01 13:06:58 +02005815 mlx5_free_bfreg(dev->mdev, &dev->fp_bfreg);
Eli Cohen5fe9dec2017-01-03 23:55:25 +02005816
Mark Bloch16c19752018-01-01 13:06:58 +02005817 return err;
5818}
Mark Bloch0837e862016-06-17 15:10:55 +03005819
Mark Blochb5ca15a2018-01-23 11:16:30 +00005820void mlx5_ib_stage_bfrag_cleanup(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005821{
5822 mlx5_free_bfreg(dev->mdev, &dev->fp_bfreg);
5823 mlx5_free_bfreg(dev->mdev, &dev->bfreg);
5824}
Eli Cohene126ba92013-07-07 17:25:49 +03005825
Matan Barak8c846602018-03-28 09:27:41 +03005826static int mlx5_ib_stage_populate_specs(struct mlx5_ib_dev *dev)
5827{
5828 return populate_specs_root(dev);
5829}
5830
Mark Blochb5ca15a2018-01-23 11:16:30 +00005831int mlx5_ib_stage_ib_reg_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005832{
5833 return ib_register_device(&dev->ib_dev, NULL);
5834}
5835
Matan Barak8c846602018-03-28 09:27:41 +03005836static void mlx5_ib_stage_depopulate_specs(struct mlx5_ib_dev *dev)
5837{
5838 depopulate_specs_root(dev);
5839}
5840
David S. Miller03fe2de2018-03-23 11:24:57 -04005841void mlx5_ib_stage_pre_ib_reg_umr_cleanup(struct mlx5_ib_dev *dev)
Mark Bloch42cea832018-03-14 09:14:15 +02005842{
5843 destroy_umrc_res(dev);
5844}
5845
Mark Blochb5ca15a2018-01-23 11:16:30 +00005846void mlx5_ib_stage_ib_reg_cleanup(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005847{
5848 ib_unregister_device(&dev->ib_dev);
5849}
5850
David S. Miller03fe2de2018-03-23 11:24:57 -04005851int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005852{
5853 return create_umr_res(dev);
5854}
5855
Mark Bloch16c19752018-01-01 13:06:58 +02005856static int mlx5_ib_stage_delay_drop_init(struct mlx5_ib_dev *dev)
5857{
Maor Gottlieb03404e82017-05-30 10:29:13 +03005858 init_delay_drop(dev);
5859
Mark Bloch16c19752018-01-01 13:06:58 +02005860 return 0;
5861}
5862
5863static void mlx5_ib_stage_delay_drop_cleanup(struct mlx5_ib_dev *dev)
5864{
5865 cancel_delay_drop(dev);
5866}
5867
Mark Blochb5ca15a2018-01-23 11:16:30 +00005868int mlx5_ib_stage_class_attr_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005869{
5870 int err;
5871 int i;
5872
Eli Cohene126ba92013-07-07 17:25:49 +03005873 for (i = 0; i < ARRAY_SIZE(mlx5_class_attributes); i++) {
Wei Yongjun281d1a92013-07-30 07:54:26 +08005874 err = device_create_file(&dev->ib_dev.dev,
5875 mlx5_class_attributes[i]);
5876 if (err)
Mark Bloch16c19752018-01-01 13:06:58 +02005877 return err;
Eli Cohene126ba92013-07-07 17:25:49 +03005878 }
5879
Mark Bloch16c19752018-01-01 13:06:58 +02005880 return 0;
5881}
5882
Mark Blochfc385b72018-01-16 14:34:48 +00005883static int mlx5_ib_stage_rep_reg_init(struct mlx5_ib_dev *dev)
5884{
5885 mlx5_ib_register_vport_reps(dev);
5886
5887 return 0;
5888}
5889
5890static void mlx5_ib_stage_rep_reg_cleanup(struct mlx5_ib_dev *dev)
5891{
5892 mlx5_ib_unregister_vport_reps(dev);
5893}
5894
Mark Blochb5ca15a2018-01-23 11:16:30 +00005895void __mlx5_ib_remove(struct mlx5_ib_dev *dev,
5896 const struct mlx5_ib_profile *profile,
5897 int stage)
Mark Bloch16c19752018-01-01 13:06:58 +02005898{
5899 /* Number of stages to cleanup */
5900 while (stage) {
5901 stage--;
5902 if (profile->stage[stage].cleanup)
5903 profile->stage[stage].cleanup(dev);
5904 }
5905
5906 ib_dealloc_device((struct ib_device *)dev);
5907}
5908
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005909static void *mlx5_ib_add_slave_port(struct mlx5_core_dev *mdev, u8 port_num);
5910
Mark Blochb5ca15a2018-01-23 11:16:30 +00005911void *__mlx5_ib_add(struct mlx5_ib_dev *dev,
5912 const struct mlx5_ib_profile *profile)
Mark Bloch16c19752018-01-01 13:06:58 +02005913{
Mark Bloch16c19752018-01-01 13:06:58 +02005914 int err;
5915 int i;
5916
5917 printk_once(KERN_INFO "%s", mlx5_version);
5918
Mark Bloch16c19752018-01-01 13:06:58 +02005919 for (i = 0; i < MLX5_IB_STAGE_MAX; i++) {
5920 if (profile->stage[i].init) {
5921 err = profile->stage[i].init(dev);
5922 if (err)
5923 goto err_out;
5924 }
5925 }
5926
5927 dev->profile = profile;
Eli Cohene126ba92013-07-07 17:25:49 +03005928 dev->ib_active = true;
5929
Jack Morgenstein9603b612014-07-28 23:30:22 +03005930 return dev;
Eli Cohene126ba92013-07-07 17:25:49 +03005931
Mark Bloch16c19752018-01-01 13:06:58 +02005932err_out:
5933 __mlx5_ib_remove(dev, profile, i);
Eli Cohene126ba92013-07-07 17:25:49 +03005934
Jack Morgenstein9603b612014-07-28 23:30:22 +03005935 return NULL;
Eli Cohene126ba92013-07-07 17:25:49 +03005936}
5937
Mark Bloch16c19752018-01-01 13:06:58 +02005938static const struct mlx5_ib_profile pf_profile = {
5939 STAGE_CREATE(MLX5_IB_STAGE_INIT,
5940 mlx5_ib_stage_init_init,
5941 mlx5_ib_stage_init_cleanup),
Mark Bloch9a4ca382018-01-16 14:42:35 +00005942 STAGE_CREATE(MLX5_IB_STAGE_FLOW_DB,
5943 mlx5_ib_stage_flow_db_init,
5944 mlx5_ib_stage_flow_db_cleanup),
Mark Bloch16c19752018-01-01 13:06:58 +02005945 STAGE_CREATE(MLX5_IB_STAGE_CAPS,
5946 mlx5_ib_stage_caps_init,
5947 NULL),
Mark Bloch8e6efa32017-11-06 12:22:13 +00005948 STAGE_CREATE(MLX5_IB_STAGE_NON_DEFAULT_CB,
5949 mlx5_ib_stage_non_default_cb,
5950 NULL),
Mark Bloch16c19752018-01-01 13:06:58 +02005951 STAGE_CREATE(MLX5_IB_STAGE_ROCE,
5952 mlx5_ib_stage_roce_init,
5953 mlx5_ib_stage_roce_cleanup),
5954 STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,
5955 mlx5_ib_stage_dev_res_init,
5956 mlx5_ib_stage_dev_res_cleanup),
5957 STAGE_CREATE(MLX5_IB_STAGE_ODP,
5958 mlx5_ib_stage_odp_init,
Mark Bloch3cc297d2018-01-01 13:07:03 +02005959 NULL),
Mark Bloch16c19752018-01-01 13:06:58 +02005960 STAGE_CREATE(MLX5_IB_STAGE_COUNTERS,
5961 mlx5_ib_stage_counters_init,
5962 mlx5_ib_stage_counters_cleanup),
5963 STAGE_CREATE(MLX5_IB_STAGE_CONG_DEBUGFS,
5964 mlx5_ib_stage_cong_debugfs_init,
5965 mlx5_ib_stage_cong_debugfs_cleanup),
5966 STAGE_CREATE(MLX5_IB_STAGE_UAR,
5967 mlx5_ib_stage_uar_init,
5968 mlx5_ib_stage_uar_cleanup),
5969 STAGE_CREATE(MLX5_IB_STAGE_BFREG,
5970 mlx5_ib_stage_bfrag_init,
5971 mlx5_ib_stage_bfrag_cleanup),
Mark Bloch42cea832018-03-14 09:14:15 +02005972 STAGE_CREATE(MLX5_IB_STAGE_PRE_IB_REG_UMR,
5973 NULL,
5974 mlx5_ib_stage_pre_ib_reg_umr_cleanup),
Matan Barak8c846602018-03-28 09:27:41 +03005975 STAGE_CREATE(MLX5_IB_STAGE_SPECS,
5976 mlx5_ib_stage_populate_specs,
5977 mlx5_ib_stage_depopulate_specs),
Mark Bloch16c19752018-01-01 13:06:58 +02005978 STAGE_CREATE(MLX5_IB_STAGE_IB_REG,
5979 mlx5_ib_stage_ib_reg_init,
5980 mlx5_ib_stage_ib_reg_cleanup),
Mark Bloch42cea832018-03-14 09:14:15 +02005981 STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR,
5982 mlx5_ib_stage_post_ib_reg_umr_init,
5983 NULL),
Mark Bloch16c19752018-01-01 13:06:58 +02005984 STAGE_CREATE(MLX5_IB_STAGE_DELAY_DROP,
5985 mlx5_ib_stage_delay_drop_init,
5986 mlx5_ib_stage_delay_drop_cleanup),
5987 STAGE_CREATE(MLX5_IB_STAGE_CLASS_ATTR,
5988 mlx5_ib_stage_class_attr_init,
5989 NULL),
Mark Bloch16c19752018-01-01 13:06:58 +02005990};
5991
Mark Blochb5ca15a2018-01-23 11:16:30 +00005992static const struct mlx5_ib_profile nic_rep_profile = {
5993 STAGE_CREATE(MLX5_IB_STAGE_INIT,
5994 mlx5_ib_stage_init_init,
5995 mlx5_ib_stage_init_cleanup),
5996 STAGE_CREATE(MLX5_IB_STAGE_FLOW_DB,
5997 mlx5_ib_stage_flow_db_init,
5998 mlx5_ib_stage_flow_db_cleanup),
5999 STAGE_CREATE(MLX5_IB_STAGE_CAPS,
6000 mlx5_ib_stage_caps_init,
6001 NULL),
6002 STAGE_CREATE(MLX5_IB_STAGE_NON_DEFAULT_CB,
6003 mlx5_ib_stage_rep_non_default_cb,
6004 NULL),
6005 STAGE_CREATE(MLX5_IB_STAGE_ROCE,
6006 mlx5_ib_stage_rep_roce_init,
6007 mlx5_ib_stage_rep_roce_cleanup),
6008 STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,
6009 mlx5_ib_stage_dev_res_init,
6010 mlx5_ib_stage_dev_res_cleanup),
6011 STAGE_CREATE(MLX5_IB_STAGE_COUNTERS,
6012 mlx5_ib_stage_counters_init,
6013 mlx5_ib_stage_counters_cleanup),
6014 STAGE_CREATE(MLX5_IB_STAGE_UAR,
6015 mlx5_ib_stage_uar_init,
6016 mlx5_ib_stage_uar_cleanup),
6017 STAGE_CREATE(MLX5_IB_STAGE_BFREG,
6018 mlx5_ib_stage_bfrag_init,
6019 mlx5_ib_stage_bfrag_cleanup),
David S. Miller03fe2de2018-03-23 11:24:57 -04006020 STAGE_CREATE(MLX5_IB_STAGE_PRE_IB_REG_UMR,
6021 NULL,
6022 mlx5_ib_stage_pre_ib_reg_umr_cleanup),
Matan Barak8c846602018-03-28 09:27:41 +03006023 STAGE_CREATE(MLX5_IB_STAGE_SPECS,
6024 mlx5_ib_stage_populate_specs,
6025 mlx5_ib_stage_depopulate_specs),
Mark Blochb5ca15a2018-01-23 11:16:30 +00006026 STAGE_CREATE(MLX5_IB_STAGE_IB_REG,
6027 mlx5_ib_stage_ib_reg_init,
6028 mlx5_ib_stage_ib_reg_cleanup),
David S. Miller03fe2de2018-03-23 11:24:57 -04006029 STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR,
6030 mlx5_ib_stage_post_ib_reg_umr_init,
6031 NULL),
Mark Blochb5ca15a2018-01-23 11:16:30 +00006032 STAGE_CREATE(MLX5_IB_STAGE_CLASS_ATTR,
6033 mlx5_ib_stage_class_attr_init,
6034 NULL),
6035 STAGE_CREATE(MLX5_IB_STAGE_REP_REG,
6036 mlx5_ib_stage_rep_reg_init,
6037 mlx5_ib_stage_rep_reg_cleanup),
6038};
6039
Daniel Jurgens32f69e42018-01-04 17:25:36 +02006040static void *mlx5_ib_add_slave_port(struct mlx5_core_dev *mdev, u8 port_num)
6041{
6042 struct mlx5_ib_multiport_info *mpi;
6043 struct mlx5_ib_dev *dev;
6044 bool bound = false;
6045 int err;
6046
6047 mpi = kzalloc(sizeof(*mpi), GFP_KERNEL);
6048 if (!mpi)
6049 return NULL;
6050
6051 mpi->mdev = mdev;
6052
6053 err = mlx5_query_nic_vport_system_image_guid(mdev,
6054 &mpi->sys_image_guid);
6055 if (err) {
6056 kfree(mpi);
6057 return NULL;
6058 }
6059
6060 mutex_lock(&mlx5_ib_multiport_mutex);
6061 list_for_each_entry(dev, &mlx5_ib_dev_list, ib_dev_list) {
6062 if (dev->sys_image_guid == mpi->sys_image_guid)
6063 bound = mlx5_ib_bind_slave_port(dev, mpi);
6064
6065 if (bound) {
6066 rdma_roce_rescan_device(&dev->ib_dev);
6067 break;
6068 }
6069 }
6070
6071 if (!bound) {
6072 list_add_tail(&mpi->list, &mlx5_ib_unaffiliated_port_list);
6073 dev_dbg(&mdev->pdev->dev, "no suitable IB device found to bind to, added to unaffiliated list.\n");
6074 } else {
6075 mlx5_ib_dbg(dev, "bound port %u\n", port_num + 1);
6076 }
6077 mutex_unlock(&mlx5_ib_multiport_mutex);
6078
6079 return mpi;
6080}
6081
Mark Bloch16c19752018-01-01 13:06:58 +02006082static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
6083{
Daniel Jurgens32f69e42018-01-04 17:25:36 +02006084 enum rdma_link_layer ll;
Mark Blochb5ca15a2018-01-23 11:16:30 +00006085 struct mlx5_ib_dev *dev;
Daniel Jurgens32f69e42018-01-04 17:25:36 +02006086 int port_type_cap;
6087
Mark Blochb5ca15a2018-01-23 11:16:30 +00006088 printk_once(KERN_INFO "%s", mlx5_version);
6089
Daniel Jurgens32f69e42018-01-04 17:25:36 +02006090 port_type_cap = MLX5_CAP_GEN(mdev, port_type);
6091 ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);
6092
6093 if (mlx5_core_is_mp_slave(mdev) && ll == IB_LINK_LAYER_ETHERNET) {
6094 u8 port_num = mlx5_core_native_port_num(mdev) - 1;
6095
6096 return mlx5_ib_add_slave_port(mdev, port_num);
6097 }
6098
Mark Blochb5ca15a2018-01-23 11:16:30 +00006099 dev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*dev));
6100 if (!dev)
6101 return NULL;
6102
6103 dev->mdev = mdev;
6104 dev->num_ports = max(MLX5_CAP_GEN(mdev, num_ports),
6105 MLX5_CAP_GEN(mdev, num_vhca_ports));
6106
6107 if (MLX5_VPORT_MANAGER(mdev) &&
6108 mlx5_ib_eswitch_mode(mdev->priv.eswitch) == SRIOV_OFFLOADS) {
6109 dev->rep = mlx5_ib_vport_rep(mdev->priv.eswitch, 0);
6110
6111 return __mlx5_ib_add(dev, &nic_rep_profile);
6112 }
6113
6114 return __mlx5_ib_add(dev, &pf_profile);
Mark Bloch16c19752018-01-01 13:06:58 +02006115}
6116
Jack Morgenstein9603b612014-07-28 23:30:22 +03006117static void mlx5_ib_remove(struct mlx5_core_dev *mdev, void *context)
Eli Cohene126ba92013-07-07 17:25:49 +03006118{
Daniel Jurgens32f69e42018-01-04 17:25:36 +02006119 struct mlx5_ib_multiport_info *mpi;
6120 struct mlx5_ib_dev *dev;
Haggai Eran6aec21f2014-12-11 17:04:23 +02006121
Daniel Jurgens32f69e42018-01-04 17:25:36 +02006122 if (mlx5_core_is_mp_slave(mdev)) {
6123 mpi = context;
6124 mutex_lock(&mlx5_ib_multiport_mutex);
6125 if (mpi->ibdev)
6126 mlx5_ib_unbind_slave_port(mpi->ibdev, mpi);
6127 list_del(&mpi->list);
6128 mutex_unlock(&mlx5_ib_multiport_mutex);
6129 return;
6130 }
6131
6132 dev = context;
Mark Bloch16c19752018-01-01 13:06:58 +02006133 __mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);
Eli Cohene126ba92013-07-07 17:25:49 +03006134}
6135
Jack Morgenstein9603b612014-07-28 23:30:22 +03006136static struct mlx5_interface mlx5_ib_interface = {
6137 .add = mlx5_ib_add,
6138 .remove = mlx5_ib_remove,
6139 .event = mlx5_ib_event,
Artemy Kovalyovd9aaed82017-01-02 11:37:46 +02006140#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
6141 .pfault = mlx5_ib_pfault,
6142#endif
Saeed Mahameed64613d942015-04-02 17:07:34 +03006143 .protocol = MLX5_INTERFACE_PROTOCOL_IB,
Eli Cohene126ba92013-07-07 17:25:49 +03006144};
6145
Ilya Lesokhinc44ef992018-03-13 15:18:48 +02006146unsigned long mlx5_ib_get_xlt_emergency_page(void)
6147{
6148 mutex_lock(&xlt_emergency_page_mutex);
6149 return xlt_emergency_page;
6150}
6151
6152void mlx5_ib_put_xlt_emergency_page(void)
6153{
6154 mutex_unlock(&xlt_emergency_page_mutex);
6155}
6156
Eli Cohene126ba92013-07-07 17:25:49 +03006157static int __init mlx5_ib_init(void)
6158{
Haggai Eran6aec21f2014-12-11 17:04:23 +02006159 int err;
6160
Ilya Lesokhinc44ef992018-03-13 15:18:48 +02006161 xlt_emergency_page = __get_free_page(GFP_KERNEL);
6162 if (!xlt_emergency_page)
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02006163 return -ENOMEM;
6164
Ilya Lesokhinc44ef992018-03-13 15:18:48 +02006165 mutex_init(&xlt_emergency_page_mutex);
6166
6167 mlx5_ib_event_wq = alloc_ordered_workqueue("mlx5_ib_event_wq", 0);
6168 if (!mlx5_ib_event_wq) {
6169 free_page(xlt_emergency_page);
6170 return -ENOMEM;
6171 }
6172
Artemy Kovalyov81713d32017-01-18 16:58:11 +02006173 mlx5_ib_odp_init();
Jack Morgenstein9603b612014-07-28 23:30:22 +03006174
Haggai Eran6aec21f2014-12-11 17:04:23 +02006175 err = mlx5_register_interface(&mlx5_ib_interface);
Haggai Eran6aec21f2014-12-11 17:04:23 +02006176
6177 return err;
Eli Cohene126ba92013-07-07 17:25:49 +03006178}
6179
6180static void __exit mlx5_ib_cleanup(void)
6181{
Jack Morgenstein9603b612014-07-28 23:30:22 +03006182 mlx5_unregister_interface(&mlx5_ib_interface);
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02006183 destroy_workqueue(mlx5_ib_event_wq);
Ilya Lesokhinc44ef992018-03-13 15:18:48 +02006184 mutex_destroy(&xlt_emergency_page_mutex);
6185 free_page(xlt_emergency_page);
Eli Cohene126ba92013-07-07 17:25:49 +03006186}
6187
6188module_init(mlx5_ib_init);
6189module_exit(mlx5_ib_cleanup);