blob: 31295e39896c994e6eaf18b342df14161722ac80 [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>
Guy Levi37aa5c32016-04-27 16:49:50 +030041#if defined(CONFIG_X86)
42#include <asm/pat.h>
43#endif
Eli Cohene126ba92013-07-07 17:25:49 +030044#include <linux/sched.h>
Ingo Molnar6e84f312017-02-08 18:51:29 +010045#include <linux/sched/mm.h>
Ingo Molnar0881e7b2017-02-05 15:30:50 +010046#include <linux/sched/task.h>
Maor Gottlieb7c2344c2016-06-17 14:56:44 +030047#include <linux/delay.h>
Eli Cohene126ba92013-07-07 17:25:49 +030048#include <rdma/ib_user_verbs.h>
Achiad Shochat3f89a642015-12-23 18:47:21 +020049#include <rdma/ib_addr.h>
Achiad Shochat2811ba52015-12-23 18:47:24 +020050#include <rdma/ib_cache.h>
Achiad Shochatada68c32016-02-22 18:17:23 +020051#include <linux/mlx5/port.h>
Majd Dibbiny1b5daf12015-06-04 19:30:46 +030052#include <linux/mlx5/vport.h>
Pravin Shedge72c7fe92017-12-06 22:19:39 +053053#include <linux/mlx5/fs.h>
Aviad Yehezkel802c2122018-03-28 09:27:53 +030054#include <linux/mlx5/fs_helpers.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;
Mark Blochbcf87f12018-01-16 15:02:36 +0000182 } else if (ndev->dev.parent == &ibdev->mdev->pdev->dev) {
183 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 Pandit414448d2018-04-01 15:08:24 +0300513static int mlx5_ib_add_gid(const union ib_gid *gid,
Achiad Shochat3cca2602015-12-23 18:47:23 +0200514 const struct ib_gid_attr *attr,
515 __always_unused void **context)
516{
Parav Pandit414448d2018-04-01 15:08:24 +0300517 return set_roce_addr(to_mdev(attr->device), attr->port_num,
518 attr->index, gid, attr);
Achiad Shochat3cca2602015-12-23 18:47:23 +0200519}
520
Parav Pandit414448d2018-04-01 15:08:24 +0300521static int mlx5_ib_del_gid(const struct ib_gid_attr *attr,
522 __always_unused void **context)
Achiad Shochat3cca2602015-12-23 18:47:23 +0200523{
Parav Pandit414448d2018-04-01 15:08:24 +0300524 return set_roce_addr(to_mdev(attr->device), attr->port_num,
525 attr->index, NULL, NULL);
Achiad Shochat3cca2602015-12-23 18:47:23 +0200526}
527
Achiad Shochat2811ba52015-12-23 18:47:24 +0200528__be16 mlx5_get_roce_udp_sport(struct mlx5_ib_dev *dev, u8 port_num,
529 int index)
530{
531 struct ib_gid_attr attr;
532 union ib_gid gid;
533
534 if (ib_get_cached_gid(&dev->ib_dev, port_num, index, &gid, &attr))
535 return 0;
536
Achiad Shochat2811ba52015-12-23 18:47:24 +0200537 dev_put(attr.ndev);
538
539 if (attr.gid_type != IB_GID_TYPE_ROCE_UDP_ENCAP)
540 return 0;
541
542 return cpu_to_be16(MLX5_CAP_ROCE(dev->mdev, r_roce_min_src_udp_port));
543}
544
Majd Dibbinyed884512017-01-18 14:10:35 +0200545int mlx5_get_roce_gid_type(struct mlx5_ib_dev *dev, u8 port_num,
546 int index, enum ib_gid_type *gid_type)
547{
548 struct ib_gid_attr attr;
549 union ib_gid gid;
550 int ret;
551
552 ret = ib_get_cached_gid(&dev->ib_dev, port_num, index, &gid, &attr);
553 if (ret)
554 return ret;
555
Majd Dibbinyed884512017-01-18 14:10:35 +0200556 dev_put(attr.ndev);
557
558 *gid_type = attr.gid_type;
559
560 return 0;
561}
562
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300563static int mlx5_use_mad_ifc(struct mlx5_ib_dev *dev)
564{
Noa Osherovich7fae6652016-09-12 19:16:23 +0300565 if (MLX5_CAP_GEN(dev->mdev, port_type) == MLX5_CAP_PORT_TYPE_IB)
566 return !MLX5_CAP_GEN(dev->mdev, ib_virt);
567 return 0;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300568}
569
570enum {
571 MLX5_VPORT_ACCESS_METHOD_MAD,
572 MLX5_VPORT_ACCESS_METHOD_HCA,
573 MLX5_VPORT_ACCESS_METHOD_NIC,
574};
575
576static int mlx5_get_vport_access_method(struct ib_device *ibdev)
577{
578 if (mlx5_use_mad_ifc(to_mdev(ibdev)))
579 return MLX5_VPORT_ACCESS_METHOD_MAD;
580
Achiad Shochatebd61f62015-12-23 18:47:16 +0200581 if (mlx5_ib_port_link_layer(ibdev, 1) ==
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300582 IB_LINK_LAYER_ETHERNET)
583 return MLX5_VPORT_ACCESS_METHOD_NIC;
584
585 return MLX5_VPORT_ACCESS_METHOD_HCA;
586}
587
Eran Ben Elishada7525d2015-12-14 16:34:10 +0200588static void get_atomic_caps(struct mlx5_ib_dev *dev,
Moni Shoua776a3902018-01-02 16:19:33 +0200589 u8 atomic_size_qp,
Eran Ben Elishada7525d2015-12-14 16:34:10 +0200590 struct ib_device_attr *props)
591{
592 u8 tmp;
593 u8 atomic_operations = MLX5_CAP_ATOMIC(dev->mdev, atomic_operations);
Eran Ben Elishada7525d2015-12-14 16:34:10 +0200594 u8 atomic_req_8B_endianness_mode =
Or Gerlitzbd108382017-05-28 15:24:17 +0300595 MLX5_CAP_ATOMIC(dev->mdev, atomic_req_8B_endianness_mode);
Eran Ben Elishada7525d2015-12-14 16:34:10 +0200596
597 /* Check if HW supports 8 bytes standard atomic operations and capable
598 * of host endianness respond
599 */
600 tmp = MLX5_ATOMIC_OPS_CMP_SWAP | MLX5_ATOMIC_OPS_FETCH_ADD;
601 if (((atomic_operations & tmp) == tmp) &&
602 (atomic_size_qp & MLX5_ATOMIC_SIZE_QP_8BYTES) &&
603 (atomic_req_8B_endianness_mode)) {
604 props->atomic_cap = IB_ATOMIC_HCA;
605 } else {
606 props->atomic_cap = IB_ATOMIC_NONE;
607 }
608}
609
Moni Shoua776a3902018-01-02 16:19:33 +0200610static void get_atomic_caps_qp(struct mlx5_ib_dev *dev,
611 struct ib_device_attr *props)
612{
613 u8 atomic_size_qp = MLX5_CAP_ATOMIC(dev->mdev, atomic_size_qp);
614
615 get_atomic_caps(dev, atomic_size_qp, props);
616}
617
618static void get_atomic_caps_dc(struct mlx5_ib_dev *dev,
619 struct ib_device_attr *props)
620{
621 u8 atomic_size_qp = MLX5_CAP_ATOMIC(dev->mdev, atomic_size_dc);
622
623 get_atomic_caps(dev, atomic_size_qp, props);
624}
625
626bool mlx5_ib_dc_atomic_is_supported(struct mlx5_ib_dev *dev)
627{
628 struct ib_device_attr props = {};
629
630 get_atomic_caps_dc(dev, &props);
631 return (props.atomic_cap == IB_ATOMIC_HCA) ? true : false;
632}
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300633static int mlx5_query_system_image_guid(struct ib_device *ibdev,
634 __be64 *sys_image_guid)
635{
636 struct mlx5_ib_dev *dev = to_mdev(ibdev);
637 struct mlx5_core_dev *mdev = dev->mdev;
638 u64 tmp;
639 int err;
640
641 switch (mlx5_get_vport_access_method(ibdev)) {
642 case MLX5_VPORT_ACCESS_METHOD_MAD:
643 return mlx5_query_mad_ifc_system_image_guid(ibdev,
644 sys_image_guid);
645
646 case MLX5_VPORT_ACCESS_METHOD_HCA:
647 err = mlx5_query_hca_vport_system_image_guid(mdev, &tmp);
Achiad Shochat3f89a642015-12-23 18:47:21 +0200648 break;
649
650 case MLX5_VPORT_ACCESS_METHOD_NIC:
651 err = mlx5_query_nic_vport_system_image_guid(mdev, &tmp);
652 break;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300653
654 default:
655 return -EINVAL;
656 }
Achiad Shochat3f89a642015-12-23 18:47:21 +0200657
658 if (!err)
659 *sys_image_guid = cpu_to_be64(tmp);
660
661 return err;
662
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300663}
664
665static int mlx5_query_max_pkeys(struct ib_device *ibdev,
666 u16 *max_pkeys)
667{
668 struct mlx5_ib_dev *dev = to_mdev(ibdev);
669 struct mlx5_core_dev *mdev = dev->mdev;
670
671 switch (mlx5_get_vport_access_method(ibdev)) {
672 case MLX5_VPORT_ACCESS_METHOD_MAD:
673 return mlx5_query_mad_ifc_max_pkeys(ibdev, max_pkeys);
674
675 case MLX5_VPORT_ACCESS_METHOD_HCA:
676 case MLX5_VPORT_ACCESS_METHOD_NIC:
677 *max_pkeys = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(mdev,
678 pkey_table_size));
679 return 0;
680
681 default:
682 return -EINVAL;
683 }
684}
685
686static int mlx5_query_vendor_id(struct ib_device *ibdev,
687 u32 *vendor_id)
688{
689 struct mlx5_ib_dev *dev = to_mdev(ibdev);
690
691 switch (mlx5_get_vport_access_method(ibdev)) {
692 case MLX5_VPORT_ACCESS_METHOD_MAD:
693 return mlx5_query_mad_ifc_vendor_id(ibdev, vendor_id);
694
695 case MLX5_VPORT_ACCESS_METHOD_HCA:
696 case MLX5_VPORT_ACCESS_METHOD_NIC:
697 return mlx5_core_query_vendor_id(dev->mdev, vendor_id);
698
699 default:
700 return -EINVAL;
701 }
702}
703
704static int mlx5_query_node_guid(struct mlx5_ib_dev *dev,
705 __be64 *node_guid)
706{
707 u64 tmp;
708 int err;
709
710 switch (mlx5_get_vport_access_method(&dev->ib_dev)) {
711 case MLX5_VPORT_ACCESS_METHOD_MAD:
712 return mlx5_query_mad_ifc_node_guid(dev, node_guid);
713
714 case MLX5_VPORT_ACCESS_METHOD_HCA:
715 err = mlx5_query_hca_vport_node_guid(dev->mdev, &tmp);
Achiad Shochat3f89a642015-12-23 18:47:21 +0200716 break;
717
718 case MLX5_VPORT_ACCESS_METHOD_NIC:
719 err = mlx5_query_nic_vport_node_guid(dev->mdev, &tmp);
720 break;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300721
722 default:
723 return -EINVAL;
724 }
Achiad Shochat3f89a642015-12-23 18:47:21 +0200725
726 if (!err)
727 *node_guid = cpu_to_be64(tmp);
728
729 return err;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300730}
731
732struct mlx5_reg_node_desc {
Yuval Shaiabd99fde2016-08-25 10:57:07 -0700733 u8 desc[IB_DEVICE_NODE_DESC_MAX];
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300734};
735
736static int mlx5_query_node_desc(struct mlx5_ib_dev *dev, char *node_desc)
737{
738 struct mlx5_reg_node_desc in;
739
740 if (mlx5_use_mad_ifc(dev))
741 return mlx5_query_mad_ifc_node_desc(dev, node_desc);
742
743 memset(&in, 0, sizeof(in));
744
745 return mlx5_core_access_reg(dev->mdev, &in, sizeof(in), node_desc,
746 sizeof(struct mlx5_reg_node_desc),
747 MLX5_REG_NODE_DESC, 0, 0);
748}
749
Eli Cohene126ba92013-07-07 17:25:49 +0300750static int mlx5_ib_query_device(struct ib_device *ibdev,
Matan Barak2528e332015-06-11 16:35:25 +0300751 struct ib_device_attr *props,
752 struct ib_udata *uhw)
Eli Cohene126ba92013-07-07 17:25:49 +0300753{
754 struct mlx5_ib_dev *dev = to_mdev(ibdev);
Saeed Mahameed938fe832015-05-28 22:28:41 +0300755 struct mlx5_core_dev *mdev = dev->mdev;
Eli Cohene126ba92013-07-07 17:25:49 +0300756 int err = -ENOMEM;
Eli Cohen288c01b2016-10-27 16:36:45 +0300757 int max_sq_desc;
Eli Cohene126ba92013-07-07 17:25:49 +0300758 int max_rq_sg;
759 int max_sq_sg;
Sagi Grimberge0238a62015-07-21 14:40:12 +0300760 u64 min_page_size = 1ull << MLX5_CAP_GEN(mdev, log_pg_sz);
Daniel Jurgens85c7c012018-01-04 17:25:43 +0200761 bool raw_support = !mlx5_core_mp_enabled(mdev);
Bodong Wang402ca532016-06-17 15:02:20 +0300762 struct mlx5_ib_query_device_resp resp = {};
763 size_t resp_len;
764 u64 max_tso;
Eli Cohene126ba92013-07-07 17:25:49 +0300765
Bodong Wang402ca532016-06-17 15:02:20 +0300766 resp_len = sizeof(resp.comp_mask) + sizeof(resp.response_length);
767 if (uhw->outlen && uhw->outlen < resp_len)
768 return -EINVAL;
769 else
770 resp.response_length = resp_len;
771
772 if (uhw->inlen && !ib_is_udata_cleared(uhw, 0, uhw->inlen))
Matan Barak2528e332015-06-11 16:35:25 +0300773 return -EINVAL;
774
Eli Cohene126ba92013-07-07 17:25:49 +0300775 memset(props, 0, sizeof(*props));
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300776 err = mlx5_query_system_image_guid(ibdev,
777 &props->sys_image_guid);
778 if (err)
779 return err;
780
781 err = mlx5_query_max_pkeys(ibdev, &props->max_pkeys);
782 if (err)
783 return err;
784
785 err = mlx5_query_vendor_id(ibdev, &props->vendor_id);
786 if (err)
787 return err;
Eli Cohene126ba92013-07-07 17:25:49 +0300788
Jack Morgenstein9603b612014-07-28 23:30:22 +0300789 props->fw_ver = ((u64)fw_rev_maj(dev->mdev) << 32) |
790 (fw_rev_min(dev->mdev) << 16) |
791 fw_rev_sub(dev->mdev);
Eli Cohene126ba92013-07-07 17:25:49 +0300792 props->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT |
793 IB_DEVICE_PORT_ACTIVE_EVENT |
794 IB_DEVICE_SYS_IMAGE_GUID |
Eli Cohen1a4c3a32014-02-06 17:41:25 +0200795 IB_DEVICE_RC_RNR_NAK_GEN;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300796
797 if (MLX5_CAP_GEN(mdev, pkv))
Eli Cohene126ba92013-07-07 17:25:49 +0300798 props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300799 if (MLX5_CAP_GEN(mdev, qkv))
Eli Cohene126ba92013-07-07 17:25:49 +0300800 props->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300801 if (MLX5_CAP_GEN(mdev, apm))
Eli Cohene126ba92013-07-07 17:25:49 +0300802 props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300803 if (MLX5_CAP_GEN(mdev, xrc))
Eli Cohene126ba92013-07-07 17:25:49 +0300804 props->device_cap_flags |= IB_DEVICE_XRC;
Matan Barakd2370e02016-02-29 18:05:30 +0200805 if (MLX5_CAP_GEN(mdev, imaicl)) {
806 props->device_cap_flags |= IB_DEVICE_MEM_WINDOW |
807 IB_DEVICE_MEM_WINDOW_TYPE_2B;
808 props->max_mw = 1 << MLX5_CAP_GEN(mdev, log_max_mkey);
Sagi Grimbergb005d312016-02-29 19:07:33 +0200809 /* We support 'Gappy' memory registration too */
810 props->device_cap_flags |= IB_DEVICE_SG_GAPS_REG;
Matan Barakd2370e02016-02-29 18:05:30 +0200811 }
Eli Cohene126ba92013-07-07 17:25:49 +0300812 props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300813 if (MLX5_CAP_GEN(mdev, sho)) {
Sagi Grimberg2dea9092014-02-23 14:19:13 +0200814 props->device_cap_flags |= IB_DEVICE_SIGNATURE_HANDOVER;
815 /* At this stage no support for signature handover */
816 props->sig_prot_cap = IB_PROT_T10DIF_TYPE_1 |
817 IB_PROT_T10DIF_TYPE_2 |
818 IB_PROT_T10DIF_TYPE_3;
819 props->sig_guard_cap = IB_GUARD_T10DIF_CRC |
820 IB_GUARD_T10DIF_CSUM;
821 }
Saeed Mahameed938fe832015-05-28 22:28:41 +0300822 if (MLX5_CAP_GEN(mdev, block_lb_mc))
Eli Cohenf360d882014-04-02 00:10:16 +0300823 props->device_cap_flags |= IB_DEVICE_BLOCK_MULTICAST_LOOPBACK;
Eli Cohene126ba92013-07-07 17:25:49 +0300824
Daniel Jurgens85c7c012018-01-04 17:25:43 +0200825 if (MLX5_CAP_GEN(dev->mdev, eth_net_offloads) && raw_support) {
Noa Osheroviche8161332017-01-18 15:40:01 +0200826 if (MLX5_CAP_ETH(mdev, csum_cap)) {
827 /* Legacy bit to support old userspace libraries */
Bodong Wang88115fe2015-12-18 13:53:20 +0200828 props->device_cap_flags |= IB_DEVICE_RAW_IP_CSUM;
Noa Osheroviche8161332017-01-18 15:40:01 +0200829 props->raw_packet_caps |= IB_RAW_PACKET_CAP_IP_CSUM;
830 }
831
832 if (MLX5_CAP_ETH(dev->mdev, vlan_cap))
833 props->raw_packet_caps |=
834 IB_RAW_PACKET_CAP_CVLAN_STRIPPING;
Bodong Wang88115fe2015-12-18 13:53:20 +0200835
Bodong Wang402ca532016-06-17 15:02:20 +0300836 if (field_avail(typeof(resp), tso_caps, uhw->outlen)) {
837 max_tso = MLX5_CAP_ETH(mdev, max_lso_cap);
838 if (max_tso) {
839 resp.tso_caps.max_tso = 1 << max_tso;
840 resp.tso_caps.supported_qpts |=
841 1 << IB_QPT_RAW_PACKET;
842 resp.response_length += sizeof(resp.tso_caps);
843 }
844 }
Yishai Hadas31f69a82016-08-28 11:28:45 +0300845
846 if (field_avail(typeof(resp), rss_caps, uhw->outlen)) {
847 resp.rss_caps.rx_hash_function =
848 MLX5_RX_HASH_FUNC_TOEPLITZ;
849 resp.rss_caps.rx_hash_fields_mask =
850 MLX5_RX_HASH_SRC_IPV4 |
851 MLX5_RX_HASH_DST_IPV4 |
852 MLX5_RX_HASH_SRC_IPV6 |
853 MLX5_RX_HASH_DST_IPV6 |
854 MLX5_RX_HASH_SRC_PORT_TCP |
855 MLX5_RX_HASH_DST_PORT_TCP |
856 MLX5_RX_HASH_SRC_PORT_UDP |
Maor Gottlieb4e2b53a2017-12-24 14:51:25 +0200857 MLX5_RX_HASH_DST_PORT_UDP |
858 MLX5_RX_HASH_INNER;
Matan Barak2d93fc82018-03-28 09:27:55 +0300859 if (mlx5_accel_ipsec_device_caps(dev->mdev) &
860 MLX5_ACCEL_IPSEC_CAP_DEVICE)
861 resp.rss_caps.rx_hash_fields_mask |=
862 MLX5_RX_HASH_IPSEC_SPI;
Yishai Hadas31f69a82016-08-28 11:28:45 +0300863 resp.response_length += sizeof(resp.rss_caps);
864 }
865 } else {
866 if (field_avail(typeof(resp), tso_caps, uhw->outlen))
867 resp.response_length += sizeof(resp.tso_caps);
868 if (field_avail(typeof(resp), rss_caps, uhw->outlen))
869 resp.response_length += sizeof(resp.rss_caps);
Bodong Wang402ca532016-06-17 15:02:20 +0300870 }
871
Erez Shitritf0313962016-02-21 16:27:17 +0200872 if (MLX5_CAP_GEN(mdev, ipoib_basic_offloads)) {
873 props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
874 props->device_cap_flags |= IB_DEVICE_UD_TSO;
875 }
876
Maor Gottlieb03404e82017-05-30 10:29:13 +0300877 if (MLX5_CAP_GEN(dev->mdev, rq_delay_drop) &&
Daniel Jurgens85c7c012018-01-04 17:25:43 +0200878 MLX5_CAP_GEN(dev->mdev, general_notification_event) &&
879 raw_support)
Maor Gottlieb03404e82017-05-30 10:29:13 +0300880 props->raw_packet_caps |= IB_RAW_PACKET_CAP_DELAY_DROP;
881
Yishai Hadas1d54f892017-06-08 16:15:11 +0300882 if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads) &&
883 MLX5_CAP_IPOIB_ENHANCED(mdev, csum_cap))
884 props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
885
Majd Dibbinycff5a0f2016-04-17 17:19:38 +0300886 if (MLX5_CAP_GEN(dev->mdev, eth_net_offloads) &&
Daniel Jurgens85c7c012018-01-04 17:25:43 +0200887 MLX5_CAP_ETH(dev->mdev, scatter_fcs) &&
888 raw_support) {
Noa Osheroviche8161332017-01-18 15:40:01 +0200889 /* Legacy bit to support old userspace libraries */
Majd Dibbinycff5a0f2016-04-17 17:19:38 +0300890 props->device_cap_flags |= IB_DEVICE_RAW_SCATTER_FCS;
Noa Osheroviche8161332017-01-18 15:40:01 +0200891 props->raw_packet_caps |= IB_RAW_PACKET_CAP_SCATTER_FCS;
892 }
Majd Dibbinycff5a0f2016-04-17 17:19:38 +0300893
Maor Gottliebda6d6ba32016-06-04 15:15:28 +0300894 if (mlx5_get_flow_namespace(dev->mdev, MLX5_FLOW_NAMESPACE_BYPASS))
895 props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING;
896
Noa Osherovichb1383aa2017-10-29 13:59:45 +0200897 if (MLX5_CAP_GEN(mdev, end_pad))
898 props->device_cap_flags |= IB_DEVICE_PCI_WRITE_END_PADDING;
899
Majd Dibbiny1b5daf12015-06-04 19:30:46 +0300900 props->vendor_part_id = mdev->pdev->device;
901 props->hw_ver = mdev->pdev->revision;
Eli Cohene126ba92013-07-07 17:25:49 +0300902
903 props->max_mr_size = ~0ull;
Sagi Grimberge0238a62015-07-21 14:40:12 +0300904 props->page_size_cap = ~(min_page_size - 1);
Saeed Mahameed938fe832015-05-28 22:28:41 +0300905 props->max_qp = 1 << MLX5_CAP_GEN(mdev, log_max_qp);
906 props->max_qp_wr = 1 << MLX5_CAP_GEN(mdev, log_max_qp_sz);
907 max_rq_sg = MLX5_CAP_GEN(mdev, max_wqe_sz_rq) /
908 sizeof(struct mlx5_wqe_data_seg);
Eli Cohen288c01b2016-10-27 16:36:45 +0300909 max_sq_desc = min_t(int, MLX5_CAP_GEN(mdev, max_wqe_sz_sq), 512);
910 max_sq_sg = (max_sq_desc - sizeof(struct mlx5_wqe_ctrl_seg) -
911 sizeof(struct mlx5_wqe_raddr_seg)) /
912 sizeof(struct mlx5_wqe_data_seg);
Eli Cohene126ba92013-07-07 17:25:49 +0300913 props->max_sge = min(max_rq_sg, max_sq_sg);
Sagi Grimberg986ef952016-03-31 19:03:25 +0300914 props->max_sge_rd = MLX5_MAX_SGE_RD;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300915 props->max_cq = 1 << MLX5_CAP_GEN(mdev, log_max_cq);
Leon Romanovsky9f177682016-01-14 08:11:40 +0200916 props->max_cqe = (1 << MLX5_CAP_GEN(mdev, log_max_cq_sz)) - 1;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300917 props->max_mr = 1 << MLX5_CAP_GEN(mdev, log_max_mkey);
918 props->max_pd = 1 << MLX5_CAP_GEN(mdev, log_max_pd);
919 props->max_qp_rd_atom = 1 << MLX5_CAP_GEN(mdev, log_max_ra_req_qp);
920 props->max_qp_init_rd_atom = 1 << MLX5_CAP_GEN(mdev, log_max_ra_res_qp);
921 props->max_srq = 1 << MLX5_CAP_GEN(mdev, log_max_srq);
922 props->max_srq_wr = (1 << MLX5_CAP_GEN(mdev, log_max_srq_sz)) - 1;
923 props->local_ca_ack_delay = MLX5_CAP_GEN(mdev, local_ca_ack_delay);
Eli Cohene126ba92013-07-07 17:25:49 +0300924 props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp;
Eli Cohene126ba92013-07-07 17:25:49 +0300925 props->max_srq_sge = max_rq_sg - 1;
Sagi Grimberg911f4332016-03-03 13:37:51 +0200926 props->max_fast_reg_page_list_len =
927 1 << MLX5_CAP_GEN(mdev, log_max_klm_list_size);
Moni Shoua776a3902018-01-02 16:19:33 +0200928 get_atomic_caps_qp(dev, props);
Eli Cohen81bea282013-09-11 16:35:30 +0300929 props->masked_atomic_cap = IB_ATOMIC_NONE;
Saeed Mahameed938fe832015-05-28 22:28:41 +0300930 props->max_mcast_grp = 1 << MLX5_CAP_GEN(mdev, log_max_mcg);
931 props->max_mcast_qp_attach = MLX5_CAP_GEN(mdev, max_qp_mcg);
Eli Cohene126ba92013-07-07 17:25:49 +0300932 props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *
933 props->max_mcast_grp;
934 props->max_map_per_fmr = INT_MAX; /* no limit in ConnectIB */
Maor Gottlieb86695a62016-10-27 16:36:38 +0300935 props->max_ah = INT_MAX;
Matan Barak7c60bcb2015-12-15 20:30:11 +0200936 props->hca_core_clock = MLX5_CAP_GEN(mdev, device_frequency_khz);
937 props->timestamp_mask = 0x7FFFFFFFFFFFFFFFULL;
Eli Cohene126ba92013-07-07 17:25:49 +0300938
Haggai Eran8cdd3122014-12-11 17:04:20 +0200939#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
Saeed Mahameed938fe832015-05-28 22:28:41 +0300940 if (MLX5_CAP_GEN(mdev, pg))
Haggai Eran8cdd3122014-12-11 17:04:20 +0200941 props->device_cap_flags |= IB_DEVICE_ON_DEMAND_PAGING;
942 props->odp_caps = dev->odp_caps;
943#endif
944
Leon Romanovsky051f2632015-12-20 12:16:11 +0200945 if (MLX5_CAP_GEN(mdev, cd))
946 props->device_cap_flags |= IB_DEVICE_CROSS_CHANNEL;
947
Eli Coheneff901d2016-03-11 22:58:42 +0200948 if (!mlx5_core_is_pf(mdev))
949 props->device_cap_flags |= IB_DEVICE_VIRTUAL_FUNCTION;
950
Yishai Hadas31f69a82016-08-28 11:28:45 +0300951 if (mlx5_ib_port_link_layer(ibdev, 1) ==
Daniel Jurgens85c7c012018-01-04 17:25:43 +0200952 IB_LINK_LAYER_ETHERNET && raw_support) {
Yishai Hadas31f69a82016-08-28 11:28:45 +0300953 props->rss_caps.max_rwq_indirection_tables =
954 1 << MLX5_CAP_GEN(dev->mdev, log_max_rqt);
955 props->rss_caps.max_rwq_indirection_table_size =
956 1 << MLX5_CAP_GEN(dev->mdev, log_max_rqt_size);
957 props->rss_caps.supported_qpts = 1 << IB_QPT_RAW_PACKET;
958 props->max_wq_type_rq =
959 1 << MLX5_CAP_GEN(dev->mdev, log_max_rq);
960 }
961
Artemy Kovalyoveb761892017-08-17 15:52:09 +0300962 if (MLX5_CAP_GEN(mdev, tag_matching)) {
Leon Romanovsky78b1beb2017-09-24 21:46:29 +0300963 props->tm_caps.max_rndv_hdr_size = MLX5_TM_MAX_RNDV_MSG_SIZE;
964 props->tm_caps.max_num_tags =
Artemy Kovalyoveb761892017-08-17 15:52:09 +0300965 (1 << MLX5_CAP_GEN(mdev, log_tag_matching_list_sz)) - 1;
Leon Romanovsky78b1beb2017-09-24 21:46:29 +0300966 props->tm_caps.flags = IB_TM_CAP_RC;
967 props->tm_caps.max_ops =
Artemy Kovalyoveb761892017-08-17 15:52:09 +0300968 1 << MLX5_CAP_GEN(mdev, log_max_qp_sz);
Leon Romanovsky78b1beb2017-09-24 21:46:29 +0300969 props->tm_caps.max_sge = MLX5_TM_MAX_SGE;
Artemy Kovalyoveb761892017-08-17 15:52:09 +0300970 }
971
Yonatan Cohen87ab3f52017-11-13 10:51:18 +0200972 if (MLX5_CAP_GEN(dev->mdev, cq_moderation)) {
973 props->cq_caps.max_cq_moderation_count =
974 MLX5_MAX_CQ_COUNT;
975 props->cq_caps.max_cq_moderation_period =
976 MLX5_MAX_CQ_PERIOD;
977 }
978
Bodong Wang7e43a2a2016-10-31 12:16:44 +0200979 if (field_avail(typeof(resp), cqe_comp_caps, uhw->outlen)) {
980 resp.cqe_comp_caps.max_num =
981 MLX5_CAP_GEN(dev->mdev, cqe_compression) ?
982 MLX5_CAP_GEN(dev->mdev, cqe_compression_max_num) : 0;
983 resp.cqe_comp_caps.supported_format =
984 MLX5_IB_CQE_RES_FORMAT_HASH |
985 MLX5_IB_CQE_RES_FORMAT_CSUM;
986 resp.response_length += sizeof(resp.cqe_comp_caps);
987 }
988
Daniel Jurgens85c7c012018-01-04 17:25:43 +0200989 if (field_avail(typeof(resp), packet_pacing_caps, uhw->outlen) &&
990 raw_support) {
Bodong Wangd9491672016-12-01 13:43:13 +0200991 if (MLX5_CAP_QOS(mdev, packet_pacing) &&
992 MLX5_CAP_GEN(mdev, qos)) {
993 resp.packet_pacing_caps.qp_rate_limit_max =
994 MLX5_CAP_QOS(mdev, packet_pacing_max_rate);
995 resp.packet_pacing_caps.qp_rate_limit_min =
996 MLX5_CAP_QOS(mdev, packet_pacing_min_rate);
997 resp.packet_pacing_caps.supported_qpts |=
998 1 << IB_QPT_RAW_PACKET;
Bodong Wang61147f32018-03-19 15:10:30 +0200999 if (MLX5_CAP_QOS(mdev, packet_pacing_burst_bound) &&
1000 MLX5_CAP_QOS(mdev, packet_pacing_typical_size))
1001 resp.packet_pacing_caps.cap_flags |=
1002 MLX5_IB_PP_SUPPORT_BURST;
Bodong Wangd9491672016-12-01 13:43:13 +02001003 }
1004 resp.response_length += sizeof(resp.packet_pacing_caps);
1005 }
1006
Leon Romanovsky9f885202017-01-02 11:37:39 +02001007 if (field_avail(typeof(resp), mlx5_ib_support_multi_pkt_send_wqes,
1008 uhw->outlen)) {
Bodong Wang795b6092017-08-17 15:52:34 +03001009 if (MLX5_CAP_ETH(mdev, multi_pkt_send_wqe))
1010 resp.mlx5_ib_support_multi_pkt_send_wqes =
1011 MLX5_IB_ALLOW_MPW;
Bodong Wang050da902017-08-17 15:52:35 +03001012
1013 if (MLX5_CAP_ETH(mdev, enhanced_multi_pkt_send_wqe))
1014 resp.mlx5_ib_support_multi_pkt_send_wqes |=
1015 MLX5_IB_SUPPORT_EMPW;
1016
Leon Romanovsky9f885202017-01-02 11:37:39 +02001017 resp.response_length +=
1018 sizeof(resp.mlx5_ib_support_multi_pkt_send_wqes);
1019 }
1020
Guy Levide57f2a2017-10-19 08:25:52 +03001021 if (field_avail(typeof(resp), flags, uhw->outlen)) {
1022 resp.response_length += sizeof(resp.flags);
Guy Levi7a0c8f42017-10-19 08:25:53 +03001023
Guy Levide57f2a2017-10-19 08:25:52 +03001024 if (MLX5_CAP_GEN(mdev, cqe_compression_128))
1025 resp.flags |=
1026 MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_COMP;
Guy Levi7a0c8f42017-10-19 08:25:53 +03001027
1028 if (MLX5_CAP_GEN(mdev, cqe_128_always))
1029 resp.flags |= MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_PAD;
Guy Levide57f2a2017-10-19 08:25:52 +03001030 }
Leon Romanovsky9f885202017-01-02 11:37:39 +02001031
Noa Osherovich96dc3fc2017-08-17 15:52:28 +03001032 if (field_avail(typeof(resp), sw_parsing_caps,
1033 uhw->outlen)) {
1034 resp.response_length += sizeof(resp.sw_parsing_caps);
1035 if (MLX5_CAP_ETH(mdev, swp)) {
1036 resp.sw_parsing_caps.sw_parsing_offloads |=
1037 MLX5_IB_SW_PARSING;
1038
1039 if (MLX5_CAP_ETH(mdev, swp_csum))
1040 resp.sw_parsing_caps.sw_parsing_offloads |=
1041 MLX5_IB_SW_PARSING_CSUM;
1042
1043 if (MLX5_CAP_ETH(mdev, swp_lso))
1044 resp.sw_parsing_caps.sw_parsing_offloads |=
1045 MLX5_IB_SW_PARSING_LSO;
1046
1047 if (resp.sw_parsing_caps.sw_parsing_offloads)
1048 resp.sw_parsing_caps.supported_qpts =
1049 BIT(IB_QPT_RAW_PACKET);
1050 }
1051 }
1052
Daniel Jurgens85c7c012018-01-04 17:25:43 +02001053 if (field_avail(typeof(resp), striding_rq_caps, uhw->outlen) &&
1054 raw_support) {
Noa Osherovichb4f34592017-10-17 18:01:12 +03001055 resp.response_length += sizeof(resp.striding_rq_caps);
1056 if (MLX5_CAP_GEN(mdev, striding_rq)) {
1057 resp.striding_rq_caps.min_single_stride_log_num_of_bytes =
1058 MLX5_MIN_SINGLE_STRIDE_LOG_NUM_BYTES;
1059 resp.striding_rq_caps.max_single_stride_log_num_of_bytes =
1060 MLX5_MAX_SINGLE_STRIDE_LOG_NUM_BYTES;
1061 resp.striding_rq_caps.min_single_wqe_log_num_of_strides =
1062 MLX5_MIN_SINGLE_WQE_LOG_NUM_STRIDES;
1063 resp.striding_rq_caps.max_single_wqe_log_num_of_strides =
1064 MLX5_MAX_SINGLE_WQE_LOG_NUM_STRIDES;
1065 resp.striding_rq_caps.supported_qpts =
1066 BIT(IB_QPT_RAW_PACKET);
1067 }
1068 }
1069
Maor Gottliebf95ef6c2017-10-19 08:25:55 +03001070 if (field_avail(typeof(resp), tunnel_offloads_caps,
1071 uhw->outlen)) {
1072 resp.response_length += sizeof(resp.tunnel_offloads_caps);
1073 if (MLX5_CAP_ETH(mdev, tunnel_stateless_vxlan))
1074 resp.tunnel_offloads_caps |=
1075 MLX5_IB_TUNNELED_OFFLOADS_VXLAN;
1076 if (MLX5_CAP_ETH(mdev, tunnel_stateless_geneve_rx))
1077 resp.tunnel_offloads_caps |=
1078 MLX5_IB_TUNNELED_OFFLOADS_GENEVE;
1079 if (MLX5_CAP_ETH(mdev, tunnel_stateless_gre))
1080 resp.tunnel_offloads_caps |=
1081 MLX5_IB_TUNNELED_OFFLOADS_GRE;
1082 }
1083
Bodong Wang402ca532016-06-17 15:02:20 +03001084 if (uhw->outlen) {
1085 err = ib_copy_to_udata(uhw, &resp, resp.response_length);
1086
1087 if (err)
1088 return err;
1089 }
1090
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001091 return 0;
1092}
Eli Cohene126ba92013-07-07 17:25:49 +03001093
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001094enum mlx5_ib_width {
1095 MLX5_IB_WIDTH_1X = 1 << 0,
1096 MLX5_IB_WIDTH_2X = 1 << 1,
1097 MLX5_IB_WIDTH_4X = 1 << 2,
1098 MLX5_IB_WIDTH_8X = 1 << 3,
1099 MLX5_IB_WIDTH_12X = 1 << 4
1100};
1101
1102static int translate_active_width(struct ib_device *ibdev, u8 active_width,
1103 u8 *ib_width)
1104{
1105 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1106 int err = 0;
1107
1108 if (active_width & MLX5_IB_WIDTH_1X) {
1109 *ib_width = IB_WIDTH_1X;
1110 } else if (active_width & MLX5_IB_WIDTH_2X) {
1111 mlx5_ib_dbg(dev, "active_width %d is not supported by IB spec\n",
1112 (int)active_width);
1113 err = -EINVAL;
1114 } else if (active_width & MLX5_IB_WIDTH_4X) {
1115 *ib_width = IB_WIDTH_4X;
1116 } else if (active_width & MLX5_IB_WIDTH_8X) {
1117 *ib_width = IB_WIDTH_8X;
1118 } else if (active_width & MLX5_IB_WIDTH_12X) {
1119 *ib_width = IB_WIDTH_12X;
1120 } else {
1121 mlx5_ib_dbg(dev, "Invalid active_width %d\n",
1122 (int)active_width);
1123 err = -EINVAL;
1124 }
1125
1126 return err;
1127}
1128
1129static int mlx5_mtu_to_ib_mtu(int mtu)
1130{
1131 switch (mtu) {
1132 case 256: return 1;
1133 case 512: return 2;
1134 case 1024: return 3;
1135 case 2048: return 4;
1136 case 4096: return 5;
1137 default:
1138 pr_warn("invalid mtu\n");
1139 return -1;
1140 }
1141}
1142
1143enum ib_max_vl_num {
1144 __IB_MAX_VL_0 = 1,
1145 __IB_MAX_VL_0_1 = 2,
1146 __IB_MAX_VL_0_3 = 3,
1147 __IB_MAX_VL_0_7 = 4,
1148 __IB_MAX_VL_0_14 = 5,
1149};
1150
1151enum mlx5_vl_hw_cap {
1152 MLX5_VL_HW_0 = 1,
1153 MLX5_VL_HW_0_1 = 2,
1154 MLX5_VL_HW_0_2 = 3,
1155 MLX5_VL_HW_0_3 = 4,
1156 MLX5_VL_HW_0_4 = 5,
1157 MLX5_VL_HW_0_5 = 6,
1158 MLX5_VL_HW_0_6 = 7,
1159 MLX5_VL_HW_0_7 = 8,
1160 MLX5_VL_HW_0_14 = 15
1161};
1162
1163static int translate_max_vl_num(struct ib_device *ibdev, u8 vl_hw_cap,
1164 u8 *max_vl_num)
1165{
1166 switch (vl_hw_cap) {
1167 case MLX5_VL_HW_0:
1168 *max_vl_num = __IB_MAX_VL_0;
1169 break;
1170 case MLX5_VL_HW_0_1:
1171 *max_vl_num = __IB_MAX_VL_0_1;
1172 break;
1173 case MLX5_VL_HW_0_3:
1174 *max_vl_num = __IB_MAX_VL_0_3;
1175 break;
1176 case MLX5_VL_HW_0_7:
1177 *max_vl_num = __IB_MAX_VL_0_7;
1178 break;
1179 case MLX5_VL_HW_0_14:
1180 *max_vl_num = __IB_MAX_VL_0_14;
1181 break;
1182
1183 default:
1184 return -EINVAL;
1185 }
1186
1187 return 0;
1188}
1189
1190static int mlx5_query_hca_port(struct ib_device *ibdev, u8 port,
1191 struct ib_port_attr *props)
1192{
1193 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1194 struct mlx5_core_dev *mdev = dev->mdev;
1195 struct mlx5_hca_vport_context *rep;
Saeed Mahameed046339e2016-04-22 00:33:03 +03001196 u16 max_mtu;
1197 u16 oper_mtu;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001198 int err;
1199 u8 ib_link_width_oper;
1200 u8 vl_hw_cap;
1201
1202 rep = kzalloc(sizeof(*rep), GFP_KERNEL);
1203 if (!rep) {
1204 err = -ENOMEM;
1205 goto out;
1206 }
1207
Or Gerlitzc4550c62017-01-24 13:02:39 +02001208 /* props being zeroed by the caller, avoid zeroing it here */
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001209
1210 err = mlx5_query_hca_vport_context(mdev, 0, port, 0, rep);
1211 if (err)
1212 goto out;
1213
1214 props->lid = rep->lid;
1215 props->lmc = rep->lmc;
1216 props->sm_lid = rep->sm_lid;
1217 props->sm_sl = rep->sm_sl;
1218 props->state = rep->vport_state;
1219 props->phys_state = rep->port_physical_state;
1220 props->port_cap_flags = rep->cap_mask1;
1221 props->gid_tbl_len = mlx5_get_gid_table_len(MLX5_CAP_GEN(mdev, gid_table_size));
1222 props->max_msg_sz = 1 << MLX5_CAP_GEN(mdev, log_max_msg);
1223 props->pkey_tbl_len = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(mdev, pkey_table_size));
1224 props->bad_pkey_cntr = rep->pkey_violation_counter;
1225 props->qkey_viol_cntr = rep->qkey_violation_counter;
1226 props->subnet_timeout = rep->subnet_timeout;
1227 props->init_type_reply = rep->init_type_reply;
Eli Coheneff901d2016-03-11 22:58:42 +02001228 props->grh_required = rep->grh_required;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001229
1230 err = mlx5_query_port_link_width_oper(mdev, &ib_link_width_oper, port);
1231 if (err)
1232 goto out;
1233
1234 err = translate_active_width(ibdev, ib_link_width_oper,
1235 &props->active_width);
1236 if (err)
1237 goto out;
Noa Osherovichd5beb7f2016-06-02 10:47:53 +03001238 err = mlx5_query_port_ib_proto_oper(mdev, &props->active_speed, port);
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001239 if (err)
1240 goto out;
1241
Saeed Mahameedfacc9692015-06-11 14:47:27 +03001242 mlx5_query_port_max_mtu(mdev, &max_mtu, port);
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001243
1244 props->max_mtu = mlx5_mtu_to_ib_mtu(max_mtu);
1245
Saeed Mahameedfacc9692015-06-11 14:47:27 +03001246 mlx5_query_port_oper_mtu(mdev, &oper_mtu, port);
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001247
1248 props->active_mtu = mlx5_mtu_to_ib_mtu(oper_mtu);
1249
1250 err = mlx5_query_port_vl_hw_cap(mdev, &vl_hw_cap, port);
1251 if (err)
1252 goto out;
1253
1254 err = translate_max_vl_num(ibdev, vl_hw_cap,
1255 &props->max_vl_num);
1256out:
1257 kfree(rep);
Eli Cohene126ba92013-07-07 17:25:49 +03001258 return err;
1259}
1260
1261int mlx5_ib_query_port(struct ib_device *ibdev, u8 port,
1262 struct ib_port_attr *props)
1263{
Ilan Tayari095b0922017-05-14 16:04:30 +03001264 unsigned int count;
1265 int ret;
1266
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001267 switch (mlx5_get_vport_access_method(ibdev)) {
1268 case MLX5_VPORT_ACCESS_METHOD_MAD:
Ilan Tayari095b0922017-05-14 16:04:30 +03001269 ret = mlx5_query_mad_ifc_port(ibdev, port, props);
1270 break;
Eli Cohene126ba92013-07-07 17:25:49 +03001271
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001272 case MLX5_VPORT_ACCESS_METHOD_HCA:
Ilan Tayari095b0922017-05-14 16:04:30 +03001273 ret = mlx5_query_hca_port(ibdev, port, props);
1274 break;
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001275
Achiad Shochat3f89a642015-12-23 18:47:21 +02001276 case MLX5_VPORT_ACCESS_METHOD_NIC:
Ilan Tayari095b0922017-05-14 16:04:30 +03001277 ret = mlx5_query_port_roce(ibdev, port, props);
1278 break;
Achiad Shochat3f89a642015-12-23 18:47:21 +02001279
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001280 default:
Ilan Tayari095b0922017-05-14 16:04:30 +03001281 ret = -EINVAL;
Eli Cohene126ba92013-07-07 17:25:49 +03001282 }
Ilan Tayari095b0922017-05-14 16:04:30 +03001283
1284 if (!ret && props) {
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001285 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1286 struct mlx5_core_dev *mdev;
1287 bool put_mdev = true;
1288
1289 mdev = mlx5_ib_get_native_port_mdev(dev, port, NULL);
1290 if (!mdev) {
1291 /* If the port isn't affiliated yet query the master.
1292 * The master and slave will have the same values.
1293 */
1294 mdev = dev->mdev;
1295 port = 1;
1296 put_mdev = false;
1297 }
1298 count = mlx5_core_reserved_gids_count(mdev);
1299 if (put_mdev)
1300 mlx5_ib_put_native_port_mdev(dev, port);
Ilan Tayari095b0922017-05-14 16:04:30 +03001301 props->gid_tbl_len -= count;
1302 }
1303 return ret;
Eli Cohene126ba92013-07-07 17:25:49 +03001304}
1305
Mark Bloch8e6efa32017-11-06 12:22:13 +00001306static int mlx5_ib_rep_query_port(struct ib_device *ibdev, u8 port,
1307 struct ib_port_attr *props)
1308{
1309 int ret;
1310
1311 /* Only link layer == ethernet is valid for representors */
1312 ret = mlx5_query_port_roce(ibdev, port, props);
1313 if (ret || !props)
1314 return ret;
1315
1316 /* We don't support GIDS */
1317 props->gid_tbl_len = 0;
1318
1319 return ret;
1320}
1321
Eli Cohene126ba92013-07-07 17:25:49 +03001322static int mlx5_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
1323 union ib_gid *gid)
1324{
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001325 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1326 struct mlx5_core_dev *mdev = dev->mdev;
Eli Cohene126ba92013-07-07 17:25:49 +03001327
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001328 switch (mlx5_get_vport_access_method(ibdev)) {
1329 case MLX5_VPORT_ACCESS_METHOD_MAD:
1330 return mlx5_query_mad_ifc_gids(ibdev, port, index, gid);
Eli Cohene126ba92013-07-07 17:25:49 +03001331
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001332 case MLX5_VPORT_ACCESS_METHOD_HCA:
1333 return mlx5_query_hca_vport_gid(mdev, 0, port, 0, index, gid);
Eli Cohene126ba92013-07-07 17:25:49 +03001334
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001335 default:
1336 return -EINVAL;
1337 }
Eli Cohene126ba92013-07-07 17:25:49 +03001338
Eli Cohene126ba92013-07-07 17:25:49 +03001339}
1340
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001341static int mlx5_query_hca_nic_pkey(struct ib_device *ibdev, u8 port,
1342 u16 index, u16 *pkey)
1343{
1344 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1345 struct mlx5_core_dev *mdev;
1346 bool put_mdev = true;
1347 u8 mdev_port_num;
1348 int err;
1349
1350 mdev = mlx5_ib_get_native_port_mdev(dev, port, &mdev_port_num);
1351 if (!mdev) {
1352 /* The port isn't affiliated yet, get the PKey from the master
1353 * port. For RoCE the PKey tables will be the same.
1354 */
1355 put_mdev = false;
1356 mdev = dev->mdev;
1357 mdev_port_num = 1;
1358 }
1359
1360 err = mlx5_query_hca_vport_pkey(mdev, 0, mdev_port_num, 0,
1361 index, pkey);
1362 if (put_mdev)
1363 mlx5_ib_put_native_port_mdev(dev, port);
1364
1365 return err;
1366}
1367
Eli Cohene126ba92013-07-07 17:25:49 +03001368static int mlx5_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index,
1369 u16 *pkey)
1370{
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001371 switch (mlx5_get_vport_access_method(ibdev)) {
1372 case MLX5_VPORT_ACCESS_METHOD_MAD:
1373 return mlx5_query_mad_ifc_pkey(ibdev, port, index, pkey);
Eli Cohene126ba92013-07-07 17:25:49 +03001374
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001375 case MLX5_VPORT_ACCESS_METHOD_HCA:
1376 case MLX5_VPORT_ACCESS_METHOD_NIC:
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001377 return mlx5_query_hca_nic_pkey(ibdev, port, index, pkey);
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03001378 default:
1379 return -EINVAL;
1380 }
Eli Cohene126ba92013-07-07 17:25:49 +03001381}
1382
Eli Cohene126ba92013-07-07 17:25:49 +03001383static int mlx5_ib_modify_device(struct ib_device *ibdev, int mask,
1384 struct ib_device_modify *props)
1385{
1386 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1387 struct mlx5_reg_node_desc in;
1388 struct mlx5_reg_node_desc out;
1389 int err;
1390
1391 if (mask & ~IB_DEVICE_MODIFY_NODE_DESC)
1392 return -EOPNOTSUPP;
1393
1394 if (!(mask & IB_DEVICE_MODIFY_NODE_DESC))
1395 return 0;
1396
1397 /*
1398 * If possible, pass node desc to FW, so it can generate
1399 * a 144 trap. If cmd fails, just ignore.
1400 */
Yuval Shaiabd99fde2016-08-25 10:57:07 -07001401 memcpy(&in, props->node_desc, IB_DEVICE_NODE_DESC_MAX);
Jack Morgenstein9603b612014-07-28 23:30:22 +03001402 err = mlx5_core_access_reg(dev->mdev, &in, sizeof(in), &out,
Eli Cohene126ba92013-07-07 17:25:49 +03001403 sizeof(out), MLX5_REG_NODE_DESC, 0, 1);
1404 if (err)
1405 return err;
1406
Yuval Shaiabd99fde2016-08-25 10:57:07 -07001407 memcpy(ibdev->node_desc, props->node_desc, IB_DEVICE_NODE_DESC_MAX);
Eli Cohene126ba92013-07-07 17:25:49 +03001408
1409 return err;
1410}
1411
Eli Cohencdbe33d2017-02-14 07:25:38 +02001412static int set_port_caps_atomic(struct mlx5_ib_dev *dev, u8 port_num, u32 mask,
1413 u32 value)
1414{
1415 struct mlx5_hca_vport_context ctx = {};
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001416 struct mlx5_core_dev *mdev;
1417 u8 mdev_port_num;
Eli Cohencdbe33d2017-02-14 07:25:38 +02001418 int err;
1419
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001420 mdev = mlx5_ib_get_native_port_mdev(dev, port_num, &mdev_port_num);
1421 if (!mdev)
1422 return -ENODEV;
1423
1424 err = mlx5_query_hca_vport_context(mdev, 0, mdev_port_num, 0, &ctx);
Eli Cohencdbe33d2017-02-14 07:25:38 +02001425 if (err)
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001426 goto out;
Eli Cohencdbe33d2017-02-14 07:25:38 +02001427
1428 if (~ctx.cap_mask1_perm & mask) {
1429 mlx5_ib_warn(dev, "trying to change bitmask 0x%X but change supported 0x%X\n",
1430 mask, ctx.cap_mask1_perm);
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001431 err = -EINVAL;
1432 goto out;
Eli Cohencdbe33d2017-02-14 07:25:38 +02001433 }
1434
1435 ctx.cap_mask1 = value;
1436 ctx.cap_mask1_perm = mask;
Daniel Jurgensb3cbd6f2018-01-04 17:25:38 +02001437 err = mlx5_core_modify_hca_vport_context(mdev, 0, mdev_port_num,
1438 0, &ctx);
1439
1440out:
1441 mlx5_ib_put_native_port_mdev(dev, port_num);
Eli Cohencdbe33d2017-02-14 07:25:38 +02001442
1443 return err;
1444}
1445
Eli Cohene126ba92013-07-07 17:25:49 +03001446static int mlx5_ib_modify_port(struct ib_device *ibdev, u8 port, int mask,
1447 struct ib_port_modify *props)
1448{
1449 struct mlx5_ib_dev *dev = to_mdev(ibdev);
1450 struct ib_port_attr attr;
1451 u32 tmp;
1452 int err;
Eli Cohencdbe33d2017-02-14 07:25:38 +02001453 u32 change_mask;
1454 u32 value;
1455 bool is_ib = (mlx5_ib_port_link_layer(ibdev, port) ==
1456 IB_LINK_LAYER_INFINIBAND);
1457
Majd Dibbinyec255872017-08-23 08:35:42 +03001458 /* CM layer calls ib_modify_port() regardless of the link layer. For
1459 * Ethernet ports, qkey violation and Port capabilities are meaningless.
1460 */
1461 if (!is_ib)
1462 return 0;
1463
Eli Cohencdbe33d2017-02-14 07:25:38 +02001464 if (MLX5_CAP_GEN(dev->mdev, ib_virt) && is_ib) {
1465 change_mask = props->clr_port_cap_mask | props->set_port_cap_mask;
1466 value = ~props->clr_port_cap_mask | props->set_port_cap_mask;
1467 return set_port_caps_atomic(dev, port, change_mask, value);
1468 }
Eli Cohene126ba92013-07-07 17:25:49 +03001469
1470 mutex_lock(&dev->cap_mask_mutex);
1471
Or Gerlitzc4550c62017-01-24 13:02:39 +02001472 err = ib_query_port(ibdev, port, &attr);
Eli Cohene126ba92013-07-07 17:25:49 +03001473 if (err)
1474 goto out;
1475
1476 tmp = (attr.port_cap_flags | props->set_port_cap_mask) &
1477 ~props->clr_port_cap_mask;
1478
Jack Morgenstein9603b612014-07-28 23:30:22 +03001479 err = mlx5_set_port_caps(dev->mdev, port, tmp);
Eli Cohene126ba92013-07-07 17:25:49 +03001480
1481out:
1482 mutex_unlock(&dev->cap_mask_mutex);
1483 return err;
1484}
1485
Eli Cohen30aa60b2017-01-03 23:55:27 +02001486static void print_lib_caps(struct mlx5_ib_dev *dev, u64 caps)
1487{
1488 mlx5_ib_dbg(dev, "MLX5_LIB_CAP_4K_UAR = %s\n",
1489 caps & MLX5_LIB_CAP_4K_UAR ? "y" : "n");
1490}
1491
Yishai Hadas31a78a52017-12-24 16:31:34 +02001492static u16 calc_dynamic_bfregs(int uars_per_sys_page)
1493{
1494 /* Large page with non 4k uar support might limit the dynamic size */
1495 if (uars_per_sys_page == 1 && PAGE_SIZE > 4096)
1496 return MLX5_MIN_DYN_BFREGS;
1497
1498 return MLX5_MAX_DYN_BFREGS;
1499}
1500
Eli Cohenb037c292017-01-03 23:55:26 +02001501static int calc_total_bfregs(struct mlx5_ib_dev *dev, bool lib_uar_4k,
1502 struct mlx5_ib_alloc_ucontext_req_v2 *req,
Yishai Hadas31a78a52017-12-24 16:31:34 +02001503 struct mlx5_bfreg_info *bfregi)
Eli Cohenb037c292017-01-03 23:55:26 +02001504{
1505 int uars_per_sys_page;
1506 int bfregs_per_sys_page;
1507 int ref_bfregs = req->total_num_bfregs;
1508
1509 if (req->total_num_bfregs == 0)
1510 return -EINVAL;
1511
1512 BUILD_BUG_ON(MLX5_MAX_BFREGS % MLX5_NON_FP_BFREGS_IN_PAGE);
1513 BUILD_BUG_ON(MLX5_MAX_BFREGS < MLX5_NON_FP_BFREGS_IN_PAGE);
1514
1515 if (req->total_num_bfregs > MLX5_MAX_BFREGS)
1516 return -ENOMEM;
1517
1518 uars_per_sys_page = get_uars_per_sys_page(dev, lib_uar_4k);
1519 bfregs_per_sys_page = uars_per_sys_page * MLX5_NON_FP_BFREGS_PER_UAR;
Yishai Hadas31a78a52017-12-24 16:31:34 +02001520 /* This holds the required static allocation asked by the user */
Eli Cohenb037c292017-01-03 23:55:26 +02001521 req->total_num_bfregs = ALIGN(req->total_num_bfregs, bfregs_per_sys_page);
Eli Cohenb037c292017-01-03 23:55:26 +02001522 if (req->num_low_latency_bfregs > req->total_num_bfregs - 1)
1523 return -EINVAL;
1524
Yishai Hadas31a78a52017-12-24 16:31:34 +02001525 bfregi->num_static_sys_pages = req->total_num_bfregs / bfregs_per_sys_page;
1526 bfregi->num_dyn_bfregs = ALIGN(calc_dynamic_bfregs(uars_per_sys_page), bfregs_per_sys_page);
1527 bfregi->total_num_bfregs = req->total_num_bfregs + bfregi->num_dyn_bfregs;
1528 bfregi->num_sys_pages = bfregi->total_num_bfregs / bfregs_per_sys_page;
1529
1530 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 +02001531 MLX5_CAP_GEN(dev->mdev, uar_4k) ? "yes" : "no",
1532 lib_uar_4k ? "yes" : "no", ref_bfregs,
Yishai Hadas31a78a52017-12-24 16:31:34 +02001533 req->total_num_bfregs, bfregi->total_num_bfregs,
1534 bfregi->num_sys_pages);
Eli Cohenb037c292017-01-03 23:55:26 +02001535
1536 return 0;
1537}
1538
1539static int allocate_uars(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *context)
1540{
1541 struct mlx5_bfreg_info *bfregi;
1542 int err;
1543 int i;
1544
1545 bfregi = &context->bfregi;
Yishai Hadas31a78a52017-12-24 16:31:34 +02001546 for (i = 0; i < bfregi->num_static_sys_pages; i++) {
Eli Cohenb037c292017-01-03 23:55:26 +02001547 err = mlx5_cmd_alloc_uar(dev->mdev, &bfregi->sys_pages[i]);
1548 if (err)
1549 goto error;
1550
1551 mlx5_ib_dbg(dev, "allocated uar %d\n", bfregi->sys_pages[i]);
1552 }
Yishai Hadas4ed131d2017-12-24 16:31:35 +02001553
1554 for (i = bfregi->num_static_sys_pages; i < bfregi->num_sys_pages; i++)
1555 bfregi->sys_pages[i] = MLX5_IB_INVALID_UAR_INDEX;
1556
Eli Cohenb037c292017-01-03 23:55:26 +02001557 return 0;
1558
1559error:
1560 for (--i; i >= 0; i--)
1561 if (mlx5_cmd_free_uar(dev->mdev, bfregi->sys_pages[i]))
1562 mlx5_ib_warn(dev, "failed to free uar %d\n", i);
1563
1564 return err;
1565}
1566
1567static int deallocate_uars(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *context)
1568{
1569 struct mlx5_bfreg_info *bfregi;
1570 int err;
1571 int i;
1572
1573 bfregi = &context->bfregi;
Yishai Hadas4ed131d2017-12-24 16:31:35 +02001574 for (i = 0; i < bfregi->num_sys_pages; i++) {
1575 if (i < bfregi->num_static_sys_pages ||
1576 bfregi->sys_pages[i] != MLX5_IB_INVALID_UAR_INDEX) {
1577 err = mlx5_cmd_free_uar(dev->mdev, bfregi->sys_pages[i]);
1578 if (err) {
1579 mlx5_ib_warn(dev, "failed to free uar %d, err=%d\n", i, err);
1580 return err;
1581 }
Eli Cohenb037c292017-01-03 23:55:26 +02001582 }
1583 }
Yishai Hadas4ed131d2017-12-24 16:31:35 +02001584
Eli Cohenb037c292017-01-03 23:55:26 +02001585 return 0;
1586}
1587
Huy Nguyenc85023e2017-05-30 09:42:54 +03001588static int mlx5_ib_alloc_transport_domain(struct mlx5_ib_dev *dev, u32 *tdn)
1589{
1590 int err;
1591
1592 err = mlx5_core_alloc_transport_domain(dev->mdev, tdn);
1593 if (err)
1594 return err;
1595
1596 if ((MLX5_CAP_GEN(dev->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) ||
Eran Ben Elisha8978cc92018-01-09 11:41:10 +02001597 (!MLX5_CAP_GEN(dev->mdev, disable_local_lb_uc) &&
1598 !MLX5_CAP_GEN(dev->mdev, disable_local_lb_mc)))
Huy Nguyenc85023e2017-05-30 09:42:54 +03001599 return err;
1600
1601 mutex_lock(&dev->lb_mutex);
1602 dev->user_td++;
1603
1604 if (dev->user_td == 2)
1605 err = mlx5_nic_vport_update_local_lb(dev->mdev, true);
1606
1607 mutex_unlock(&dev->lb_mutex);
1608 return err;
1609}
1610
1611static void mlx5_ib_dealloc_transport_domain(struct mlx5_ib_dev *dev, u32 tdn)
1612{
1613 mlx5_core_dealloc_transport_domain(dev->mdev, tdn);
1614
1615 if ((MLX5_CAP_GEN(dev->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) ||
Eran Ben Elisha8978cc92018-01-09 11:41:10 +02001616 (!MLX5_CAP_GEN(dev->mdev, disable_local_lb_uc) &&
1617 !MLX5_CAP_GEN(dev->mdev, disable_local_lb_mc)))
Huy Nguyenc85023e2017-05-30 09:42:54 +03001618 return;
1619
1620 mutex_lock(&dev->lb_mutex);
1621 dev->user_td--;
1622
1623 if (dev->user_td < 2)
1624 mlx5_nic_vport_update_local_lb(dev->mdev, false);
1625
1626 mutex_unlock(&dev->lb_mutex);
1627}
1628
Eli Cohene126ba92013-07-07 17:25:49 +03001629static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
1630 struct ib_udata *udata)
1631{
1632 struct mlx5_ib_dev *dev = to_mdev(ibdev);
Matan Barakb368d7c2015-12-15 20:30:12 +02001633 struct mlx5_ib_alloc_ucontext_req_v2 req = {};
1634 struct mlx5_ib_alloc_ucontext_resp resp = {};
Feras Daoud5c99eae2018-01-16 20:08:41 +02001635 struct mlx5_core_dev *mdev = dev->mdev;
Eli Cohene126ba92013-07-07 17:25:49 +03001636 struct mlx5_ib_ucontext *context;
Eli Cohen2f5ff262017-01-03 23:55:21 +02001637 struct mlx5_bfreg_info *bfregi;
Eli Cohen78c0f982014-01-30 13:49:48 +02001638 int ver;
Eli Cohene126ba92013-07-07 17:25:49 +03001639 int err;
Majd Dibbinya168a41c2016-01-28 17:51:47 +02001640 size_t min_req_v2 = offsetof(struct mlx5_ib_alloc_ucontext_req_v2,
1641 max_cqe_version);
Eli Cohenb037c292017-01-03 23:55:26 +02001642 bool lib_uar_4k;
Eli Cohene126ba92013-07-07 17:25:49 +03001643
1644 if (!dev->ib_active)
1645 return ERR_PTR(-EAGAIN);
1646
Amrani, Rame0931112017-06-27 17:04:42 +03001647 if (udata->inlen == sizeof(struct mlx5_ib_alloc_ucontext_req))
Eli Cohen78c0f982014-01-30 13:49:48 +02001648 ver = 0;
Amrani, Rame0931112017-06-27 17:04:42 +03001649 else if (udata->inlen >= min_req_v2)
Eli Cohen78c0f982014-01-30 13:49:48 +02001650 ver = 2;
1651 else
1652 return ERR_PTR(-EINVAL);
1653
Amrani, Rame0931112017-06-27 17:04:42 +03001654 err = ib_copy_from_udata(&req, udata, min(udata->inlen, sizeof(req)));
Eli Cohene126ba92013-07-07 17:25:49 +03001655 if (err)
1656 return ERR_PTR(err);
1657
Matan Barakb368d7c2015-12-15 20:30:12 +02001658 if (req.flags)
Eli Cohen78c0f982014-01-30 13:49:48 +02001659 return ERR_PTR(-EINVAL);
1660
Haggai Abramovskyf72300c2016-01-14 19:12:58 +02001661 if (req.comp_mask || req.reserved0 || req.reserved1 || req.reserved2)
Matan Barakb368d7c2015-12-15 20:30:12 +02001662 return ERR_PTR(-EOPNOTSUPP);
1663
Eli Cohen2f5ff262017-01-03 23:55:21 +02001664 req.total_num_bfregs = ALIGN(req.total_num_bfregs,
1665 MLX5_NON_FP_BFREGS_PER_UAR);
1666 if (req.num_low_latency_bfregs > req.total_num_bfregs - 1)
Eli Cohene126ba92013-07-07 17:25:49 +03001667 return ERR_PTR(-EINVAL);
1668
Saeed Mahameed938fe832015-05-28 22:28:41 +03001669 resp.qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp);
Noa Osherovich2cc6ad52016-06-04 15:15:33 +03001670 if (mlx5_core_is_pf(dev->mdev) && MLX5_CAP_GEN(dev->mdev, bf))
1671 resp.bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size);
Daniel Jurgensb47bd6e2016-10-25 18:36:24 +03001672 resp.cache_line_size = cache_line_size();
Saeed Mahameed938fe832015-05-28 22:28:41 +03001673 resp.max_sq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq);
1674 resp.max_rq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq);
1675 resp.max_send_wqebb = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz);
1676 resp.max_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz);
1677 resp.max_srq_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_srq_sz);
Haggai Abramovskyf72300c2016-01-14 19:12:58 +02001678 resp.cqe_version = min_t(__u8,
1679 (__u8)MLX5_CAP_GEN(dev->mdev, cqe_version),
1680 req.max_cqe_version);
Eli Cohen30aa60b2017-01-03 23:55:27 +02001681 resp.log_uar_size = MLX5_CAP_GEN(dev->mdev, uar_4k) ?
1682 MLX5_ADAPTER_PAGE_SHIFT : PAGE_SHIFT;
1683 resp.num_uars_per_page = MLX5_CAP_GEN(dev->mdev, uar_4k) ?
1684 MLX5_CAP_GEN(dev->mdev, num_of_uars_per_page) : 1;
Matan Barakb368d7c2015-12-15 20:30:12 +02001685 resp.response_length = min(offsetof(typeof(resp), response_length) +
1686 sizeof(resp.response_length), udata->outlen);
Eli Cohene126ba92013-07-07 17:25:49 +03001687
Matan Barakc03faa52018-03-28 09:27:54 +03001688 if (mlx5_accel_ipsec_device_caps(dev->mdev) & MLX5_ACCEL_IPSEC_CAP_DEVICE) {
1689 if (mlx5_get_flow_namespace(dev->mdev, MLX5_FLOW_NAMESPACE_EGRESS))
1690 resp.flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM;
1691 if (mlx5_accel_ipsec_device_caps(dev->mdev) & MLX5_ACCEL_IPSEC_CAP_REQUIRED_METADATA)
1692 resp.flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_REQ_METADATA;
1693 if (MLX5_CAP_FLOWTABLE(dev->mdev, flow_table_properties_nic_receive.ft_field_support.outer_esp_spi))
1694 resp.flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_SPI_STEERING;
1695 if (mlx5_accel_ipsec_device_caps(dev->mdev) & MLX5_ACCEL_IPSEC_CAP_TX_IV_IS_ESN)
1696 resp.flow_action_flags |= MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_TX_IV_IS_ESN;
1697 /* MLX5_USER_ALLOC_UCONTEXT_FLOW_ACTION_FLAGS_ESP_AES_GCM_FULL_OFFLOAD is currently always 0 */
1698 }
1699
Eli Cohene126ba92013-07-07 17:25:49 +03001700 context = kzalloc(sizeof(*context), GFP_KERNEL);
1701 if (!context)
1702 return ERR_PTR(-ENOMEM);
1703
Eli Cohen30aa60b2017-01-03 23:55:27 +02001704 lib_uar_4k = req.lib_caps & MLX5_LIB_CAP_4K_UAR;
Eli Cohen2f5ff262017-01-03 23:55:21 +02001705 bfregi = &context->bfregi;
Eli Cohenb037c292017-01-03 23:55:26 +02001706
1707 /* updates req->total_num_bfregs */
Yishai Hadas31a78a52017-12-24 16:31:34 +02001708 err = calc_total_bfregs(dev, lib_uar_4k, &req, bfregi);
Eli Cohenb037c292017-01-03 23:55:26 +02001709 if (err)
1710 goto out_ctx;
1711
Eli Cohen2f5ff262017-01-03 23:55:21 +02001712 mutex_init(&bfregi->lock);
Eli Cohenb037c292017-01-03 23:55:26 +02001713 bfregi->lib_uar_4k = lib_uar_4k;
Yishai Hadas31a78a52017-12-24 16:31:34 +02001714 bfregi->count = kcalloc(bfregi->total_num_bfregs, sizeof(*bfregi->count),
Eli Cohenb037c292017-01-03 23:55:26 +02001715 GFP_KERNEL);
1716 if (!bfregi->count) {
Eli Cohene126ba92013-07-07 17:25:49 +03001717 err = -ENOMEM;
1718 goto out_ctx;
1719 }
1720
Eli Cohenb037c292017-01-03 23:55:26 +02001721 bfregi->sys_pages = kcalloc(bfregi->num_sys_pages,
1722 sizeof(*bfregi->sys_pages),
1723 GFP_KERNEL);
1724 if (!bfregi->sys_pages) {
Eli Cohene126ba92013-07-07 17:25:49 +03001725 err = -ENOMEM;
Eli Cohenb037c292017-01-03 23:55:26 +02001726 goto out_count;
Eli Cohene126ba92013-07-07 17:25:49 +03001727 }
1728
Eli Cohenb037c292017-01-03 23:55:26 +02001729 err = allocate_uars(dev, context);
1730 if (err)
1731 goto out_sys_pages;
Eli Cohene126ba92013-07-07 17:25:49 +03001732
Haggai Eranb4cfe442014-12-11 17:04:26 +02001733#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
1734 context->ibucontext.invalidate_range = &mlx5_ib_invalidate_range;
1735#endif
1736
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001737 if (MLX5_CAP_GEN(dev->mdev, log_max_transport_domain)) {
Huy Nguyenc85023e2017-05-30 09:42:54 +03001738 err = mlx5_ib_alloc_transport_domain(dev, &context->tdn);
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001739 if (err)
Ilya Lesokhinc44ef992018-03-13 15:18:48 +02001740 goto out_uars;
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001741 }
1742
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001743 INIT_LIST_HEAD(&context->vma_private_list);
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001744 mutex_init(&context->vma_private_list_mutex);
Eli Cohene126ba92013-07-07 17:25:49 +03001745 INIT_LIST_HEAD(&context->db_page_list);
1746 mutex_init(&context->db_page_mutex);
1747
Eli Cohen2f5ff262017-01-03 23:55:21 +02001748 resp.tot_bfregs = req.total_num_bfregs;
Daniel Jurgens508562d2018-01-04 17:25:34 +02001749 resp.num_ports = dev->num_ports;
Matan Barakb368d7c2015-12-15 20:30:12 +02001750
Haggai Abramovskyf72300c2016-01-14 19:12:58 +02001751 if (field_avail(typeof(resp), cqe_version, udata->outlen))
1752 resp.response_length += sizeof(resp.cqe_version);
Matan Barakb368d7c2015-12-15 20:30:12 +02001753
Bodong Wang402ca532016-06-17 15:02:20 +03001754 if (field_avail(typeof(resp), cmds_supp_uhw, udata->outlen)) {
Moni Shoua6ad279c52016-11-23 08:23:23 +02001755 resp.cmds_supp_uhw |= MLX5_USER_CMDS_SUPP_UHW_QUERY_DEVICE |
1756 MLX5_USER_CMDS_SUPP_UHW_CREATE_AH;
Bodong Wang402ca532016-06-17 15:02:20 +03001757 resp.response_length += sizeof(resp.cmds_supp_uhw);
1758 }
1759
Or Gerlitz78984892016-11-30 20:33:33 +02001760 if (field_avail(typeof(resp), eth_min_inline, udata->outlen)) {
1761 if (mlx5_ib_port_link_layer(ibdev, 1) == IB_LINK_LAYER_ETHERNET) {
1762 mlx5_query_min_inline(dev->mdev, &resp.eth_min_inline);
1763 resp.eth_min_inline++;
1764 }
1765 resp.response_length += sizeof(resp.eth_min_inline);
1766 }
1767
Feras Daoud5c99eae2018-01-16 20:08:41 +02001768 if (field_avail(typeof(resp), clock_info_versions, udata->outlen)) {
1769 if (mdev->clock_info)
1770 resp.clock_info_versions = BIT(MLX5_IB_CLOCK_INFO_V1);
1771 resp.response_length += sizeof(resp.clock_info_versions);
1772 }
1773
Noa Osherovichbc5c6ee2016-06-04 15:15:31 +03001774 /*
1775 * We don't want to expose information from the PCI bar that is located
1776 * after 4096 bytes, so if the arch only supports larger pages, let's
1777 * pretend we don't support reading the HCA's core clock. This is also
1778 * forced by mmap function.
1779 */
Eli Cohende8d6e02017-01-03 23:55:19 +02001780 if (field_avail(typeof(resp), hca_core_clock_offset, udata->outlen)) {
1781 if (PAGE_SIZE <= 4096) {
1782 resp.comp_mask |=
1783 MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_CORE_CLOCK_OFFSET;
1784 resp.hca_core_clock_offset =
1785 offsetof(struct mlx5_init_seg, internal_timer_h) % PAGE_SIZE;
1786 }
Feras Daoud5c99eae2018-01-16 20:08:41 +02001787 resp.response_length += sizeof(resp.hca_core_clock_offset);
Matan Barakb368d7c2015-12-15 20:30:12 +02001788 }
1789
Eli Cohen30aa60b2017-01-03 23:55:27 +02001790 if (field_avail(typeof(resp), log_uar_size, udata->outlen))
1791 resp.response_length += sizeof(resp.log_uar_size);
1792
1793 if (field_avail(typeof(resp), num_uars_per_page, udata->outlen))
1794 resp.response_length += sizeof(resp.num_uars_per_page);
1795
Yishai Hadas31a78a52017-12-24 16:31:34 +02001796 if (field_avail(typeof(resp), num_dyn_bfregs, udata->outlen)) {
1797 resp.num_dyn_bfregs = bfregi->num_dyn_bfregs;
1798 resp.response_length += sizeof(resp.num_dyn_bfregs);
1799 }
1800
Matan Barakb368d7c2015-12-15 20:30:12 +02001801 err = ib_copy_to_udata(udata, &resp, resp.response_length);
Eli Cohene126ba92013-07-07 17:25:49 +03001802 if (err)
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001803 goto out_td;
Eli Cohene126ba92013-07-07 17:25:49 +03001804
Eli Cohen2f5ff262017-01-03 23:55:21 +02001805 bfregi->ver = ver;
1806 bfregi->num_low_latency_bfregs = req.num_low_latency_bfregs;
Haggai Abramovskyf72300c2016-01-14 19:12:58 +02001807 context->cqe_version = resp.cqe_version;
Eli Cohen30aa60b2017-01-03 23:55:27 +02001808 context->lib_caps = req.lib_caps;
1809 print_lib_caps(dev, context->lib_caps);
Haggai Abramovskyf72300c2016-01-14 19:12:58 +02001810
Eli Cohene126ba92013-07-07 17:25:49 +03001811 return &context->ibucontext;
1812
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001813out_td:
1814 if (MLX5_CAP_GEN(dev->mdev, log_max_transport_domain))
Huy Nguyenc85023e2017-05-30 09:42:54 +03001815 mlx5_ib_dealloc_transport_domain(dev, context->tdn);
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001816
Eli Cohene126ba92013-07-07 17:25:49 +03001817out_uars:
Eli Cohenb037c292017-01-03 23:55:26 +02001818 deallocate_uars(dev, context);
1819
1820out_sys_pages:
1821 kfree(bfregi->sys_pages);
1822
Eli Cohene126ba92013-07-07 17:25:49 +03001823out_count:
Eli Cohen2f5ff262017-01-03 23:55:21 +02001824 kfree(bfregi->count);
Eli Cohene126ba92013-07-07 17:25:49 +03001825
Eli Cohene126ba92013-07-07 17:25:49 +03001826out_ctx:
1827 kfree(context);
Eli Cohenb037c292017-01-03 23:55:26 +02001828
Eli Cohene126ba92013-07-07 17:25:49 +03001829 return ERR_PTR(err);
1830}
1831
1832static int mlx5_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)
1833{
1834 struct mlx5_ib_ucontext *context = to_mucontext(ibcontext);
1835 struct mlx5_ib_dev *dev = to_mdev(ibcontext->device);
Eli Cohenb037c292017-01-03 23:55:26 +02001836 struct mlx5_bfreg_info *bfregi;
Eli Cohene126ba92013-07-07 17:25:49 +03001837
Eli Cohenb037c292017-01-03 23:55:26 +02001838 bfregi = &context->bfregi;
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001839 if (MLX5_CAP_GEN(dev->mdev, log_max_transport_domain))
Huy Nguyenc85023e2017-05-30 09:42:54 +03001840 mlx5_ib_dealloc_transport_domain(dev, context->tdn);
majd@mellanox.com146d2f12016-01-14 19:13:02 +02001841
Eli Cohenb037c292017-01-03 23:55:26 +02001842 deallocate_uars(dev, context);
1843 kfree(bfregi->sys_pages);
Eli Cohen2f5ff262017-01-03 23:55:21 +02001844 kfree(bfregi->count);
Eli Cohene126ba92013-07-07 17:25:49 +03001845 kfree(context);
1846
1847 return 0;
1848}
1849
Eli Cohenb037c292017-01-03 23:55:26 +02001850static phys_addr_t uar_index2pfn(struct mlx5_ib_dev *dev,
Yishai Hadas4ed131d2017-12-24 16:31:35 +02001851 int uar_idx)
Eli Cohene126ba92013-07-07 17:25:49 +03001852{
Eli Cohenb037c292017-01-03 23:55:26 +02001853 int fw_uars_per_page;
1854
1855 fw_uars_per_page = MLX5_CAP_GEN(dev->mdev, uar_4k) ? MLX5_UARS_IN_PAGE : 1;
1856
Yishai Hadas4ed131d2017-12-24 16:31:35 +02001857 return (pci_resource_start(dev->mdev->pdev, 0) >> PAGE_SHIFT) + uar_idx / fw_uars_per_page;
Eli Cohene126ba92013-07-07 17:25:49 +03001858}
1859
1860static int get_command(unsigned long offset)
1861{
1862 return (offset >> MLX5_IB_MMAP_CMD_SHIFT) & MLX5_IB_MMAP_CMD_MASK;
1863}
1864
1865static int get_arg(unsigned long offset)
1866{
1867 return offset & ((1 << MLX5_IB_MMAP_CMD_SHIFT) - 1);
1868}
1869
1870static int get_index(unsigned long offset)
1871{
1872 return get_arg(offset);
1873}
1874
Yishai Hadas4ed131d2017-12-24 16:31:35 +02001875/* Index resides in an extra byte to enable larger values than 255 */
1876static int get_extended_index(unsigned long offset)
1877{
1878 return get_arg(offset) | ((offset >> 16) & 0xff) << 8;
1879}
1880
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001881static void mlx5_ib_vma_open(struct vm_area_struct *area)
1882{
1883 /* vma_open is called when a new VMA is created on top of our VMA. This
1884 * is done through either mremap flow or split_vma (usually due to
1885 * mlock, madvise, munmap, etc.) We do not support a clone of the VMA,
1886 * as this VMA is strongly hardware related. Therefore we set the
1887 * vm_ops of the newly created/cloned VMA to NULL, to prevent it from
1888 * calling us again and trying to do incorrect actions. We assume that
1889 * the original VMA size is exactly a single page, and therefore all
1890 * "splitting" operation will not happen to it.
1891 */
1892 area->vm_ops = NULL;
1893}
1894
1895static void mlx5_ib_vma_close(struct vm_area_struct *area)
1896{
1897 struct mlx5_ib_vma_private_data *mlx5_ib_vma_priv_data;
1898
1899 /* It's guaranteed that all VMAs opened on a FD are closed before the
1900 * file itself is closed, therefore no sync is needed with the regular
1901 * closing flow. (e.g. mlx5 ib_dealloc_ucontext)
1902 * However need a sync with accessing the vma as part of
1903 * mlx5_ib_disassociate_ucontext.
1904 * The close operation is usually called under mm->mmap_sem except when
1905 * process is exiting.
1906 * The exiting case is handled explicitly as part of
1907 * mlx5_ib_disassociate_ucontext.
1908 */
1909 mlx5_ib_vma_priv_data = (struct mlx5_ib_vma_private_data *)area->vm_private_data;
1910
1911 /* setting the vma context pointer to null in the mlx5_ib driver's
1912 * private data, to protect a race condition in
1913 * mlx5_ib_disassociate_ucontext().
1914 */
1915 mlx5_ib_vma_priv_data->vma = NULL;
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001916 mutex_lock(mlx5_ib_vma_priv_data->vma_private_list_mutex);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001917 list_del(&mlx5_ib_vma_priv_data->list);
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001918 mutex_unlock(mlx5_ib_vma_priv_data->vma_private_list_mutex);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001919 kfree(mlx5_ib_vma_priv_data);
1920}
1921
1922static const struct vm_operations_struct mlx5_ib_vm_ops = {
1923 .open = mlx5_ib_vma_open,
1924 .close = mlx5_ib_vma_close
1925};
1926
1927static int mlx5_ib_set_vma_data(struct vm_area_struct *vma,
1928 struct mlx5_ib_ucontext *ctx)
1929{
1930 struct mlx5_ib_vma_private_data *vma_prv;
1931 struct list_head *vma_head = &ctx->vma_private_list;
1932
1933 vma_prv = kzalloc(sizeof(*vma_prv), GFP_KERNEL);
1934 if (!vma_prv)
1935 return -ENOMEM;
1936
1937 vma_prv->vma = vma;
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001938 vma_prv->vma_private_list_mutex = &ctx->vma_private_list_mutex;
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001939 vma->vm_private_data = vma_prv;
1940 vma->vm_ops = &mlx5_ib_vm_ops;
1941
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001942 mutex_lock(&ctx->vma_private_list_mutex);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001943 list_add(&vma_prv->list, vma_head);
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001944 mutex_unlock(&ctx->vma_private_list_mutex);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001945
1946 return 0;
1947}
1948
1949static void mlx5_ib_disassociate_ucontext(struct ib_ucontext *ibcontext)
1950{
1951 int ret;
1952 struct vm_area_struct *vma;
1953 struct mlx5_ib_vma_private_data *vma_private, *n;
1954 struct mlx5_ib_ucontext *context = to_mucontext(ibcontext);
1955 struct task_struct *owning_process = NULL;
1956 struct mm_struct *owning_mm = NULL;
1957
1958 owning_process = get_pid_task(ibcontext->tgid, PIDTYPE_PID);
1959 if (!owning_process)
1960 return;
1961
1962 owning_mm = get_task_mm(owning_process);
1963 if (!owning_mm) {
1964 pr_info("no mm, disassociate ucontext is pending task termination\n");
1965 while (1) {
1966 put_task_struct(owning_process);
1967 usleep_range(1000, 2000);
1968 owning_process = get_pid_task(ibcontext->tgid,
1969 PIDTYPE_PID);
1970 if (!owning_process ||
1971 owning_process->state == TASK_DEAD) {
1972 pr_info("disassociate ucontext done, task was terminated\n");
1973 /* in case task was dead need to release the
1974 * task struct.
1975 */
1976 if (owning_process)
1977 put_task_struct(owning_process);
1978 return;
1979 }
1980 }
1981 }
1982
1983 /* need to protect from a race on closing the vma as part of
1984 * mlx5_ib_vma_close.
1985 */
Maor Gottliebecc7d832017-03-29 06:03:02 +03001986 down_write(&owning_mm->mmap_sem);
Majd Dibbinyad9a3662017-12-24 13:54:56 +02001987 mutex_lock(&context->vma_private_list_mutex);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001988 list_for_each_entry_safe(vma_private, n, &context->vma_private_list,
1989 list) {
1990 vma = vma_private->vma;
1991 ret = zap_vma_ptes(vma, vma->vm_start,
1992 PAGE_SIZE);
1993 WARN_ONCE(ret, "%s: zap_vma_ptes failed", __func__);
1994 /* context going to be destroyed, should
1995 * not access ops any more.
1996 */
Maor Gottlieb13776612017-03-29 06:03:03 +03001997 vma->vm_flags &= ~(VM_SHARED | VM_MAYSHARE);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03001998 vma->vm_ops = NULL;
1999 list_del(&vma_private->list);
2000 kfree(vma_private);
2001 }
Majd Dibbinyad9a3662017-12-24 13:54:56 +02002002 mutex_unlock(&context->vma_private_list_mutex);
Maor Gottliebecc7d832017-03-29 06:03:02 +03002003 up_write(&owning_mm->mmap_sem);
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03002004 mmput(owning_mm);
2005 put_task_struct(owning_process);
2006}
2007
Guy Levi37aa5c32016-04-27 16:49:50 +03002008static inline char *mmap_cmd2str(enum mlx5_ib_mmap_cmd cmd)
2009{
2010 switch (cmd) {
2011 case MLX5_IB_MMAP_WC_PAGE:
2012 return "WC";
2013 case MLX5_IB_MMAP_REGULAR_PAGE:
2014 return "best effort WC";
2015 case MLX5_IB_MMAP_NC_PAGE:
2016 return "NC";
2017 default:
2018 return NULL;
2019 }
2020}
2021
Feras Daoud5c99eae2018-01-16 20:08:41 +02002022static int mlx5_ib_mmap_clock_info_page(struct mlx5_ib_dev *dev,
2023 struct vm_area_struct *vma,
2024 struct mlx5_ib_ucontext *context)
2025{
2026 phys_addr_t pfn;
2027 int err;
2028
2029 if (vma->vm_end - vma->vm_start != PAGE_SIZE)
2030 return -EINVAL;
2031
2032 if (get_index(vma->vm_pgoff) != MLX5_IB_CLOCK_INFO_V1)
2033 return -EOPNOTSUPP;
2034
2035 if (vma->vm_flags & VM_WRITE)
2036 return -EPERM;
2037
2038 if (!dev->mdev->clock_info_page)
2039 return -EOPNOTSUPP;
2040
2041 pfn = page_to_pfn(dev->mdev->clock_info_page);
2042 err = remap_pfn_range(vma, vma->vm_start, pfn, PAGE_SIZE,
2043 vma->vm_page_prot);
2044 if (err)
2045 return err;
2046
2047 mlx5_ib_dbg(dev, "mapped clock info at 0x%lx, PA 0x%llx\n",
2048 vma->vm_start,
2049 (unsigned long long)pfn << PAGE_SHIFT);
2050
2051 return mlx5_ib_set_vma_data(vma, context);
2052}
2053
Guy Levi37aa5c32016-04-27 16:49:50 +03002054static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03002055 struct vm_area_struct *vma,
2056 struct mlx5_ib_ucontext *context)
Guy Levi37aa5c32016-04-27 16:49:50 +03002057{
Eli Cohen2f5ff262017-01-03 23:55:21 +02002058 struct mlx5_bfreg_info *bfregi = &context->bfregi;
Guy Levi37aa5c32016-04-27 16:49:50 +03002059 int err;
2060 unsigned long idx;
2061 phys_addr_t pfn, pa;
2062 pgprot_t prot;
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002063 u32 bfreg_dyn_idx = 0;
2064 u32 uar_index;
2065 int dyn_uar = (cmd == MLX5_IB_MMAP_ALLOC_WC);
2066 int max_valid_idx = dyn_uar ? bfregi->num_sys_pages :
2067 bfregi->num_static_sys_pages;
Eli Cohenb037c292017-01-03 23:55:26 +02002068
2069 if (vma->vm_end - vma->vm_start != PAGE_SIZE)
2070 return -EINVAL;
2071
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002072 if (dyn_uar)
2073 idx = get_extended_index(vma->vm_pgoff) + bfregi->num_static_sys_pages;
2074 else
2075 idx = get_index(vma->vm_pgoff);
2076
2077 if (idx >= max_valid_idx) {
2078 mlx5_ib_warn(dev, "invalid uar index %lu, max=%d\n",
2079 idx, max_valid_idx);
Eli Cohenb037c292017-01-03 23:55:26 +02002080 return -EINVAL;
2081 }
Guy Levi37aa5c32016-04-27 16:49:50 +03002082
2083 switch (cmd) {
2084 case MLX5_IB_MMAP_WC_PAGE:
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002085 case MLX5_IB_MMAP_ALLOC_WC:
Guy Levi37aa5c32016-04-27 16:49:50 +03002086/* Some architectures don't support WC memory */
2087#if defined(CONFIG_X86)
2088 if (!pat_enabled())
2089 return -EPERM;
2090#elif !(defined(CONFIG_PPC) || (defined(CONFIG_ARM) && defined(CONFIG_MMU)))
2091 return -EPERM;
2092#endif
2093 /* fall through */
2094 case MLX5_IB_MMAP_REGULAR_PAGE:
2095 /* For MLX5_IB_MMAP_REGULAR_PAGE do the best effort to get WC */
2096 prot = pgprot_writecombine(vma->vm_page_prot);
2097 break;
2098 case MLX5_IB_MMAP_NC_PAGE:
2099 prot = pgprot_noncached(vma->vm_page_prot);
2100 break;
2101 default:
2102 return -EINVAL;
2103 }
2104
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002105 if (dyn_uar) {
2106 int uars_per_page;
2107
2108 uars_per_page = get_uars_per_sys_page(dev, bfregi->lib_uar_4k);
2109 bfreg_dyn_idx = idx * (uars_per_page * MLX5_NON_FP_BFREGS_PER_UAR);
2110 if (bfreg_dyn_idx >= bfregi->total_num_bfregs) {
2111 mlx5_ib_warn(dev, "invalid bfreg_dyn_idx %u, max=%u\n",
2112 bfreg_dyn_idx, bfregi->total_num_bfregs);
2113 return -EINVAL;
2114 }
2115
2116 mutex_lock(&bfregi->lock);
2117 /* Fail if uar already allocated, first bfreg index of each
2118 * page holds its count.
2119 */
2120 if (bfregi->count[bfreg_dyn_idx]) {
2121 mlx5_ib_warn(dev, "wrong offset, idx %lu is busy, bfregn=%u\n", idx, bfreg_dyn_idx);
2122 mutex_unlock(&bfregi->lock);
2123 return -EINVAL;
2124 }
2125
2126 bfregi->count[bfreg_dyn_idx]++;
2127 mutex_unlock(&bfregi->lock);
2128
2129 err = mlx5_cmd_alloc_uar(dev->mdev, &uar_index);
2130 if (err) {
2131 mlx5_ib_warn(dev, "UAR alloc failed\n");
2132 goto free_bfreg;
2133 }
2134 } else {
2135 uar_index = bfregi->sys_pages[idx];
2136 }
2137
2138 pfn = uar_index2pfn(dev, uar_index);
Guy Levi37aa5c32016-04-27 16:49:50 +03002139 mlx5_ib_dbg(dev, "uar idx 0x%lx, pfn %pa\n", idx, &pfn);
2140
2141 vma->vm_page_prot = prot;
2142 err = io_remap_pfn_range(vma, vma->vm_start, pfn,
2143 PAGE_SIZE, vma->vm_page_prot);
2144 if (err) {
2145 mlx5_ib_err(dev, "io_remap_pfn_range failed with error=%d, vm_start=0x%lx, pfn=%pa, mmap_cmd=%s\n",
2146 err, vma->vm_start, &pfn, mmap_cmd2str(cmd));
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002147 err = -EAGAIN;
2148 goto err;
Guy Levi37aa5c32016-04-27 16:49:50 +03002149 }
2150
2151 pa = pfn << PAGE_SHIFT;
2152 mlx5_ib_dbg(dev, "mapped %s at 0x%lx, PA %pa\n", mmap_cmd2str(cmd),
2153 vma->vm_start, &pa);
2154
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002155 err = mlx5_ib_set_vma_data(vma, context);
2156 if (err)
2157 goto err;
2158
2159 if (dyn_uar)
2160 bfregi->sys_pages[idx] = uar_index;
2161 return 0;
2162
2163err:
2164 if (!dyn_uar)
2165 return err;
2166
2167 mlx5_cmd_free_uar(dev->mdev, idx);
2168
2169free_bfreg:
2170 mlx5_ib_free_bfreg(dev, bfregi, bfreg_dyn_idx);
2171
2172 return err;
Guy Levi37aa5c32016-04-27 16:49:50 +03002173}
2174
Eli Cohene126ba92013-07-07 17:25:49 +03002175static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma)
2176{
2177 struct mlx5_ib_ucontext *context = to_mucontext(ibcontext);
2178 struct mlx5_ib_dev *dev = to_mdev(ibcontext->device);
Eli Cohene126ba92013-07-07 17:25:49 +03002179 unsigned long command;
Eli Cohene126ba92013-07-07 17:25:49 +03002180 phys_addr_t pfn;
2181
2182 command = get_command(vma->vm_pgoff);
2183 switch (command) {
Guy Levi37aa5c32016-04-27 16:49:50 +03002184 case MLX5_IB_MMAP_WC_PAGE:
2185 case MLX5_IB_MMAP_NC_PAGE:
Eli Cohene126ba92013-07-07 17:25:49 +03002186 case MLX5_IB_MMAP_REGULAR_PAGE:
Yishai Hadas4ed131d2017-12-24 16:31:35 +02002187 case MLX5_IB_MMAP_ALLOC_WC:
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03002188 return uar_mmap(dev, command, vma, context);
Eli Cohene126ba92013-07-07 17:25:49 +03002189
2190 case MLX5_IB_MMAP_GET_CONTIGUOUS_PAGES:
2191 return -ENOSYS;
2192
Matan Barakd69e3bc2015-12-15 20:30:13 +02002193 case MLX5_IB_MMAP_CORE_CLOCK:
Matan Barakd69e3bc2015-12-15 20:30:13 +02002194 if (vma->vm_end - vma->vm_start != PAGE_SIZE)
2195 return -EINVAL;
2196
Matan Barak6cbac1e2016-04-14 16:52:10 +03002197 if (vma->vm_flags & VM_WRITE)
Matan Barakd69e3bc2015-12-15 20:30:13 +02002198 return -EPERM;
2199
2200 /* Don't expose to user-space information it shouldn't have */
2201 if (PAGE_SIZE > 4096)
2202 return -EOPNOTSUPP;
2203
2204 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
2205 pfn = (dev->mdev->iseg_base +
2206 offsetof(struct mlx5_init_seg, internal_timer_h)) >>
2207 PAGE_SHIFT;
2208 if (io_remap_pfn_range(vma, vma->vm_start, pfn,
2209 PAGE_SIZE, vma->vm_page_prot))
2210 return -EAGAIN;
2211
2212 mlx5_ib_dbg(dev, "mapped internal timer at 0x%lx, PA 0x%llx\n",
2213 vma->vm_start,
2214 (unsigned long long)pfn << PAGE_SHIFT);
2215 break;
Feras Daoud5c99eae2018-01-16 20:08:41 +02002216 case MLX5_IB_MMAP_CLOCK_INFO:
2217 return mlx5_ib_mmap_clock_info_page(dev, vma, context);
Matan Barakd69e3bc2015-12-15 20:30:13 +02002218
Eli Cohene126ba92013-07-07 17:25:49 +03002219 default:
2220 return -EINVAL;
2221 }
2222
2223 return 0;
2224}
2225
Eli Cohene126ba92013-07-07 17:25:49 +03002226static struct ib_pd *mlx5_ib_alloc_pd(struct ib_device *ibdev,
2227 struct ib_ucontext *context,
2228 struct ib_udata *udata)
2229{
2230 struct mlx5_ib_alloc_pd_resp resp;
2231 struct mlx5_ib_pd *pd;
2232 int err;
2233
2234 pd = kmalloc(sizeof(*pd), GFP_KERNEL);
2235 if (!pd)
2236 return ERR_PTR(-ENOMEM);
2237
Jack Morgenstein9603b612014-07-28 23:30:22 +03002238 err = mlx5_core_alloc_pd(to_mdev(ibdev)->mdev, &pd->pdn);
Eli Cohene126ba92013-07-07 17:25:49 +03002239 if (err) {
2240 kfree(pd);
2241 return ERR_PTR(err);
2242 }
2243
2244 if (context) {
2245 resp.pdn = pd->pdn;
2246 if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {
Jack Morgenstein9603b612014-07-28 23:30:22 +03002247 mlx5_core_dealloc_pd(to_mdev(ibdev)->mdev, pd->pdn);
Eli Cohene126ba92013-07-07 17:25:49 +03002248 kfree(pd);
2249 return ERR_PTR(-EFAULT);
2250 }
Eli Cohene126ba92013-07-07 17:25:49 +03002251 }
2252
2253 return &pd->ibpd;
2254}
2255
2256static int mlx5_ib_dealloc_pd(struct ib_pd *pd)
2257{
2258 struct mlx5_ib_dev *mdev = to_mdev(pd->device);
2259 struct mlx5_ib_pd *mpd = to_mpd(pd);
2260
Jack Morgenstein9603b612014-07-28 23:30:22 +03002261 mlx5_core_dealloc_pd(mdev->mdev, mpd->pdn);
Eli Cohene126ba92013-07-07 17:25:49 +03002262 kfree(mpd);
2263
2264 return 0;
2265}
2266
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002267enum {
2268 MATCH_CRITERIA_ENABLE_OUTER_BIT,
2269 MATCH_CRITERIA_ENABLE_MISC_BIT,
2270 MATCH_CRITERIA_ENABLE_INNER_BIT
2271};
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002272
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002273#define HEADER_IS_ZERO(match_criteria, headers) \
2274 !(memchr_inv(MLX5_ADDR_OF(fte_match_param, match_criteria, headers), \
2275 0, MLX5_FLD_SZ_BYTES(fte_match_param, headers))) \
2276
2277static u8 get_match_criteria_enable(u32 *match_criteria)
2278{
2279 u8 match_criteria_enable;
2280
2281 match_criteria_enable =
2282 (!HEADER_IS_ZERO(match_criteria, outer_headers)) <<
2283 MATCH_CRITERIA_ENABLE_OUTER_BIT;
2284 match_criteria_enable |=
2285 (!HEADER_IS_ZERO(match_criteria, misc_parameters)) <<
2286 MATCH_CRITERIA_ENABLE_MISC_BIT;
2287 match_criteria_enable |=
2288 (!HEADER_IS_ZERO(match_criteria, inner_headers)) <<
2289 MATCH_CRITERIA_ENABLE_INNER_BIT;
2290
2291 return match_criteria_enable;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002292}
2293
Maor Gottliebca0d4752016-08-30 16:58:35 +03002294static void set_proto(void *outer_c, void *outer_v, u8 mask, u8 val)
2295{
2296 MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_protocol, mask);
2297 MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_protocol, val);
2298}
2299
Moses Reuben2d1e6972016-11-14 19:04:52 +02002300static void set_flow_label(void *misc_c, void *misc_v, u8 mask, u8 val,
2301 bool inner)
2302{
2303 if (inner) {
2304 MLX5_SET(fte_match_set_misc,
2305 misc_c, inner_ipv6_flow_label, mask);
2306 MLX5_SET(fte_match_set_misc,
2307 misc_v, inner_ipv6_flow_label, val);
2308 } else {
2309 MLX5_SET(fte_match_set_misc,
2310 misc_c, outer_ipv6_flow_label, mask);
2311 MLX5_SET(fte_match_set_misc,
2312 misc_v, outer_ipv6_flow_label, val);
2313 }
2314}
2315
Maor Gottliebca0d4752016-08-30 16:58:35 +03002316static void set_tos(void *outer_c, void *outer_v, u8 mask, u8 val)
2317{
2318 MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_ecn, mask);
2319 MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_ecn, val);
2320 MLX5_SET(fte_match_set_lyr_2_4, outer_c, ip_dscp, mask >> 2);
2321 MLX5_SET(fte_match_set_lyr_2_4, outer_v, ip_dscp, val >> 2);
2322}
2323
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002324#define LAST_ETH_FIELD vlan_tag
2325#define LAST_IB_FIELD sl
Maor Gottliebca0d4752016-08-30 16:58:35 +03002326#define LAST_IPV4_FIELD tos
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002327#define LAST_IPV6_FIELD traffic_class
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002328#define LAST_TCP_UDP_FIELD src_port
Moses Reubenffb30d82016-11-14 19:04:50 +02002329#define LAST_TUNNEL_FIELD tunnel_id
Moses Reuben2ac693f2017-01-18 14:59:50 +02002330#define LAST_FLOW_TAG_FIELD tag_id
Slava Shwartsmana22ed862017-04-03 13:13:52 +03002331#define LAST_DROP_FIELD size
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002332
2333/* Field is the last supported field */
2334#define FIELDS_NOT_SUPPORTED(filter, field)\
2335 memchr_inv((void *)&filter.field +\
2336 sizeof(filter.field), 0,\
2337 sizeof(filter) -\
2338 offsetof(typeof(filter), field) -\
2339 sizeof(filter.field))
2340
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002341static int parse_flow_flow_action(const union ib_flow_spec *ib_spec,
2342 const struct ib_flow_attr *flow_attr,
2343 struct mlx5_flow_act *action)
2344{
2345 struct mlx5_ib_flow_action *maction = to_mflow_act(ib_spec->action.act);
2346
2347 switch (maction->ib_action.type) {
2348 case IB_FLOW_ACTION_ESP:
2349 /* Currently only AES_GCM keymat is supported by the driver */
2350 action->esp_id = (uintptr_t)maction->esp_aes_gcm.ctx;
2351 action->action |= flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS ?
2352 MLX5_FLOW_CONTEXT_ACTION_ENCRYPT :
2353 MLX5_FLOW_CONTEXT_ACTION_DECRYPT;
2354 return 0;
2355 default:
2356 return -EOPNOTSUPP;
2357 }
2358}
2359
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002360static int parse_flow_attr(struct mlx5_core_dev *mdev, u32 *match_c,
2361 u32 *match_v, const union ib_flow_spec *ib_spec,
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002362 const struct ib_flow_attr *flow_attr,
Boris Pismenny075572d2017-08-16 09:33:30 +03002363 struct mlx5_flow_act *action)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002364{
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002365 void *misc_params_c = MLX5_ADDR_OF(fte_match_param, match_c,
2366 misc_parameters);
2367 void *misc_params_v = MLX5_ADDR_OF(fte_match_param, match_v,
2368 misc_parameters);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002369 void *headers_c;
2370 void *headers_v;
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002371 int match_ipv;
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002372 int ret;
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002373
Moses Reuben2d1e6972016-11-14 19:04:52 +02002374 if (ib_spec->type & IB_FLOW_SPEC_INNER) {
2375 headers_c = MLX5_ADDR_OF(fte_match_param, match_c,
2376 inner_headers);
2377 headers_v = MLX5_ADDR_OF(fte_match_param, match_v,
2378 inner_headers);
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002379 match_ipv = MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
2380 ft_field_support.inner_ip_version);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002381 } else {
2382 headers_c = MLX5_ADDR_OF(fte_match_param, match_c,
2383 outer_headers);
2384 headers_v = MLX5_ADDR_OF(fte_match_param, match_v,
2385 outer_headers);
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002386 match_ipv = MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
2387 ft_field_support.outer_ip_version);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002388 }
2389
2390 switch (ib_spec->type & ~IB_FLOW_SPEC_INNER) {
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002391 case IB_FLOW_SPEC_ETH:
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002392 if (FIELDS_NOT_SUPPORTED(ib_spec->eth.mask, LAST_ETH_FIELD))
Leon Romanovsky1ffd3a22017-01-18 14:59:51 +02002393 return -EOPNOTSUPP;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002394
Moses Reuben2d1e6972016-11-14 19:04:52 +02002395 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002396 dmac_47_16),
2397 ib_spec->eth.mask.dst_mac);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002398 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002399 dmac_47_16),
2400 ib_spec->eth.val.dst_mac);
2401
Moses Reuben2d1e6972016-11-14 19:04:52 +02002402 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
Maor Gottliebee3da802016-09-12 19:16:24 +03002403 smac_47_16),
2404 ib_spec->eth.mask.src_mac);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002405 ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
Maor Gottliebee3da802016-09-12 19:16:24 +03002406 smac_47_16),
2407 ib_spec->eth.val.src_mac);
2408
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002409 if (ib_spec->eth.mask.vlan_tag) {
Moses Reuben2d1e6972016-11-14 19:04:52 +02002410 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
Mohamad Haj Yahia10543362016-10-09 16:25:43 +03002411 cvlan_tag, 1);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002412 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Mohamad Haj Yahia10543362016-10-09 16:25:43 +03002413 cvlan_tag, 1);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002414
Moses Reuben2d1e6972016-11-14 19:04:52 +02002415 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002416 first_vid, ntohs(ib_spec->eth.mask.vlan_tag));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002417 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002418 first_vid, ntohs(ib_spec->eth.val.vlan_tag));
2419
Moses Reuben2d1e6972016-11-14 19:04:52 +02002420 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002421 first_cfi,
2422 ntohs(ib_spec->eth.mask.vlan_tag) >> 12);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002423 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002424 first_cfi,
2425 ntohs(ib_spec->eth.val.vlan_tag) >> 12);
2426
Moses Reuben2d1e6972016-11-14 19:04:52 +02002427 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002428 first_prio,
2429 ntohs(ib_spec->eth.mask.vlan_tag) >> 13);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002430 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002431 first_prio,
2432 ntohs(ib_spec->eth.val.vlan_tag) >> 13);
2433 }
Moses Reuben2d1e6972016-11-14 19:04:52 +02002434 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002435 ethertype, ntohs(ib_spec->eth.mask.ether_type));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002436 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002437 ethertype, ntohs(ib_spec->eth.val.ether_type));
2438 break;
2439 case IB_FLOW_SPEC_IPV4:
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002440 if (FIELDS_NOT_SUPPORTED(ib_spec->ipv4.mask, LAST_IPV4_FIELD))
Leon Romanovsky1ffd3a22017-01-18 14:59:51 +02002441 return -EOPNOTSUPP;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002442
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002443 if (match_ipv) {
2444 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
2445 ip_version, 0xf);
2446 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Boris Pismenny3346c482017-08-20 15:13:08 +03002447 ip_version, MLX5_FS_IPV4_VERSION);
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002448 } else {
2449 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
2450 ethertype, 0xffff);
2451 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
2452 ethertype, ETH_P_IP);
2453 }
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002454
Moses Reuben2d1e6972016-11-14 19:04:52 +02002455 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002456 src_ipv4_src_ipv6.ipv4_layout.ipv4),
2457 &ib_spec->ipv4.mask.src_ip,
2458 sizeof(ib_spec->ipv4.mask.src_ip));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002459 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002460 src_ipv4_src_ipv6.ipv4_layout.ipv4),
2461 &ib_spec->ipv4.val.src_ip,
2462 sizeof(ib_spec->ipv4.val.src_ip));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002463 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002464 dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
2465 &ib_spec->ipv4.mask.dst_ip,
2466 sizeof(ib_spec->ipv4.mask.dst_ip));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002467 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002468 dst_ipv4_dst_ipv6.ipv4_layout.ipv4),
2469 &ib_spec->ipv4.val.dst_ip,
2470 sizeof(ib_spec->ipv4.val.dst_ip));
Maor Gottliebca0d4752016-08-30 16:58:35 +03002471
Moses Reuben2d1e6972016-11-14 19:04:52 +02002472 set_tos(headers_c, headers_v,
Maor Gottliebca0d4752016-08-30 16:58:35 +03002473 ib_spec->ipv4.mask.tos, ib_spec->ipv4.val.tos);
2474
Moses Reuben2d1e6972016-11-14 19:04:52 +02002475 set_proto(headers_c, headers_v,
Maor Gottliebca0d4752016-08-30 16:58:35 +03002476 ib_spec->ipv4.mask.proto, ib_spec->ipv4.val.proto);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002477 break;
Maor Gottlieb026bae02016-06-17 15:14:51 +03002478 case IB_FLOW_SPEC_IPV6:
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002479 if (FIELDS_NOT_SUPPORTED(ib_spec->ipv6.mask, LAST_IPV6_FIELD))
Leon Romanovsky1ffd3a22017-01-18 14:59:51 +02002480 return -EOPNOTSUPP;
Maor Gottlieb026bae02016-06-17 15:14:51 +03002481
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002482 if (match_ipv) {
2483 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
2484 ip_version, 0xf);
2485 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
Boris Pismenny3346c482017-08-20 15:13:08 +03002486 ip_version, MLX5_FS_IPV6_VERSION);
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002487 } else {
2488 MLX5_SET(fte_match_set_lyr_2_4, headers_c,
2489 ethertype, 0xffff);
2490 MLX5_SET(fte_match_set_lyr_2_4, headers_v,
2491 ethertype, ETH_P_IPV6);
2492 }
Maor Gottlieb026bae02016-06-17 15:14:51 +03002493
Moses Reuben2d1e6972016-11-14 19:04:52 +02002494 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb026bae02016-06-17 15:14:51 +03002495 src_ipv4_src_ipv6.ipv6_layout.ipv6),
2496 &ib_spec->ipv6.mask.src_ip,
2497 sizeof(ib_spec->ipv6.mask.src_ip));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002498 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb026bae02016-06-17 15:14:51 +03002499 src_ipv4_src_ipv6.ipv6_layout.ipv6),
2500 &ib_spec->ipv6.val.src_ip,
2501 sizeof(ib_spec->ipv6.val.src_ip));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002502 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c,
Maor Gottlieb026bae02016-06-17 15:14:51 +03002503 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
2504 &ib_spec->ipv6.mask.dst_ip,
2505 sizeof(ib_spec->ipv6.mask.dst_ip));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002506 memcpy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
Maor Gottlieb026bae02016-06-17 15:14:51 +03002507 dst_ipv4_dst_ipv6.ipv6_layout.ipv6),
2508 &ib_spec->ipv6.val.dst_ip,
2509 sizeof(ib_spec->ipv6.val.dst_ip));
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002510
Moses Reuben2d1e6972016-11-14 19:04:52 +02002511 set_tos(headers_c, headers_v,
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002512 ib_spec->ipv6.mask.traffic_class,
2513 ib_spec->ipv6.val.traffic_class);
2514
Moses Reuben2d1e6972016-11-14 19:04:52 +02002515 set_proto(headers_c, headers_v,
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002516 ib_spec->ipv6.mask.next_hdr,
2517 ib_spec->ipv6.val.next_hdr);
2518
Moses Reuben2d1e6972016-11-14 19:04:52 +02002519 set_flow_label(misc_params_c, misc_params_v,
2520 ntohl(ib_spec->ipv6.mask.flow_label),
2521 ntohl(ib_spec->ipv6.val.flow_label),
2522 ib_spec->type & IB_FLOW_SPEC_INNER);
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002523 break;
2524 case IB_FLOW_SPEC_ESP:
2525 if (ib_spec->esp.mask.seq)
2526 return -EOPNOTSUPP;
Moses Reuben2d1e6972016-11-14 19:04:52 +02002527
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002528 MLX5_SET(fte_match_set_misc, misc_params_c, outer_esp_spi,
2529 ntohl(ib_spec->esp.mask.spi));
2530 MLX5_SET(fte_match_set_misc, misc_params_v, outer_esp_spi,
2531 ntohl(ib_spec->esp.val.spi));
Maor Gottlieb026bae02016-06-17 15:14:51 +03002532 break;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002533 case IB_FLOW_SPEC_TCP:
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002534 if (FIELDS_NOT_SUPPORTED(ib_spec->tcp_udp.mask,
2535 LAST_TCP_UDP_FIELD))
Leon Romanovsky1ffd3a22017-01-18 14:59:51 +02002536 return -EOPNOTSUPP;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002537
Moses Reuben2d1e6972016-11-14 19:04:52 +02002538 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002539 0xff);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002540 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002541 IPPROTO_TCP);
2542
Moses Reuben2d1e6972016-11-14 19:04:52 +02002543 MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_sport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002544 ntohs(ib_spec->tcp_udp.mask.src_port));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002545 MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_sport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002546 ntohs(ib_spec->tcp_udp.val.src_port));
2547
Moses Reuben2d1e6972016-11-14 19:04:52 +02002548 MLX5_SET(fte_match_set_lyr_2_4, headers_c, tcp_dport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002549 ntohs(ib_spec->tcp_udp.mask.dst_port));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002550 MLX5_SET(fte_match_set_lyr_2_4, headers_v, tcp_dport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002551 ntohs(ib_spec->tcp_udp.val.dst_port));
2552 break;
2553 case IB_FLOW_SPEC_UDP:
Maor Gottliebc47ac6a2016-08-30 16:58:31 +03002554 if (FIELDS_NOT_SUPPORTED(ib_spec->tcp_udp.mask,
2555 LAST_TCP_UDP_FIELD))
Leon Romanovsky1ffd3a22017-01-18 14:59:51 +02002556 return -EOPNOTSUPP;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002557
Moses Reuben2d1e6972016-11-14 19:04:52 +02002558 MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002559 0xff);
Moses Reuben2d1e6972016-11-14 19:04:52 +02002560 MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002561 IPPROTO_UDP);
2562
Moses Reuben2d1e6972016-11-14 19:04:52 +02002563 MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_sport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002564 ntohs(ib_spec->tcp_udp.mask.src_port));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002565 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_sport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002566 ntohs(ib_spec->tcp_udp.val.src_port));
2567
Moses Reuben2d1e6972016-11-14 19:04:52 +02002568 MLX5_SET(fte_match_set_lyr_2_4, headers_c, udp_dport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002569 ntohs(ib_spec->tcp_udp.mask.dst_port));
Moses Reuben2d1e6972016-11-14 19:04:52 +02002570 MLX5_SET(fte_match_set_lyr_2_4, headers_v, udp_dport,
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002571 ntohs(ib_spec->tcp_udp.val.dst_port));
2572 break;
Moses Reubenffb30d82016-11-14 19:04:50 +02002573 case IB_FLOW_SPEC_VXLAN_TUNNEL:
2574 if (FIELDS_NOT_SUPPORTED(ib_spec->tunnel.mask,
2575 LAST_TUNNEL_FIELD))
Leon Romanovsky1ffd3a22017-01-18 14:59:51 +02002576 return -EOPNOTSUPP;
Moses Reubenffb30d82016-11-14 19:04:50 +02002577
2578 MLX5_SET(fte_match_set_misc, misc_params_c, vxlan_vni,
2579 ntohl(ib_spec->tunnel.mask.tunnel_id));
2580 MLX5_SET(fte_match_set_misc, misc_params_v, vxlan_vni,
2581 ntohl(ib_spec->tunnel.val.tunnel_id));
2582 break;
Moses Reuben2ac693f2017-01-18 14:59:50 +02002583 case IB_FLOW_SPEC_ACTION_TAG:
2584 if (FIELDS_NOT_SUPPORTED(ib_spec->flow_tag,
2585 LAST_FLOW_TAG_FIELD))
2586 return -EOPNOTSUPP;
2587 if (ib_spec->flow_tag.tag_id >= BIT(24))
2588 return -EINVAL;
2589
Boris Pismenny075572d2017-08-16 09:33:30 +03002590 action->flow_tag = ib_spec->flow_tag.tag_id;
Matan Baraka9db0ec2017-08-16 09:43:48 +03002591 action->has_flow_tag = true;
Moses Reuben2ac693f2017-01-18 14:59:50 +02002592 break;
Slava Shwartsmana22ed862017-04-03 13:13:52 +03002593 case IB_FLOW_SPEC_ACTION_DROP:
2594 if (FIELDS_NOT_SUPPORTED(ib_spec->drop,
2595 LAST_DROP_FIELD))
2596 return -EOPNOTSUPP;
Boris Pismenny075572d2017-08-16 09:33:30 +03002597 action->action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
Slava Shwartsmana22ed862017-04-03 13:13:52 +03002598 break;
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002599 case IB_FLOW_SPEC_ACTION_HANDLE:
2600 ret = parse_flow_flow_action(ib_spec, flow_attr, action);
2601 if (ret)
2602 return ret;
2603 break;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002604 default:
2605 return -EINVAL;
2606 }
2607
2608 return 0;
2609}
2610
2611/* If a flow could catch both multicast and unicast packets,
2612 * it won't fall into the multicast flow steering table and this rule
2613 * could steal other multicast packets.
2614 */
Yishai Hadasa550ddf2017-08-17 15:52:33 +03002615static bool flow_is_multicast_only(const struct ib_flow_attr *ib_attr)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002616{
Yishai Hadas81e30882017-06-08 16:15:09 +03002617 union ib_flow_spec *flow_spec;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002618
2619 if (ib_attr->type != IB_FLOW_ATTR_NORMAL ||
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002620 ib_attr->num_of_specs < 1)
2621 return false;
2622
Yishai Hadas81e30882017-06-08 16:15:09 +03002623 flow_spec = (union ib_flow_spec *)(ib_attr + 1);
2624 if (flow_spec->type == IB_FLOW_SPEC_IPV4) {
2625 struct ib_flow_spec_ipv4 *ipv4_spec;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002626
Yishai Hadas81e30882017-06-08 16:15:09 +03002627 ipv4_spec = (struct ib_flow_spec_ipv4 *)flow_spec;
2628 if (ipv4_is_multicast(ipv4_spec->val.dst_ip))
2629 return true;
2630
2631 return false;
2632 }
2633
2634 if (flow_spec->type == IB_FLOW_SPEC_ETH) {
2635 struct ib_flow_spec_eth *eth_spec;
2636
2637 eth_spec = (struct ib_flow_spec_eth *)flow_spec;
2638 return is_multicast_ether_addr(eth_spec->mask.dst_mac) &&
2639 is_multicast_ether_addr(eth_spec->val.dst_mac);
2640 }
2641
2642 return false;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002643}
2644
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002645enum valid_spec {
2646 VALID_SPEC_INVALID,
2647 VALID_SPEC_VALID,
2648 VALID_SPEC_NA,
2649};
2650
2651static enum valid_spec
2652is_valid_esp_aes_gcm(struct mlx5_core_dev *mdev,
2653 const struct mlx5_flow_spec *spec,
2654 const struct mlx5_flow_act *flow_act,
2655 bool egress)
2656{
2657 const u32 *match_c = spec->match_criteria;
2658 bool is_crypto =
2659 (flow_act->action & (MLX5_FLOW_CONTEXT_ACTION_ENCRYPT |
2660 MLX5_FLOW_CONTEXT_ACTION_DECRYPT));
2661 bool is_ipsec = mlx5_fs_is_ipsec_flow(match_c);
2662 bool is_drop = flow_act->action & MLX5_FLOW_CONTEXT_ACTION_DROP;
2663
2664 /*
2665 * Currently only crypto is supported in egress, when regular egress
2666 * rules would be supported, always return VALID_SPEC_NA.
2667 */
2668 if (!is_crypto)
2669 return egress ? VALID_SPEC_INVALID : VALID_SPEC_NA;
2670
2671 return is_crypto && is_ipsec &&
2672 (!egress || (!is_drop && !flow_act->has_flow_tag)) ?
2673 VALID_SPEC_VALID : VALID_SPEC_INVALID;
2674}
2675
2676static bool is_valid_spec(struct mlx5_core_dev *mdev,
2677 const struct mlx5_flow_spec *spec,
2678 const struct mlx5_flow_act *flow_act,
2679 bool egress)
2680{
2681 /* We curretly only support ipsec egress flow */
2682 return is_valid_esp_aes_gcm(mdev, spec, flow_act, egress) != VALID_SPEC_INVALID;
2683}
2684
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002685static bool is_valid_ethertype(struct mlx5_core_dev *mdev,
2686 const struct ib_flow_attr *flow_attr,
Ariel Levkovich0f750962017-04-03 13:11:02 +03002687 bool check_inner)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002688{
2689 union ib_flow_spec *ib_spec = (union ib_flow_spec *)(flow_attr + 1);
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002690 int match_ipv = check_inner ?
2691 MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
2692 ft_field_support.inner_ip_version) :
2693 MLX5_CAP_FLOWTABLE_NIC_RX(mdev,
2694 ft_field_support.outer_ip_version);
Ariel Levkovich0f750962017-04-03 13:11:02 +03002695 int inner_bit = check_inner ? IB_FLOW_SPEC_INNER : 0;
2696 bool ipv4_spec_valid, ipv6_spec_valid;
2697 unsigned int ip_spec_type = 0;
2698 bool has_ethertype = false;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002699 unsigned int spec_index;
Ariel Levkovich0f750962017-04-03 13:11:02 +03002700 bool mask_valid = true;
2701 u16 eth_type = 0;
2702 bool type_valid;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002703
2704 /* Validate that ethertype is correct */
2705 for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
Ariel Levkovich0f750962017-04-03 13:11:02 +03002706 if ((ib_spec->type == (IB_FLOW_SPEC_ETH | inner_bit)) &&
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002707 ib_spec->eth.mask.ether_type) {
Ariel Levkovich0f750962017-04-03 13:11:02 +03002708 mask_valid = (ib_spec->eth.mask.ether_type ==
2709 htons(0xffff));
2710 has_ethertype = true;
2711 eth_type = ntohs(ib_spec->eth.val.ether_type);
2712 } else if ((ib_spec->type == (IB_FLOW_SPEC_IPV4 | inner_bit)) ||
2713 (ib_spec->type == (IB_FLOW_SPEC_IPV6 | inner_bit))) {
2714 ip_spec_type = ib_spec->type;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002715 }
2716 ib_spec = (void *)ib_spec + ib_spec->size;
2717 }
Ariel Levkovich0f750962017-04-03 13:11:02 +03002718
2719 type_valid = (!has_ethertype) || (!ip_spec_type);
2720 if (!type_valid && mask_valid) {
2721 ipv4_spec_valid = (eth_type == ETH_P_IP) &&
2722 (ip_spec_type == (IB_FLOW_SPEC_IPV4 | inner_bit));
2723 ipv6_spec_valid = (eth_type == ETH_P_IPV6) &&
2724 (ip_spec_type == (IB_FLOW_SPEC_IPV6 | inner_bit));
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002725
2726 type_valid = (ipv4_spec_valid) || (ipv6_spec_valid) ||
2727 (((eth_type == ETH_P_MPLS_UC) ||
2728 (eth_type == ETH_P_MPLS_MC)) && match_ipv);
Ariel Levkovich0f750962017-04-03 13:11:02 +03002729 }
2730
2731 return type_valid;
2732}
2733
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002734static bool is_valid_attr(struct mlx5_core_dev *mdev,
2735 const struct ib_flow_attr *flow_attr)
Ariel Levkovich0f750962017-04-03 13:11:02 +03002736{
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002737 return is_valid_ethertype(mdev, flow_attr, false) &&
2738 is_valid_ethertype(mdev, flow_attr, true);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002739}
2740
2741static void put_flow_table(struct mlx5_ib_dev *dev,
2742 struct mlx5_ib_flow_prio *prio, bool ft_added)
2743{
2744 prio->refcount -= !!ft_added;
2745 if (!prio->refcount) {
2746 mlx5_destroy_flow_table(prio->flow_table);
2747 prio->flow_table = NULL;
2748 }
2749}
2750
2751static int mlx5_ib_destroy_flow(struct ib_flow *flow_id)
2752{
2753 struct mlx5_ib_dev *dev = to_mdev(flow_id->qp->device);
2754 struct mlx5_ib_flow_handler *handler = container_of(flow_id,
2755 struct mlx5_ib_flow_handler,
2756 ibflow);
2757 struct mlx5_ib_flow_handler *iter, *tmp;
2758
Mark Bloch9a4ca382018-01-16 14:42:35 +00002759 mutex_lock(&dev->flow_db->lock);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002760
2761 list_for_each_entry_safe(iter, tmp, &handler->list, list) {
Mark Bloch74491de2016-08-31 11:24:25 +00002762 mlx5_del_flow_rules(iter->rule);
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03002763 put_flow_table(dev, iter->prio, true);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002764 list_del(&iter->list);
2765 kfree(iter);
2766 }
2767
Mark Bloch74491de2016-08-31 11:24:25 +00002768 mlx5_del_flow_rules(handler->rule);
Maor Gottlieb5497adc2016-08-28 14:16:31 +03002769 put_flow_table(dev, handler->prio, true);
Mark Bloch9a4ca382018-01-16 14:42:35 +00002770 mutex_unlock(&dev->flow_db->lock);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002771
2772 kfree(handler);
2773
2774 return 0;
2775}
2776
Maor Gottlieb35d190112016-03-07 18:51:47 +02002777static int ib_prio_to_core_prio(unsigned int priority, bool dont_trap)
2778{
2779 priority *= 2;
2780 if (!dont_trap)
2781 priority++;
2782 return priority;
2783}
2784
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03002785enum flow_table_type {
2786 MLX5_IB_FT_RX,
2787 MLX5_IB_FT_TX
2788};
2789
Maor Gottlieb00b7c2a2017-03-29 06:09:01 +03002790#define MLX5_FS_MAX_TYPES 6
2791#define MLX5_FS_MAX_ENTRIES BIT(16)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002792static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03002793 struct ib_flow_attr *flow_attr,
2794 enum flow_table_type ft_type)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002795{
Maor Gottlieb35d190112016-03-07 18:51:47 +02002796 bool dont_trap = flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002797 struct mlx5_flow_namespace *ns = NULL;
2798 struct mlx5_ib_flow_prio *prio;
2799 struct mlx5_flow_table *ft;
Maor Gottliebdac388e2017-03-29 06:09:00 +03002800 int max_table_size;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002801 int num_entries;
2802 int num_groups;
2803 int priority;
2804 int err = 0;
2805
Maor Gottliebdac388e2017-03-29 06:09:00 +03002806 max_table_size = BIT(MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
2807 log_max_ft_size));
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002808 if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002809 if (ft_type == MLX5_IB_FT_TX)
2810 priority = 0;
2811 else if (flow_is_multicast_only(flow_attr) &&
2812 !dont_trap)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002813 priority = MLX5_IB_FLOW_MCAST_PRIO;
2814 else
Maor Gottlieb35d190112016-03-07 18:51:47 +02002815 priority = ib_prio_to_core_prio(flow_attr->priority,
2816 dont_trap);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002817 ns = mlx5_get_flow_namespace(dev->mdev,
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002818 ft_type == MLX5_IB_FT_TX ?
2819 MLX5_FLOW_NAMESPACE_EGRESS :
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002820 MLX5_FLOW_NAMESPACE_BYPASS);
2821 num_entries = MLX5_FS_MAX_ENTRIES;
2822 num_groups = MLX5_FS_MAX_TYPES;
Mark Bloch9a4ca382018-01-16 14:42:35 +00002823 prio = &dev->flow_db->prios[priority];
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002824 } else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
2825 flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) {
2826 ns = mlx5_get_flow_namespace(dev->mdev,
2827 MLX5_FLOW_NAMESPACE_LEFTOVERS);
2828 build_leftovers_ft_param(&priority,
2829 &num_entries,
2830 &num_groups);
Mark Bloch9a4ca382018-01-16 14:42:35 +00002831 prio = &dev->flow_db->prios[MLX5_IB_FLOW_LEFTOVERS_PRIO];
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03002832 } else if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) {
2833 if (!MLX5_CAP_FLOWTABLE(dev->mdev,
2834 allow_sniffer_and_nic_rx_shared_tir))
2835 return ERR_PTR(-ENOTSUPP);
2836
2837 ns = mlx5_get_flow_namespace(dev->mdev, ft_type == MLX5_IB_FT_RX ?
2838 MLX5_FLOW_NAMESPACE_SNIFFER_RX :
2839 MLX5_FLOW_NAMESPACE_SNIFFER_TX);
2840
Mark Bloch9a4ca382018-01-16 14:42:35 +00002841 prio = &dev->flow_db->sniffer[ft_type];
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03002842 priority = 0;
2843 num_entries = 1;
2844 num_groups = 1;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002845 }
2846
2847 if (!ns)
2848 return ERR_PTR(-ENOTSUPP);
2849
Maor Gottliebdac388e2017-03-29 06:09:00 +03002850 if (num_entries > max_table_size)
2851 return ERR_PTR(-ENOMEM);
2852
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002853 ft = prio->flow_table;
2854 if (!ft) {
2855 ft = mlx5_create_auto_grouped_flow_table(ns, priority,
2856 num_entries,
Maor Gottliebd63cd282016-04-29 01:36:35 +03002857 num_groups,
Hadar Hen Zionc9f1b072016-11-07 15:14:44 +02002858 0, 0);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002859
2860 if (!IS_ERR(ft)) {
2861 prio->refcount = 0;
2862 prio->flow_table = ft;
2863 } else {
2864 err = PTR_ERR(ft);
2865 }
2866 }
2867
2868 return err ? ERR_PTR(err) : prio;
2869}
2870
Yishai Hadasa550ddf2017-08-17 15:52:33 +03002871static void set_underlay_qp(struct mlx5_ib_dev *dev,
2872 struct mlx5_flow_spec *spec,
2873 u32 underlay_qpn)
2874{
2875 void *misc_params_c = MLX5_ADDR_OF(fte_match_param,
2876 spec->match_criteria,
2877 misc_parameters);
2878 void *misc_params_v = MLX5_ADDR_OF(fte_match_param, spec->match_value,
2879 misc_parameters);
2880
2881 if (underlay_qpn &&
2882 MLX5_CAP_FLOWTABLE_NIC_RX(dev->mdev,
2883 ft_field_support.bth_dst_qp)) {
2884 MLX5_SET(fte_match_set_misc,
2885 misc_params_v, bth_dst_qp, underlay_qpn);
2886 MLX5_SET(fte_match_set_misc,
2887 misc_params_c, bth_dst_qp, 0xffffff);
2888 }
2889}
2890
2891static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
2892 struct mlx5_ib_flow_prio *ft_prio,
2893 const struct ib_flow_attr *flow_attr,
2894 struct mlx5_flow_destination *dst,
2895 u32 underlay_qpn)
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002896{
2897 struct mlx5_flow_table *ft = ft_prio->flow_table;
2898 struct mlx5_ib_flow_handler *handler;
Boris Pismenny075572d2017-08-16 09:33:30 +03002899 struct mlx5_flow_act flow_act = {.flow_tag = MLX5_FS_DEFAULT_FLOW_TAG};
Maor Gottliebc5bb1732016-07-04 17:23:05 +03002900 struct mlx5_flow_spec *spec;
Slava Shwartsmana22ed862017-04-03 13:13:52 +03002901 struct mlx5_flow_destination *rule_dst = dst;
Maor Gottliebdd063d02016-08-28 14:16:32 +03002902 const void *ib_flow = (const void *)flow_attr + sizeof(*flow_attr);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002903 unsigned int spec_index;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002904 int err = 0;
Slava Shwartsmana22ed862017-04-03 13:13:52 +03002905 int dest_num = 1;
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002906 bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002907
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002908 if (!is_valid_attr(dev->mdev, flow_attr))
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002909 return ERR_PTR(-EINVAL);
2910
Leon Romanovsky1b9a07e2017-05-10 21:32:18 +03002911 spec = kvzalloc(sizeof(*spec), GFP_KERNEL);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002912 handler = kzalloc(sizeof(*handler), GFP_KERNEL);
Maor Gottliebc5bb1732016-07-04 17:23:05 +03002913 if (!handler || !spec) {
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002914 err = -ENOMEM;
2915 goto free;
2916 }
2917
2918 INIT_LIST_HEAD(&handler->list);
2919
2920 for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
Ariel Levkovich19cc7522017-04-03 13:11:03 +03002921 err = parse_flow_attr(dev->mdev, spec->match_criteria,
Slava Shwartsmana22ed862017-04-03 13:13:52 +03002922 spec->match_value,
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002923 ib_flow, flow_attr, &flow_act);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002924 if (err < 0)
2925 goto free;
2926
2927 ib_flow += ((union ib_flow_spec *)ib_flow)->size;
2928 }
2929
Yishai Hadasa550ddf2017-08-17 15:52:33 +03002930 if (!flow_is_multicast_only(flow_attr))
2931 set_underlay_qp(dev, spec, underlay_qpn);
2932
Mark Bloch018a94e2018-01-16 14:44:29 +00002933 if (dev->rep) {
2934 void *misc;
2935
2936 misc = MLX5_ADDR_OF(fte_match_param, spec->match_value,
2937 misc_parameters);
2938 MLX5_SET(fte_match_set_misc, misc, source_port,
2939 dev->rep->vport);
2940 misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
2941 misc_parameters);
2942 MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
2943 }
2944
Maor Gottlieb466fa6d2016-08-30 16:58:36 +03002945 spec->match_criteria_enable = get_match_criteria_enable(spec->match_criteria);
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002946
2947 if (is_egress &&
2948 !is_valid_spec(dev->mdev, spec, &flow_act, is_egress)) {
2949 err = -EINVAL;
2950 goto free;
2951 }
2952
Boris Pismenny075572d2017-08-16 09:33:30 +03002953 if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP) {
Slava Shwartsmana22ed862017-04-03 13:13:52 +03002954 rule_dst = NULL;
2955 dest_num = 0;
2956 } else {
Aviad Yehezkel802c2122018-03-28 09:27:53 +03002957 if (is_egress)
2958 flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW;
2959 else
2960 flow_act.action |=
2961 dst ? MLX5_FLOW_CONTEXT_ACTION_FWD_DEST :
2962 MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO;
Slava Shwartsmana22ed862017-04-03 13:13:52 +03002963 }
Moses Reuben2ac693f2017-01-18 14:59:50 +02002964
Matan Baraka9db0ec2017-08-16 09:43:48 +03002965 if (flow_act.has_flow_tag &&
Moses Reuben2ac693f2017-01-18 14:59:50 +02002966 (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
2967 flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT)) {
2968 mlx5_ib_warn(dev, "Flow tag %u and attribute type %x isn't allowed in leftovers\n",
Boris Pismenny075572d2017-08-16 09:33:30 +03002969 flow_act.flow_tag, flow_attr->type);
Moses Reuben2ac693f2017-01-18 14:59:50 +02002970 err = -EINVAL;
2971 goto free;
2972 }
Mark Bloch74491de2016-08-31 11:24:25 +00002973 handler->rule = mlx5_add_flow_rules(ft, spec,
Hadar Hen Zion66958ed2016-11-07 15:14:45 +02002974 &flow_act,
Slava Shwartsmana22ed862017-04-03 13:13:52 +03002975 rule_dst, dest_num);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002976
2977 if (IS_ERR(handler->rule)) {
2978 err = PTR_ERR(handler->rule);
2979 goto free;
2980 }
2981
Maor Gottliebd9d49802016-08-28 14:16:33 +03002982 ft_prio->refcount++;
Maor Gottlieb5497adc2016-08-28 14:16:31 +03002983 handler->prio = ft_prio;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002984
2985 ft_prio->flow_table = ft;
2986free:
2987 if (err)
2988 kfree(handler);
Maor Gottliebc5bb1732016-07-04 17:23:05 +03002989 kvfree(spec);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02002990 return err ? ERR_PTR(err) : handler;
2991}
2992
Yishai Hadasa550ddf2017-08-17 15:52:33 +03002993static struct mlx5_ib_flow_handler *create_flow_rule(struct mlx5_ib_dev *dev,
2994 struct mlx5_ib_flow_prio *ft_prio,
2995 const struct ib_flow_attr *flow_attr,
2996 struct mlx5_flow_destination *dst)
2997{
2998 return _create_flow_rule(dev, ft_prio, flow_attr, dst, 0);
2999}
3000
Maor Gottlieb35d190112016-03-07 18:51:47 +02003001static struct mlx5_ib_flow_handler *create_dont_trap_rule(struct mlx5_ib_dev *dev,
3002 struct mlx5_ib_flow_prio *ft_prio,
3003 struct ib_flow_attr *flow_attr,
3004 struct mlx5_flow_destination *dst)
3005{
3006 struct mlx5_ib_flow_handler *handler_dst = NULL;
3007 struct mlx5_ib_flow_handler *handler = NULL;
3008
3009 handler = create_flow_rule(dev, ft_prio, flow_attr, NULL);
3010 if (!IS_ERR(handler)) {
3011 handler_dst = create_flow_rule(dev, ft_prio,
3012 flow_attr, dst);
3013 if (IS_ERR(handler_dst)) {
Mark Bloch74491de2016-08-31 11:24:25 +00003014 mlx5_del_flow_rules(handler->rule);
Maor Gottliebd9d49802016-08-28 14:16:33 +03003015 ft_prio->refcount--;
Maor Gottlieb35d190112016-03-07 18:51:47 +02003016 kfree(handler);
3017 handler = handler_dst;
3018 } else {
3019 list_add(&handler_dst->list, &handler->list);
3020 }
3021 }
3022
3023 return handler;
3024}
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003025enum {
3026 LEFTOVERS_MC,
3027 LEFTOVERS_UC,
3028};
3029
3030static struct mlx5_ib_flow_handler *create_leftovers_rule(struct mlx5_ib_dev *dev,
3031 struct mlx5_ib_flow_prio *ft_prio,
3032 struct ib_flow_attr *flow_attr,
3033 struct mlx5_flow_destination *dst)
3034{
3035 struct mlx5_ib_flow_handler *handler_ucast = NULL;
3036 struct mlx5_ib_flow_handler *handler = NULL;
3037
3038 static struct {
3039 struct ib_flow_attr flow_attr;
3040 struct ib_flow_spec_eth eth_flow;
3041 } leftovers_specs[] = {
3042 [LEFTOVERS_MC] = {
3043 .flow_attr = {
3044 .num_of_specs = 1,
3045 .size = sizeof(leftovers_specs[0])
3046 },
3047 .eth_flow = {
3048 .type = IB_FLOW_SPEC_ETH,
3049 .size = sizeof(struct ib_flow_spec_eth),
3050 .mask = {.dst_mac = {0x1} },
3051 .val = {.dst_mac = {0x1} }
3052 }
3053 },
3054 [LEFTOVERS_UC] = {
3055 .flow_attr = {
3056 .num_of_specs = 1,
3057 .size = sizeof(leftovers_specs[0])
3058 },
3059 .eth_flow = {
3060 .type = IB_FLOW_SPEC_ETH,
3061 .size = sizeof(struct ib_flow_spec_eth),
3062 .mask = {.dst_mac = {0x1} },
3063 .val = {.dst_mac = {} }
3064 }
3065 }
3066 };
3067
3068 handler = create_flow_rule(dev, ft_prio,
3069 &leftovers_specs[LEFTOVERS_MC].flow_attr,
3070 dst);
3071 if (!IS_ERR(handler) &&
3072 flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT) {
3073 handler_ucast = create_flow_rule(dev, ft_prio,
3074 &leftovers_specs[LEFTOVERS_UC].flow_attr,
3075 dst);
3076 if (IS_ERR(handler_ucast)) {
Mark Bloch74491de2016-08-31 11:24:25 +00003077 mlx5_del_flow_rules(handler->rule);
Maor Gottliebd9d49802016-08-28 14:16:33 +03003078 ft_prio->refcount--;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003079 kfree(handler);
3080 handler = handler_ucast;
3081 } else {
3082 list_add(&handler_ucast->list, &handler->list);
3083 }
3084 }
3085
3086 return handler;
3087}
3088
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003089static struct mlx5_ib_flow_handler *create_sniffer_rule(struct mlx5_ib_dev *dev,
3090 struct mlx5_ib_flow_prio *ft_rx,
3091 struct mlx5_ib_flow_prio *ft_tx,
3092 struct mlx5_flow_destination *dst)
3093{
3094 struct mlx5_ib_flow_handler *handler_rx;
3095 struct mlx5_ib_flow_handler *handler_tx;
3096 int err;
3097 static const struct ib_flow_attr flow_attr = {
3098 .num_of_specs = 0,
3099 .size = sizeof(flow_attr)
3100 };
3101
3102 handler_rx = create_flow_rule(dev, ft_rx, &flow_attr, dst);
3103 if (IS_ERR(handler_rx)) {
3104 err = PTR_ERR(handler_rx);
3105 goto err;
3106 }
3107
3108 handler_tx = create_flow_rule(dev, ft_tx, &flow_attr, dst);
3109 if (IS_ERR(handler_tx)) {
3110 err = PTR_ERR(handler_tx);
3111 goto err_tx;
3112 }
3113
3114 list_add(&handler_tx->list, &handler_rx->list);
3115
3116 return handler_rx;
3117
3118err_tx:
Mark Bloch74491de2016-08-31 11:24:25 +00003119 mlx5_del_flow_rules(handler_rx->rule);
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003120 ft_rx->refcount--;
3121 kfree(handler_rx);
3122err:
3123 return ERR_PTR(err);
3124}
3125
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003126static struct ib_flow *mlx5_ib_create_flow(struct ib_qp *qp,
3127 struct ib_flow_attr *flow_attr,
3128 int domain)
3129{
3130 struct mlx5_ib_dev *dev = to_mdev(qp->device);
Yishai Hadasd9f88e52016-08-28 10:58:37 +03003131 struct mlx5_ib_qp *mqp = to_mqp(qp);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003132 struct mlx5_ib_flow_handler *handler = NULL;
3133 struct mlx5_flow_destination *dst = NULL;
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003134 struct mlx5_ib_flow_prio *ft_prio_tx = NULL;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003135 struct mlx5_ib_flow_prio *ft_prio;
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003136 bool is_egress = flow_attr->flags & IB_FLOW_ATTR_FLAGS_EGRESS;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003137 int err;
Yishai Hadasa550ddf2017-08-17 15:52:33 +03003138 int underlay_qpn;
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003139
3140 if (flow_attr->priority > MLX5_IB_FLOW_LAST_PRIO)
Maor Gottliebdac388e2017-03-29 06:09:00 +03003141 return ERR_PTR(-ENOMEM);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003142
3143 if (domain != IB_FLOW_DOMAIN_USER ||
Daniel Jurgens508562d2018-01-04 17:25:34 +02003144 flow_attr->port > dev->num_ports ||
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003145 (flow_attr->flags & ~(IB_FLOW_ATTR_FLAGS_DONT_TRAP |
3146 IB_FLOW_ATTR_FLAGS_EGRESS)))
3147 return ERR_PTR(-EINVAL);
3148
3149 if (is_egress &&
3150 (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
3151 flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT))
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003152 return ERR_PTR(-EINVAL);
3153
3154 dst = kzalloc(sizeof(*dst), GFP_KERNEL);
3155 if (!dst)
3156 return ERR_PTR(-ENOMEM);
3157
Mark Bloch9a4ca382018-01-16 14:42:35 +00003158 mutex_lock(&dev->flow_db->lock);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003159
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003160 ft_prio = get_flow_table(dev, flow_attr,
3161 is_egress ? MLX5_IB_FT_TX : MLX5_IB_FT_RX);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003162 if (IS_ERR(ft_prio)) {
3163 err = PTR_ERR(ft_prio);
3164 goto unlock;
3165 }
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003166 if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) {
3167 ft_prio_tx = get_flow_table(dev, flow_attr, MLX5_IB_FT_TX);
3168 if (IS_ERR(ft_prio_tx)) {
3169 err = PTR_ERR(ft_prio_tx);
3170 ft_prio_tx = NULL;
3171 goto destroy_ft;
3172 }
3173 }
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003174
Aviad Yehezkel802c2122018-03-28 09:27:53 +03003175 if (is_egress) {
3176 dst->type = MLX5_FLOW_DESTINATION_TYPE_PORT;
3177 } else {
3178 dst->type = MLX5_FLOW_DESTINATION_TYPE_TIR;
3179 if (mqp->flags & MLX5_IB_QP_RSS)
3180 dst->tir_num = mqp->rss_qp.tirn;
3181 else
3182 dst->tir_num = mqp->raw_packet_qp.rq.tirn;
3183 }
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003184
3185 if (flow_attr->type == IB_FLOW_ATTR_NORMAL) {
Maor Gottlieb35d190112016-03-07 18:51:47 +02003186 if (flow_attr->flags & IB_FLOW_ATTR_FLAGS_DONT_TRAP) {
3187 handler = create_dont_trap_rule(dev, ft_prio,
3188 flow_attr, dst);
3189 } else {
Yishai Hadasa550ddf2017-08-17 15:52:33 +03003190 underlay_qpn = (mqp->flags & MLX5_IB_QP_UNDERLAY) ?
3191 mqp->underlay_qpn : 0;
3192 handler = _create_flow_rule(dev, ft_prio, flow_attr,
3193 dst, underlay_qpn);
Maor Gottlieb35d190112016-03-07 18:51:47 +02003194 }
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003195 } else if (flow_attr->type == IB_FLOW_ATTR_ALL_DEFAULT ||
3196 flow_attr->type == IB_FLOW_ATTR_MC_DEFAULT) {
3197 handler = create_leftovers_rule(dev, ft_prio, flow_attr,
3198 dst);
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003199 } else if (flow_attr->type == IB_FLOW_ATTR_SNIFFER) {
3200 handler = create_sniffer_rule(dev, ft_prio, ft_prio_tx, dst);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003201 } else {
3202 err = -EINVAL;
3203 goto destroy_ft;
3204 }
3205
3206 if (IS_ERR(handler)) {
3207 err = PTR_ERR(handler);
3208 handler = NULL;
3209 goto destroy_ft;
3210 }
3211
Mark Bloch9a4ca382018-01-16 14:42:35 +00003212 mutex_unlock(&dev->flow_db->lock);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003213 kfree(dst);
3214
3215 return &handler->ibflow;
3216
3217destroy_ft:
3218 put_flow_table(dev, ft_prio, false);
Maor Gottliebcc0e5d42016-08-28 14:16:34 +03003219 if (ft_prio_tx)
3220 put_flow_table(dev, ft_prio_tx, false);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003221unlock:
Mark Bloch9a4ca382018-01-16 14:42:35 +00003222 mutex_unlock(&dev->flow_db->lock);
Maor Gottlieb038d2ef2016-01-11 10:26:07 +02003223 kfree(dst);
3224 kfree(handler);
3225 return ERR_PTR(err);
3226}
3227
Aviad Yehezkelc6475a02018-03-28 09:27:50 +03003228static u32 mlx5_ib_flow_action_flags_to_accel_xfrm_flags(u32 mlx5_flags)
3229{
3230 u32 flags = 0;
3231
3232 if (mlx5_flags & MLX5_IB_UAPI_FLOW_ACTION_FLAGS_REQUIRE_METADATA)
3233 flags |= MLX5_ACCEL_XFRM_FLAG_REQUIRE_METADATA;
3234
3235 return flags;
3236}
3237
3238#define MLX5_FLOW_ACTION_ESP_CREATE_LAST_SUPPORTED MLX5_IB_UAPI_FLOW_ACTION_FLAGS_REQUIRE_METADATA
3239static struct ib_flow_action *
3240mlx5_ib_create_flow_action_esp(struct ib_device *device,
3241 const struct ib_flow_action_attrs_esp *attr,
3242 struct uverbs_attr_bundle *attrs)
3243{
3244 struct mlx5_ib_dev *mdev = to_mdev(device);
3245 struct ib_uverbs_flow_action_esp_keymat_aes_gcm *aes_gcm;
3246 struct mlx5_accel_esp_xfrm_attrs accel_attrs = {};
3247 struct mlx5_ib_flow_action *action;
3248 u64 action_flags;
3249 u64 flags;
3250 int err = 0;
3251
3252 if (IS_UVERBS_COPY_ERR(uverbs_copy_from(&action_flags, attrs,
3253 MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS)))
3254 return ERR_PTR(-EFAULT);
3255
3256 if (action_flags >= (MLX5_FLOW_ACTION_ESP_CREATE_LAST_SUPPORTED << 1))
3257 return ERR_PTR(-EOPNOTSUPP);
3258
3259 flags = mlx5_ib_flow_action_flags_to_accel_xfrm_flags(action_flags);
3260
3261 /* We current only support a subset of the standard features. Only a
3262 * keymat of type AES_GCM, with icv_len == 16, iv_algo == SEQ and esn
3263 * (with overlap). Full offload mode isn't supported.
3264 */
3265 if (!attr->keymat || attr->replay || attr->encap ||
3266 attr->spi || attr->seq || attr->tfc_pad ||
3267 attr->hard_limit_pkts ||
3268 (attr->flags & ~(IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED |
3269 IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ENCRYPT)))
3270 return ERR_PTR(-EOPNOTSUPP);
3271
3272 if (attr->keymat->protocol !=
3273 IB_UVERBS_FLOW_ACTION_ESP_KEYMAT_AES_GCM)
3274 return ERR_PTR(-EOPNOTSUPP);
3275
3276 aes_gcm = &attr->keymat->keymat.aes_gcm;
3277
3278 if (aes_gcm->icv_len != 16 ||
3279 aes_gcm->iv_algo != IB_UVERBS_FLOW_ACTION_IV_ALGO_SEQ)
3280 return ERR_PTR(-EOPNOTSUPP);
3281
3282 action = kmalloc(sizeof(*action), GFP_KERNEL);
3283 if (!action)
3284 return ERR_PTR(-ENOMEM);
3285
3286 action->esp_aes_gcm.ib_flags = attr->flags;
3287 memcpy(&accel_attrs.keymat.aes_gcm.aes_key, &aes_gcm->aes_key,
3288 sizeof(accel_attrs.keymat.aes_gcm.aes_key));
3289 accel_attrs.keymat.aes_gcm.key_len = aes_gcm->key_len * 8;
3290 memcpy(&accel_attrs.keymat.aes_gcm.salt, &aes_gcm->salt,
3291 sizeof(accel_attrs.keymat.aes_gcm.salt));
3292 memcpy(&accel_attrs.keymat.aes_gcm.seq_iv, &aes_gcm->iv,
3293 sizeof(accel_attrs.keymat.aes_gcm.seq_iv));
3294 accel_attrs.keymat.aes_gcm.icv_len = aes_gcm->icv_len * 8;
3295 accel_attrs.keymat.aes_gcm.iv_algo = MLX5_ACCEL_ESP_AES_GCM_IV_ALGO_SEQ;
3296 accel_attrs.keymat_type = MLX5_ACCEL_ESP_KEYMAT_AES_GCM;
3297
3298 accel_attrs.esn = attr->esn;
3299 if (attr->flags & IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED)
3300 accel_attrs.flags |= MLX5_ACCEL_ESP_FLAGS_ESN_TRIGGERED;
3301 if (attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW)
3302 accel_attrs.flags |= MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP;
3303
3304 if (attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ENCRYPT)
3305 accel_attrs.action |= MLX5_ACCEL_ESP_ACTION_ENCRYPT;
3306
3307 action->esp_aes_gcm.ctx =
3308 mlx5_accel_esp_create_xfrm(mdev->mdev, &accel_attrs, flags);
3309 if (IS_ERR(action->esp_aes_gcm.ctx)) {
3310 err = PTR_ERR(action->esp_aes_gcm.ctx);
3311 goto err_parse;
3312 }
3313
3314 action->esp_aes_gcm.ib_flags = attr->flags;
3315
3316 return &action->ib_action;
3317
3318err_parse:
3319 kfree(action);
3320 return ERR_PTR(err);
3321}
3322
Matan Barak349705c2018-03-28 09:27:51 +03003323static int
3324mlx5_ib_modify_flow_action_esp(struct ib_flow_action *action,
3325 const struct ib_flow_action_attrs_esp *attr,
3326 struct uverbs_attr_bundle *attrs)
3327{
3328 struct mlx5_ib_flow_action *maction = to_mflow_act(action);
3329 struct mlx5_accel_esp_xfrm_attrs accel_attrs;
3330 int err = 0;
3331
3332 if (attr->keymat || attr->replay || attr->encap ||
3333 attr->spi || attr->seq || attr->tfc_pad ||
3334 attr->hard_limit_pkts ||
3335 (attr->flags & ~(IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED |
3336 IB_FLOW_ACTION_ESP_FLAGS_MOD_ESP_ATTRS |
3337 IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW)))
3338 return -EOPNOTSUPP;
3339
3340 /* Only the ESN value or the MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP can
3341 * be modified.
3342 */
3343 if (!(maction->esp_aes_gcm.ib_flags &
3344 IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED) &&
3345 attr->flags & (IB_FLOW_ACTION_ESP_FLAGS_ESN_TRIGGERED |
3346 IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW))
3347 return -EINVAL;
3348
3349 memcpy(&accel_attrs, &maction->esp_aes_gcm.ctx->attrs,
3350 sizeof(accel_attrs));
3351
3352 accel_attrs.esn = attr->esn;
3353 if (attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW)
3354 accel_attrs.flags |= MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP;
3355 else
3356 accel_attrs.flags &= ~MLX5_ACCEL_ESP_FLAGS_ESN_STATE_OVERLAP;
3357
3358 err = mlx5_accel_esp_modify_xfrm(maction->esp_aes_gcm.ctx,
3359 &accel_attrs);
3360 if (err)
3361 return err;
3362
3363 maction->esp_aes_gcm.ib_flags &=
3364 ~IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW;
3365 maction->esp_aes_gcm.ib_flags |=
3366 attr->flags & IB_UVERBS_FLOW_ACTION_ESP_FLAGS_ESN_NEW_WINDOW;
3367
3368 return 0;
3369}
3370
Aviad Yehezkelc6475a02018-03-28 09:27:50 +03003371static int mlx5_ib_destroy_flow_action(struct ib_flow_action *action)
3372{
3373 struct mlx5_ib_flow_action *maction = to_mflow_act(action);
3374
3375 switch (action->type) {
3376 case IB_FLOW_ACTION_ESP:
3377 /*
3378 * We only support aes_gcm by now, so we implicitly know this is
3379 * the underline crypto.
3380 */
3381 mlx5_accel_esp_destroy_xfrm(maction->esp_aes_gcm.ctx);
3382 break;
3383 default:
3384 WARN_ON(true);
3385 break;
3386 }
3387
3388 kfree(maction);
3389 return 0;
3390}
3391
Eli Cohene126ba92013-07-07 17:25:49 +03003392static int mlx5_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
3393{
3394 struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
Yishai Hadas81e30882017-06-08 16:15:09 +03003395 struct mlx5_ib_qp *mqp = to_mqp(ibqp);
Eli Cohene126ba92013-07-07 17:25:49 +03003396 int err;
3397
Yishai Hadas81e30882017-06-08 16:15:09 +03003398 if (mqp->flags & MLX5_IB_QP_UNDERLAY) {
3399 mlx5_ib_dbg(dev, "Attaching a multi cast group to underlay QP is not supported\n");
3400 return -EOPNOTSUPP;
3401 }
3402
Jack Morgenstein9603b612014-07-28 23:30:22 +03003403 err = mlx5_core_attach_mcg(dev->mdev, gid, ibqp->qp_num);
Eli Cohene126ba92013-07-07 17:25:49 +03003404 if (err)
3405 mlx5_ib_warn(dev, "failed attaching QPN 0x%x, MGID %pI6\n",
3406 ibqp->qp_num, gid->raw);
3407
3408 return err;
3409}
3410
3411static int mlx5_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
3412{
3413 struct mlx5_ib_dev *dev = to_mdev(ibqp->device);
3414 int err;
3415
Jack Morgenstein9603b612014-07-28 23:30:22 +03003416 err = mlx5_core_detach_mcg(dev->mdev, gid, ibqp->qp_num);
Eli Cohene126ba92013-07-07 17:25:49 +03003417 if (err)
3418 mlx5_ib_warn(dev, "failed detaching QPN 0x%x, MGID %pI6\n",
3419 ibqp->qp_num, gid->raw);
3420
3421 return err;
3422}
3423
3424static int init_node_data(struct mlx5_ib_dev *dev)
3425{
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03003426 int err;
Eli Cohene126ba92013-07-07 17:25:49 +03003427
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03003428 err = mlx5_query_node_desc(dev, dev->ib_dev.node_desc);
Eli Cohene126ba92013-07-07 17:25:49 +03003429 if (err)
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03003430 return err;
Eli Cohene126ba92013-07-07 17:25:49 +03003431
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03003432 dev->mdev->rev_id = dev->mdev->pdev->revision;
Eli Cohene126ba92013-07-07 17:25:49 +03003433
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03003434 return mlx5_query_node_guid(dev, &dev->ib_dev.node_guid);
Eli Cohene126ba92013-07-07 17:25:49 +03003435}
3436
3437static ssize_t show_fw_pages(struct device *device, struct device_attribute *attr,
3438 char *buf)
3439{
3440 struct mlx5_ib_dev *dev =
3441 container_of(device, struct mlx5_ib_dev, ib_dev.dev);
3442
Jack Morgenstein9603b612014-07-28 23:30:22 +03003443 return sprintf(buf, "%d\n", dev->mdev->priv.fw_pages);
Eli Cohene126ba92013-07-07 17:25:49 +03003444}
3445
3446static ssize_t show_reg_pages(struct device *device,
3447 struct device_attribute *attr, char *buf)
3448{
3449 struct mlx5_ib_dev *dev =
3450 container_of(device, struct mlx5_ib_dev, ib_dev.dev);
3451
Haggai Eran6aec21f2014-12-11 17:04:23 +02003452 return sprintf(buf, "%d\n", atomic_read(&dev->mdev->priv.reg_pages));
Eli Cohene126ba92013-07-07 17:25:49 +03003453}
3454
3455static ssize_t show_hca(struct device *device, struct device_attribute *attr,
3456 char *buf)
3457{
3458 struct mlx5_ib_dev *dev =
3459 container_of(device, struct mlx5_ib_dev, ib_dev.dev);
Jack Morgenstein9603b612014-07-28 23:30:22 +03003460 return sprintf(buf, "MT%d\n", dev->mdev->pdev->device);
Eli Cohene126ba92013-07-07 17:25:49 +03003461}
3462
Eli Cohene126ba92013-07-07 17:25:49 +03003463static ssize_t show_rev(struct device *device, struct device_attribute *attr,
3464 char *buf)
3465{
3466 struct mlx5_ib_dev *dev =
3467 container_of(device, struct mlx5_ib_dev, ib_dev.dev);
Jack Morgenstein9603b612014-07-28 23:30:22 +03003468 return sprintf(buf, "%x\n", dev->mdev->rev_id);
Eli Cohene126ba92013-07-07 17:25:49 +03003469}
3470
3471static ssize_t show_board(struct device *device, struct device_attribute *attr,
3472 char *buf)
3473{
3474 struct mlx5_ib_dev *dev =
3475 container_of(device, struct mlx5_ib_dev, ib_dev.dev);
3476 return sprintf(buf, "%.*s\n", MLX5_BOARD_ID_LEN,
Jack Morgenstein9603b612014-07-28 23:30:22 +03003477 dev->mdev->board_id);
Eli Cohene126ba92013-07-07 17:25:49 +03003478}
3479
3480static DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL);
Eli Cohene126ba92013-07-07 17:25:49 +03003481static DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL);
3482static DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL);
3483static DEVICE_ATTR(fw_pages, S_IRUGO, show_fw_pages, NULL);
3484static DEVICE_ATTR(reg_pages, S_IRUGO, show_reg_pages, NULL);
3485
3486static struct device_attribute *mlx5_class_attributes[] = {
3487 &dev_attr_hw_rev,
Eli Cohene126ba92013-07-07 17:25:49 +03003488 &dev_attr_hca_type,
3489 &dev_attr_board_id,
3490 &dev_attr_fw_pages,
3491 &dev_attr_reg_pages,
3492};
3493
Haggai Eran7722f472016-02-29 15:45:07 +02003494static void pkey_change_handler(struct work_struct *work)
3495{
3496 struct mlx5_ib_port_resources *ports =
3497 container_of(work, struct mlx5_ib_port_resources,
3498 pkey_change_work);
3499
3500 mutex_lock(&ports->devr->mutex);
3501 mlx5_ib_gsi_pkey_change(ports->gsi);
3502 mutex_unlock(&ports->devr->mutex);
3503}
3504
Maor Gottlieb89ea94a72016-06-17 15:01:38 +03003505static void mlx5_ib_handle_internal_error(struct mlx5_ib_dev *ibdev)
3506{
3507 struct mlx5_ib_qp *mqp;
3508 struct mlx5_ib_cq *send_mcq, *recv_mcq;
3509 struct mlx5_core_cq *mcq;
3510 struct list_head cq_armed_list;
3511 unsigned long flags_qp;
3512 unsigned long flags_cq;
3513 unsigned long flags;
3514
3515 INIT_LIST_HEAD(&cq_armed_list);
3516
3517 /* Go over qp list reside on that ibdev, sync with create/destroy qp.*/
3518 spin_lock_irqsave(&ibdev->reset_flow_resource_lock, flags);
3519 list_for_each_entry(mqp, &ibdev->qp_list, qps_list) {
3520 spin_lock_irqsave(&mqp->sq.lock, flags_qp);
3521 if (mqp->sq.tail != mqp->sq.head) {
3522 send_mcq = to_mcq(mqp->ibqp.send_cq);
3523 spin_lock_irqsave(&send_mcq->lock, flags_cq);
3524 if (send_mcq->mcq.comp &&
3525 mqp->ibqp.send_cq->comp_handler) {
3526 if (!send_mcq->mcq.reset_notify_added) {
3527 send_mcq->mcq.reset_notify_added = 1;
3528 list_add_tail(&send_mcq->mcq.reset_notify,
3529 &cq_armed_list);
3530 }
3531 }
3532 spin_unlock_irqrestore(&send_mcq->lock, flags_cq);
3533 }
3534 spin_unlock_irqrestore(&mqp->sq.lock, flags_qp);
3535 spin_lock_irqsave(&mqp->rq.lock, flags_qp);
3536 /* no handling is needed for SRQ */
3537 if (!mqp->ibqp.srq) {
3538 if (mqp->rq.tail != mqp->rq.head) {
3539 recv_mcq = to_mcq(mqp->ibqp.recv_cq);
3540 spin_lock_irqsave(&recv_mcq->lock, flags_cq);
3541 if (recv_mcq->mcq.comp &&
3542 mqp->ibqp.recv_cq->comp_handler) {
3543 if (!recv_mcq->mcq.reset_notify_added) {
3544 recv_mcq->mcq.reset_notify_added = 1;
3545 list_add_tail(&recv_mcq->mcq.reset_notify,
3546 &cq_armed_list);
3547 }
3548 }
3549 spin_unlock_irqrestore(&recv_mcq->lock,
3550 flags_cq);
3551 }
3552 }
3553 spin_unlock_irqrestore(&mqp->rq.lock, flags_qp);
3554 }
3555 /*At that point all inflight post send were put to be executed as of we
3556 * lock/unlock above locks Now need to arm all involved CQs.
3557 */
3558 list_for_each_entry(mcq, &cq_armed_list, reset_notify) {
3559 mcq->comp(mcq);
3560 }
3561 spin_unlock_irqrestore(&ibdev->reset_flow_resource_lock, flags);
3562}
3563
Maor Gottlieb03404e82017-05-30 10:29:13 +03003564static void delay_drop_handler(struct work_struct *work)
3565{
3566 int err;
3567 struct mlx5_ib_delay_drop *delay_drop =
3568 container_of(work, struct mlx5_ib_delay_drop,
3569 delay_drop_work);
3570
Maor Gottliebfe248c32017-05-30 10:29:14 +03003571 atomic_inc(&delay_drop->events_cnt);
3572
Maor Gottlieb03404e82017-05-30 10:29:13 +03003573 mutex_lock(&delay_drop->lock);
3574 err = mlx5_core_set_delay_drop(delay_drop->dev->mdev,
3575 delay_drop->timeout);
3576 if (err) {
3577 mlx5_ib_warn(delay_drop->dev, "Failed to set delay drop, timeout=%u\n",
3578 delay_drop->timeout);
3579 delay_drop->activate = false;
3580 }
3581 mutex_unlock(&delay_drop->lock);
3582}
3583
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02003584static void mlx5_ib_handle_event(struct work_struct *_work)
Eli Cohene126ba92013-07-07 17:25:49 +03003585{
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02003586 struct mlx5_ib_event_work *work =
3587 container_of(_work, struct mlx5_ib_event_work, work);
3588 struct mlx5_ib_dev *ibdev;
Eli Cohene126ba92013-07-07 17:25:49 +03003589 struct ib_event ibev;
Eli Cohendbaaff22016-10-27 16:36:44 +03003590 bool fatal = false;
Daniel Jurgensaba46212018-02-25 13:39:53 +02003591 u8 port = (u8)work->param;
Eli Cohene126ba92013-07-07 17:25:49 +03003592
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02003593 if (mlx5_core_is_mp_slave(work->dev)) {
3594 ibdev = mlx5_ib_get_ibdev_from_mpi(work->context);
3595 if (!ibdev)
3596 goto out;
3597 } else {
3598 ibdev = work->context;
3599 }
3600
3601 switch (work->event) {
Eli Cohene126ba92013-07-07 17:25:49 +03003602 case MLX5_DEV_EVENT_SYS_ERROR:
Eli Cohene126ba92013-07-07 17:25:49 +03003603 ibev.event = IB_EVENT_DEVICE_FATAL;
Maor Gottlieb89ea94a72016-06-17 15:01:38 +03003604 mlx5_ib_handle_internal_error(ibdev);
Eli Cohendbaaff22016-10-27 16:36:44 +03003605 fatal = true;
Eli Cohene126ba92013-07-07 17:25:49 +03003606 break;
3607
3608 case MLX5_DEV_EVENT_PORT_UP:
Eli Cohene126ba92013-07-07 17:25:49 +03003609 case MLX5_DEV_EVENT_PORT_DOWN:
Noa Osherovich2788cf32016-06-04 15:15:29 +03003610 case MLX5_DEV_EVENT_PORT_INITIALIZED:
Aviv Heller5ec8c832016-09-18 20:48:00 +03003611 /* In RoCE, port up/down events are handled in
3612 * mlx5_netdev_event().
3613 */
3614 if (mlx5_ib_port_link_layer(&ibdev->ib_dev, port) ==
3615 IB_LINK_LAYER_ETHERNET)
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02003616 goto out;
Aviv Heller5ec8c832016-09-18 20:48:00 +03003617
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02003618 ibev.event = (work->event == MLX5_DEV_EVENT_PORT_UP) ?
Aviv Heller5ec8c832016-09-18 20:48:00 +03003619 IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;
Eli Cohene126ba92013-07-07 17:25:49 +03003620 break;
3621
Eli Cohene126ba92013-07-07 17:25:49 +03003622 case MLX5_DEV_EVENT_LID_CHANGE:
3623 ibev.event = IB_EVENT_LID_CHANGE;
Eli Cohene126ba92013-07-07 17:25:49 +03003624 break;
3625
3626 case MLX5_DEV_EVENT_PKEY_CHANGE:
3627 ibev.event = IB_EVENT_PKEY_CHANGE;
Haggai Eran7722f472016-02-29 15:45:07 +02003628 schedule_work(&ibdev->devr.ports[port - 1].pkey_change_work);
Eli Cohene126ba92013-07-07 17:25:49 +03003629 break;
3630
3631 case MLX5_DEV_EVENT_GUID_CHANGE:
3632 ibev.event = IB_EVENT_GID_CHANGE;
Eli Cohene126ba92013-07-07 17:25:49 +03003633 break;
3634
3635 case MLX5_DEV_EVENT_CLIENT_REREG:
3636 ibev.event = IB_EVENT_CLIENT_REREGISTER;
Eli Cohene126ba92013-07-07 17:25:49 +03003637 break;
Maor Gottlieb03404e82017-05-30 10:29:13 +03003638 case MLX5_DEV_EVENT_DELAY_DROP_TIMEOUT:
3639 schedule_work(&ibdev->delay_drop.delay_drop_work);
3640 goto out;
Saeed Mahameedbdc37922016-09-29 19:35:38 +03003641 default:
Maor Gottlieb03404e82017-05-30 10:29:13 +03003642 goto out;
Eli Cohene126ba92013-07-07 17:25:49 +03003643 }
3644
3645 ibev.device = &ibdev->ib_dev;
3646 ibev.element.port_num = port;
3647
Daniel Jurgensaba46212018-02-25 13:39:53 +02003648 if (!rdma_is_port_valid(&ibdev->ib_dev, port)) {
Eli Cohena0c84c32013-09-11 16:35:27 +03003649 mlx5_ib_warn(ibdev, "warning: event on port %d\n", port);
Maor Gottlieb03404e82017-05-30 10:29:13 +03003650 goto out;
Eli Cohena0c84c32013-09-11 16:35:27 +03003651 }
3652
Eli Cohene126ba92013-07-07 17:25:49 +03003653 if (ibdev->ib_active)
3654 ib_dispatch_event(&ibev);
Eli Cohendbaaff22016-10-27 16:36:44 +03003655
3656 if (fatal)
3657 ibdev->ib_active = false;
Maor Gottlieb03404e82017-05-30 10:29:13 +03003658out:
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02003659 kfree(work);
3660}
3661
3662static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
3663 enum mlx5_dev_event event, unsigned long param)
3664{
3665 struct mlx5_ib_event_work *work;
3666
3667 work = kmalloc(sizeof(*work), GFP_ATOMIC);
Leon Romanovsky10bea9c2018-01-19 13:07:11 +02003668 if (!work)
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02003669 return;
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02003670
Leon Romanovsky10bea9c2018-01-19 13:07:11 +02003671 INIT_WORK(&work->work, mlx5_ib_handle_event);
3672 work->dev = dev;
3673 work->param = param;
3674 work->context = context;
3675 work->event = event;
3676
3677 queue_work(mlx5_ib_event_wq, &work->work);
Eli Cohene126ba92013-07-07 17:25:49 +03003678}
3679
Maor Gottliebc43f1112017-01-18 14:10:33 +02003680static int set_has_smi_cap(struct mlx5_ib_dev *dev)
3681{
3682 struct mlx5_hca_vport_context vport_ctx;
3683 int err;
3684 int port;
3685
Daniel Jurgens508562d2018-01-04 17:25:34 +02003686 for (port = 1; port <= dev->num_ports; port++) {
Maor Gottliebc43f1112017-01-18 14:10:33 +02003687 dev->mdev->port_caps[port - 1].has_smi = false;
3688 if (MLX5_CAP_GEN(dev->mdev, port_type) ==
3689 MLX5_CAP_PORT_TYPE_IB) {
3690 if (MLX5_CAP_GEN(dev->mdev, ib_virt)) {
3691 err = mlx5_query_hca_vport_context(dev->mdev, 0,
3692 port, 0,
3693 &vport_ctx);
3694 if (err) {
3695 mlx5_ib_err(dev, "query_hca_vport_context for port=%d failed %d\n",
3696 port, err);
3697 return err;
3698 }
3699 dev->mdev->port_caps[port - 1].has_smi =
3700 vport_ctx.has_smi;
3701 } else {
3702 dev->mdev->port_caps[port - 1].has_smi = true;
3703 }
3704 }
3705 }
3706 return 0;
3707}
3708
Eli Cohene126ba92013-07-07 17:25:49 +03003709static void get_ext_port_caps(struct mlx5_ib_dev *dev)
3710{
3711 int port;
3712
Daniel Jurgens508562d2018-01-04 17:25:34 +02003713 for (port = 1; port <= dev->num_ports; port++)
Eli Cohene126ba92013-07-07 17:25:49 +03003714 mlx5_query_ext_port_caps(dev, port);
3715}
3716
Daniel Jurgens32f69e42018-01-04 17:25:36 +02003717static int get_port_caps(struct mlx5_ib_dev *dev, u8 port)
Eli Cohene126ba92013-07-07 17:25:49 +03003718{
3719 struct ib_device_attr *dprops = NULL;
3720 struct ib_port_attr *pprops = NULL;
Dan Carpenterf614fc12015-01-12 11:56:58 +03003721 int err = -ENOMEM;
Matan Barak2528e332015-06-11 16:35:25 +03003722 struct ib_udata uhw = {.inlen = 0, .outlen = 0};
Eli Cohene126ba92013-07-07 17:25:49 +03003723
3724 pprops = kmalloc(sizeof(*pprops), GFP_KERNEL);
3725 if (!pprops)
3726 goto out;
3727
3728 dprops = kmalloc(sizeof(*dprops), GFP_KERNEL);
3729 if (!dprops)
3730 goto out;
3731
Maor Gottliebc43f1112017-01-18 14:10:33 +02003732 err = set_has_smi_cap(dev);
3733 if (err)
3734 goto out;
3735
Matan Barak2528e332015-06-11 16:35:25 +03003736 err = mlx5_ib_query_device(&dev->ib_dev, dprops, &uhw);
Eli Cohene126ba92013-07-07 17:25:49 +03003737 if (err) {
3738 mlx5_ib_warn(dev, "query_device failed %d\n", err);
3739 goto out;
3740 }
3741
Daniel Jurgens32f69e42018-01-04 17:25:36 +02003742 memset(pprops, 0, sizeof(*pprops));
3743 err = mlx5_ib_query_port(&dev->ib_dev, port, pprops);
3744 if (err) {
3745 mlx5_ib_warn(dev, "query_port %d failed %d\n",
3746 port, err);
3747 goto out;
Eli Cohene126ba92013-07-07 17:25:49 +03003748 }
3749
Daniel Jurgens32f69e42018-01-04 17:25:36 +02003750 dev->mdev->port_caps[port - 1].pkey_table_len =
3751 dprops->max_pkeys;
3752 dev->mdev->port_caps[port - 1].gid_table_len =
3753 pprops->gid_tbl_len;
3754 mlx5_ib_dbg(dev, "port %d: pkey_table_len %d, gid_table_len %d\n",
3755 port, dprops->max_pkeys, pprops->gid_tbl_len);
3756
Eli Cohene126ba92013-07-07 17:25:49 +03003757out:
3758 kfree(pprops);
3759 kfree(dprops);
3760
3761 return err;
3762}
3763
3764static void destroy_umrc_res(struct mlx5_ib_dev *dev)
3765{
3766 int err;
3767
3768 err = mlx5_mr_cache_cleanup(dev);
3769 if (err)
3770 mlx5_ib_warn(dev, "mr cache cleanup failed\n");
3771
3772 mlx5_ib_destroy_qp(dev->umrc.qp);
Christoph Hellwigadd08d72016-03-03 09:38:22 +01003773 ib_free_cq(dev->umrc.cq);
Eli Cohene126ba92013-07-07 17:25:49 +03003774 ib_dealloc_pd(dev->umrc.pd);
3775}
3776
3777enum {
3778 MAX_UMR_WR = 128,
3779};
3780
3781static int create_umr_res(struct mlx5_ib_dev *dev)
3782{
3783 struct ib_qp_init_attr *init_attr = NULL;
3784 struct ib_qp_attr *attr = NULL;
3785 struct ib_pd *pd;
3786 struct ib_cq *cq;
3787 struct ib_qp *qp;
Eli Cohene126ba92013-07-07 17:25:49 +03003788 int ret;
3789
3790 attr = kzalloc(sizeof(*attr), GFP_KERNEL);
3791 init_attr = kzalloc(sizeof(*init_attr), GFP_KERNEL);
3792 if (!attr || !init_attr) {
3793 ret = -ENOMEM;
3794 goto error_0;
3795 }
3796
Christoph Hellwiged082d32016-09-05 12:56:17 +02003797 pd = ib_alloc_pd(&dev->ib_dev, 0);
Eli Cohene126ba92013-07-07 17:25:49 +03003798 if (IS_ERR(pd)) {
3799 mlx5_ib_dbg(dev, "Couldn't create PD for sync UMR QP\n");
3800 ret = PTR_ERR(pd);
3801 goto error_0;
3802 }
3803
Christoph Hellwigadd08d72016-03-03 09:38:22 +01003804 cq = ib_alloc_cq(&dev->ib_dev, NULL, 128, 0, IB_POLL_SOFTIRQ);
Eli Cohene126ba92013-07-07 17:25:49 +03003805 if (IS_ERR(cq)) {
3806 mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n");
3807 ret = PTR_ERR(cq);
3808 goto error_2;
3809 }
Eli Cohene126ba92013-07-07 17:25:49 +03003810
3811 init_attr->send_cq = cq;
3812 init_attr->recv_cq = cq;
3813 init_attr->sq_sig_type = IB_SIGNAL_ALL_WR;
3814 init_attr->cap.max_send_wr = MAX_UMR_WR;
3815 init_attr->cap.max_send_sge = 1;
3816 init_attr->qp_type = MLX5_IB_QPT_REG_UMR;
3817 init_attr->port_num = 1;
3818 qp = mlx5_ib_create_qp(pd, init_attr, NULL);
3819 if (IS_ERR(qp)) {
3820 mlx5_ib_dbg(dev, "Couldn't create sync UMR QP\n");
3821 ret = PTR_ERR(qp);
3822 goto error_3;
3823 }
3824 qp->device = &dev->ib_dev;
3825 qp->real_qp = qp;
3826 qp->uobject = NULL;
3827 qp->qp_type = MLX5_IB_QPT_REG_UMR;
Majd Dibbiny31fde032017-10-30 14:23:13 +02003828 qp->send_cq = init_attr->send_cq;
3829 qp->recv_cq = init_attr->recv_cq;
Eli Cohene126ba92013-07-07 17:25:49 +03003830
3831 attr->qp_state = IB_QPS_INIT;
3832 attr->port_num = 1;
3833 ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE | IB_QP_PKEY_INDEX |
3834 IB_QP_PORT, NULL);
3835 if (ret) {
3836 mlx5_ib_dbg(dev, "Couldn't modify UMR QP\n");
3837 goto error_4;
3838 }
3839
3840 memset(attr, 0, sizeof(*attr));
3841 attr->qp_state = IB_QPS_RTR;
3842 attr->path_mtu = IB_MTU_256;
3843
3844 ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL);
3845 if (ret) {
3846 mlx5_ib_dbg(dev, "Couldn't modify umr QP to rtr\n");
3847 goto error_4;
3848 }
3849
3850 memset(attr, 0, sizeof(*attr));
3851 attr->qp_state = IB_QPS_RTS;
3852 ret = mlx5_ib_modify_qp(qp, attr, IB_QP_STATE, NULL);
3853 if (ret) {
3854 mlx5_ib_dbg(dev, "Couldn't modify umr QP to rts\n");
3855 goto error_4;
3856 }
3857
3858 dev->umrc.qp = qp;
3859 dev->umrc.cq = cq;
Eli Cohene126ba92013-07-07 17:25:49 +03003860 dev->umrc.pd = pd;
3861
3862 sema_init(&dev->umrc.sem, MAX_UMR_WR);
3863 ret = mlx5_mr_cache_init(dev);
3864 if (ret) {
3865 mlx5_ib_warn(dev, "mr cache init failed %d\n", ret);
3866 goto error_4;
3867 }
3868
3869 kfree(attr);
3870 kfree(init_attr);
3871
3872 return 0;
3873
3874error_4:
3875 mlx5_ib_destroy_qp(qp);
3876
3877error_3:
Christoph Hellwigadd08d72016-03-03 09:38:22 +01003878 ib_free_cq(cq);
Eli Cohene126ba92013-07-07 17:25:49 +03003879
3880error_2:
Eli Cohene126ba92013-07-07 17:25:49 +03003881 ib_dealloc_pd(pd);
3882
3883error_0:
3884 kfree(attr);
3885 kfree(init_attr);
3886 return ret;
3887}
3888
Max Gurtovoy6e8484c2017-05-28 10:53:11 +03003889static u8 mlx5_get_umr_fence(u8 umr_fence_cap)
3890{
3891 switch (umr_fence_cap) {
3892 case MLX5_CAP_UMR_FENCE_NONE:
3893 return MLX5_FENCE_MODE_NONE;
3894 case MLX5_CAP_UMR_FENCE_SMALL:
3895 return MLX5_FENCE_MODE_INITIATOR_SMALL;
3896 default:
3897 return MLX5_FENCE_MODE_STRONG_ORDERING;
3898 }
3899}
3900
Eli Cohene126ba92013-07-07 17:25:49 +03003901static int create_dev_resources(struct mlx5_ib_resources *devr)
3902{
3903 struct ib_srq_init_attr attr;
3904 struct mlx5_ib_dev *dev;
Matan Barakbcf4c1e2015-06-11 16:35:20 +03003905 struct ib_cq_init_attr cq_attr = {.cqe = 1};
Haggai Eran7722f472016-02-29 15:45:07 +02003906 int port;
Eli Cohene126ba92013-07-07 17:25:49 +03003907 int ret = 0;
3908
3909 dev = container_of(devr, struct mlx5_ib_dev, devr);
3910
Haggai Erand16e91d2016-02-29 15:45:05 +02003911 mutex_init(&devr->mutex);
3912
Eli Cohene126ba92013-07-07 17:25:49 +03003913 devr->p0 = mlx5_ib_alloc_pd(&dev->ib_dev, NULL, NULL);
3914 if (IS_ERR(devr->p0)) {
3915 ret = PTR_ERR(devr->p0);
3916 goto error0;
3917 }
3918 devr->p0->device = &dev->ib_dev;
3919 devr->p0->uobject = NULL;
3920 atomic_set(&devr->p0->usecnt, 0);
3921
Matan Barakbcf4c1e2015-06-11 16:35:20 +03003922 devr->c0 = mlx5_ib_create_cq(&dev->ib_dev, &cq_attr, NULL, NULL);
Eli Cohene126ba92013-07-07 17:25:49 +03003923 if (IS_ERR(devr->c0)) {
3924 ret = PTR_ERR(devr->c0);
3925 goto error1;
3926 }
3927 devr->c0->device = &dev->ib_dev;
3928 devr->c0->uobject = NULL;
3929 devr->c0->comp_handler = NULL;
3930 devr->c0->event_handler = NULL;
3931 devr->c0->cq_context = NULL;
3932 atomic_set(&devr->c0->usecnt, 0);
3933
3934 devr->x0 = mlx5_ib_alloc_xrcd(&dev->ib_dev, NULL, NULL);
3935 if (IS_ERR(devr->x0)) {
3936 ret = PTR_ERR(devr->x0);
3937 goto error2;
3938 }
3939 devr->x0->device = &dev->ib_dev;
3940 devr->x0->inode = NULL;
3941 atomic_set(&devr->x0->usecnt, 0);
3942 mutex_init(&devr->x0->tgt_qp_mutex);
3943 INIT_LIST_HEAD(&devr->x0->tgt_qp_list);
3944
3945 devr->x1 = mlx5_ib_alloc_xrcd(&dev->ib_dev, NULL, NULL);
3946 if (IS_ERR(devr->x1)) {
3947 ret = PTR_ERR(devr->x1);
3948 goto error3;
3949 }
3950 devr->x1->device = &dev->ib_dev;
3951 devr->x1->inode = NULL;
3952 atomic_set(&devr->x1->usecnt, 0);
3953 mutex_init(&devr->x1->tgt_qp_mutex);
3954 INIT_LIST_HEAD(&devr->x1->tgt_qp_list);
3955
3956 memset(&attr, 0, sizeof(attr));
3957 attr.attr.max_sge = 1;
3958 attr.attr.max_wr = 1;
3959 attr.srq_type = IB_SRQT_XRC;
Artemy Kovalyov1a56ff62017-08-17 15:52:04 +03003960 attr.ext.cq = devr->c0;
Eli Cohene126ba92013-07-07 17:25:49 +03003961 attr.ext.xrc.xrcd = devr->x0;
3962
3963 devr->s0 = mlx5_ib_create_srq(devr->p0, &attr, NULL);
3964 if (IS_ERR(devr->s0)) {
3965 ret = PTR_ERR(devr->s0);
3966 goto error4;
3967 }
3968 devr->s0->device = &dev->ib_dev;
3969 devr->s0->pd = devr->p0;
3970 devr->s0->uobject = NULL;
3971 devr->s0->event_handler = NULL;
3972 devr->s0->srq_context = NULL;
3973 devr->s0->srq_type = IB_SRQT_XRC;
3974 devr->s0->ext.xrc.xrcd = devr->x0;
Artemy Kovalyov1a56ff62017-08-17 15:52:04 +03003975 devr->s0->ext.cq = devr->c0;
Eli Cohene126ba92013-07-07 17:25:49 +03003976 atomic_inc(&devr->s0->ext.xrc.xrcd->usecnt);
Artemy Kovalyov1a56ff62017-08-17 15:52:04 +03003977 atomic_inc(&devr->s0->ext.cq->usecnt);
Eli Cohene126ba92013-07-07 17:25:49 +03003978 atomic_inc(&devr->p0->usecnt);
3979 atomic_set(&devr->s0->usecnt, 0);
3980
Haggai Abramonvsky4aa17b22015-06-04 19:30:48 +03003981 memset(&attr, 0, sizeof(attr));
3982 attr.attr.max_sge = 1;
3983 attr.attr.max_wr = 1;
3984 attr.srq_type = IB_SRQT_BASIC;
3985 devr->s1 = mlx5_ib_create_srq(devr->p0, &attr, NULL);
3986 if (IS_ERR(devr->s1)) {
3987 ret = PTR_ERR(devr->s1);
3988 goto error5;
3989 }
3990 devr->s1->device = &dev->ib_dev;
3991 devr->s1->pd = devr->p0;
3992 devr->s1->uobject = NULL;
3993 devr->s1->event_handler = NULL;
3994 devr->s1->srq_context = NULL;
3995 devr->s1->srq_type = IB_SRQT_BASIC;
Artemy Kovalyov1a56ff62017-08-17 15:52:04 +03003996 devr->s1->ext.cq = devr->c0;
Haggai Abramonvsky4aa17b22015-06-04 19:30:48 +03003997 atomic_inc(&devr->p0->usecnt);
Artemy Kovalyov1a56ff62017-08-17 15:52:04 +03003998 atomic_set(&devr->s1->usecnt, 0);
Haggai Abramonvsky4aa17b22015-06-04 19:30:48 +03003999
Haggai Eran7722f472016-02-29 15:45:07 +02004000 for (port = 0; port < ARRAY_SIZE(devr->ports); ++port) {
4001 INIT_WORK(&devr->ports[port].pkey_change_work,
4002 pkey_change_handler);
4003 devr->ports[port].devr = devr;
4004 }
4005
Eli Cohene126ba92013-07-07 17:25:49 +03004006 return 0;
4007
Haggai Abramonvsky4aa17b22015-06-04 19:30:48 +03004008error5:
4009 mlx5_ib_destroy_srq(devr->s0);
Eli Cohene126ba92013-07-07 17:25:49 +03004010error4:
4011 mlx5_ib_dealloc_xrcd(devr->x1);
4012error3:
4013 mlx5_ib_dealloc_xrcd(devr->x0);
4014error2:
4015 mlx5_ib_destroy_cq(devr->c0);
4016error1:
4017 mlx5_ib_dealloc_pd(devr->p0);
4018error0:
4019 return ret;
4020}
4021
4022static void destroy_dev_resources(struct mlx5_ib_resources *devr)
4023{
Haggai Eran7722f472016-02-29 15:45:07 +02004024 struct mlx5_ib_dev *dev =
4025 container_of(devr, struct mlx5_ib_dev, devr);
4026 int port;
4027
Haggai Abramonvsky4aa17b22015-06-04 19:30:48 +03004028 mlx5_ib_destroy_srq(devr->s1);
Eli Cohene126ba92013-07-07 17:25:49 +03004029 mlx5_ib_destroy_srq(devr->s0);
4030 mlx5_ib_dealloc_xrcd(devr->x0);
4031 mlx5_ib_dealloc_xrcd(devr->x1);
4032 mlx5_ib_destroy_cq(devr->c0);
4033 mlx5_ib_dealloc_pd(devr->p0);
Haggai Eran7722f472016-02-29 15:45:07 +02004034
4035 /* Make sure no change P_Key work items are still executing */
4036 for (port = 0; port < dev->num_ports; ++port)
4037 cancel_work_sync(&devr->ports[port].pkey_change_work);
Eli Cohene126ba92013-07-07 17:25:49 +03004038}
4039
Achiad Shochate53505a2015-12-23 18:47:25 +02004040static u32 get_core_cap_flags(struct ib_device *ibdev)
4041{
4042 struct mlx5_ib_dev *dev = to_mdev(ibdev);
4043 enum rdma_link_layer ll = mlx5_ib_port_link_layer(ibdev, 1);
4044 u8 l3_type_cap = MLX5_CAP_ROCE(dev->mdev, l3_type);
4045 u8 roce_version_cap = MLX5_CAP_ROCE(dev->mdev, roce_version);
Daniel Jurgens85c7c012018-01-04 17:25:43 +02004046 bool raw_support = !mlx5_core_mp_enabled(dev->mdev);
Achiad Shochate53505a2015-12-23 18:47:25 +02004047 u32 ret = 0;
4048
4049 if (ll == IB_LINK_LAYER_INFINIBAND)
4050 return RDMA_CORE_PORT_IBA_IB;
4051
Daniel Jurgens85c7c012018-01-04 17:25:43 +02004052 if (raw_support)
4053 ret = RDMA_CORE_PORT_RAW_PACKET;
Or Gerlitz72cd5712017-01-24 13:02:36 +02004054
Achiad Shochate53505a2015-12-23 18:47:25 +02004055 if (!(l3_type_cap & MLX5_ROCE_L3_TYPE_IPV4_CAP))
Or Gerlitz72cd5712017-01-24 13:02:36 +02004056 return ret;
Achiad Shochate53505a2015-12-23 18:47:25 +02004057
4058 if (!(l3_type_cap & MLX5_ROCE_L3_TYPE_IPV6_CAP))
Or Gerlitz72cd5712017-01-24 13:02:36 +02004059 return ret;
Achiad Shochate53505a2015-12-23 18:47:25 +02004060
4061 if (roce_version_cap & MLX5_ROCE_VERSION_1_CAP)
4062 ret |= RDMA_CORE_PORT_IBA_ROCE;
4063
4064 if (roce_version_cap & MLX5_ROCE_VERSION_2_CAP)
4065 ret |= RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;
4066
4067 return ret;
4068}
4069
Ira Weiny77386132015-05-13 20:02:58 -04004070static int mlx5_port_immutable(struct ib_device *ibdev, u8 port_num,
4071 struct ib_port_immutable *immutable)
4072{
4073 struct ib_port_attr attr;
Or Gerlitzca5b91d2016-11-27 16:51:36 +02004074 struct mlx5_ib_dev *dev = to_mdev(ibdev);
4075 enum rdma_link_layer ll = mlx5_ib_port_link_layer(ibdev, port_num);
Ira Weiny77386132015-05-13 20:02:58 -04004076 int err;
4077
Or Gerlitzc4550c62017-01-24 13:02:39 +02004078 immutable->core_cap_flags = get_core_cap_flags(ibdev);
4079
4080 err = ib_query_port(ibdev, port_num, &attr);
Ira Weiny77386132015-05-13 20:02:58 -04004081 if (err)
4082 return err;
4083
4084 immutable->pkey_tbl_len = attr.pkey_tbl_len;
4085 immutable->gid_tbl_len = attr.gid_tbl_len;
Achiad Shochate53505a2015-12-23 18:47:25 +02004086 immutable->core_cap_flags = get_core_cap_flags(ibdev);
Or Gerlitzca5b91d2016-11-27 16:51:36 +02004087 if ((ll == IB_LINK_LAYER_INFINIBAND) || MLX5_CAP_GEN(dev->mdev, roce))
4088 immutable->max_mad_size = IB_MGMT_MAD_SIZE;
Ira Weiny77386132015-05-13 20:02:58 -04004089
4090 return 0;
4091}
4092
Mark Bloch8e6efa32017-11-06 12:22:13 +00004093static int mlx5_port_rep_immutable(struct ib_device *ibdev, u8 port_num,
4094 struct ib_port_immutable *immutable)
4095{
4096 struct ib_port_attr attr;
4097 int err;
4098
4099 immutable->core_cap_flags = RDMA_CORE_PORT_RAW_PACKET;
4100
4101 err = ib_query_port(ibdev, port_num, &attr);
4102 if (err)
4103 return err;
4104
4105 immutable->pkey_tbl_len = attr.pkey_tbl_len;
4106 immutable->gid_tbl_len = attr.gid_tbl_len;
4107 immutable->core_cap_flags = RDMA_CORE_PORT_RAW_PACKET;
4108
4109 return 0;
4110}
4111
Leon Romanovsky9abb0d12017-06-27 16:49:53 +03004112static void get_dev_fw_str(struct ib_device *ibdev, char *str)
Ira Weinyc7342822016-06-15 02:22:01 -04004113{
4114 struct mlx5_ib_dev *dev =
4115 container_of(ibdev, struct mlx5_ib_dev, ib_dev);
Leon Romanovsky9abb0d12017-06-27 16:49:53 +03004116 snprintf(str, IB_FW_VERSION_NAME_MAX, "%d.%d.%04d",
4117 fw_rev_maj(dev->mdev), fw_rev_min(dev->mdev),
4118 fw_rev_sub(dev->mdev));
Ira Weinyc7342822016-06-15 02:22:01 -04004119}
4120
Or Gerlitz45f95ac2016-11-27 16:51:35 +02004121static int mlx5_eth_lag_init(struct mlx5_ib_dev *dev)
Aviv Heller9ef9c642016-09-18 20:48:01 +03004122{
4123 struct mlx5_core_dev *mdev = dev->mdev;
4124 struct mlx5_flow_namespace *ns = mlx5_get_flow_namespace(mdev,
4125 MLX5_FLOW_NAMESPACE_LAG);
4126 struct mlx5_flow_table *ft;
4127 int err;
4128
4129 if (!ns || !mlx5_lag_is_active(mdev))
4130 return 0;
4131
4132 err = mlx5_cmd_create_vport_lag(mdev);
4133 if (err)
4134 return err;
4135
4136 ft = mlx5_create_lag_demux_flow_table(ns, 0, 0);
4137 if (IS_ERR(ft)) {
4138 err = PTR_ERR(ft);
4139 goto err_destroy_vport_lag;
4140 }
4141
Mark Bloch9a4ca382018-01-16 14:42:35 +00004142 dev->flow_db->lag_demux_ft = ft;
Aviv Heller9ef9c642016-09-18 20:48:01 +03004143 return 0;
4144
4145err_destroy_vport_lag:
4146 mlx5_cmd_destroy_vport_lag(mdev);
4147 return err;
4148}
4149
Or Gerlitz45f95ac2016-11-27 16:51:35 +02004150static void mlx5_eth_lag_cleanup(struct mlx5_ib_dev *dev)
Aviv Heller9ef9c642016-09-18 20:48:01 +03004151{
4152 struct mlx5_core_dev *mdev = dev->mdev;
4153
Mark Bloch9a4ca382018-01-16 14:42:35 +00004154 if (dev->flow_db->lag_demux_ft) {
4155 mlx5_destroy_flow_table(dev->flow_db->lag_demux_ft);
4156 dev->flow_db->lag_demux_ft = NULL;
Aviv Heller9ef9c642016-09-18 20:48:01 +03004157
4158 mlx5_cmd_destroy_vport_lag(mdev);
4159 }
4160}
4161
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +02004162static int mlx5_add_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num)
Achiad Shochatfc24fc52015-12-23 18:47:17 +02004163{
Achiad Shochate53505a2015-12-23 18:47:25 +02004164 int err;
4165
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +02004166 dev->roce[port_num].nb.notifier_call = mlx5_netdev_event;
4167 err = register_netdevice_notifier(&dev->roce[port_num].nb);
Aviv Heller5ec8c832016-09-18 20:48:00 +03004168 if (err) {
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +02004169 dev->roce[port_num].nb.notifier_call = NULL;
Achiad Shochate53505a2015-12-23 18:47:25 +02004170 return err;
Aviv Heller5ec8c832016-09-18 20:48:00 +03004171 }
Achiad Shochate53505a2015-12-23 18:47:25 +02004172
Or Gerlitzd012f5d2016-11-27 16:51:34 +02004173 return 0;
4174}
Achiad Shochate53505a2015-12-23 18:47:25 +02004175
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +02004176static void mlx5_remove_netdev_notifier(struct mlx5_ib_dev *dev, u8 port_num)
Eli Cohene126ba92013-07-07 17:25:49 +03004177{
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +02004178 if (dev->roce[port_num].nb.notifier_call) {
4179 unregister_netdevice_notifier(&dev->roce[port_num].nb);
4180 dev->roce[port_num].nb.notifier_call = NULL;
Eli Cohene126ba92013-07-07 17:25:49 +03004181 }
4182}
4183
Daniel Jurgens7fd8aef2018-01-04 17:25:35 +02004184static int mlx5_enable_eth(struct mlx5_ib_dev *dev, u8 port_num)
Eli Cohene126ba92013-07-07 17:25:49 +03004185{
Eli Cohene126ba92013-07-07 17:25:49 +03004186 int err;
4187
Or Gerlitzca5b91d2016-11-27 16:51:36 +02004188 if (MLX5_CAP_GEN(dev->mdev, roce)) {
4189 err = mlx5_nic_vport_enable_roce(dev->mdev);
4190 if (err)
Mark Bloch8e6efa32017-11-06 12:22:13 +00004191 return err;
Or Gerlitzca5b91d2016-11-27 16:51:36 +02004192 }
Achiad Shochate53505a2015-12-23 18:47:25 +02004193
Or Gerlitz45f95ac2016-11-27 16:51:35 +02004194 err = mlx5_eth_lag_init(dev);
Aviv Heller9ef9c642016-09-18 20:48:01 +03004195 if (err)
4196 goto err_disable_roce;
4197
Achiad Shochate53505a2015-12-23 18:47:25 +02004198 return 0;
4199
Aviv Heller9ef9c642016-09-18 20:48:01 +03004200err_disable_roce:
Or Gerlitzca5b91d2016-11-27 16:51:36 +02004201 if (MLX5_CAP_GEN(dev->mdev, roce))
4202 mlx5_nic_vport_disable_roce(dev->mdev);
Aviv Heller9ef9c642016-09-18 20:48:01 +03004203
Achiad Shochate53505a2015-12-23 18:47:25 +02004204 return err;
Achiad Shochatfc24fc52015-12-23 18:47:17 +02004205}
4206
Or Gerlitz45f95ac2016-11-27 16:51:35 +02004207static void mlx5_disable_eth(struct mlx5_ib_dev *dev)
Achiad Shochatfc24fc52015-12-23 18:47:17 +02004208{
Or Gerlitz45f95ac2016-11-27 16:51:35 +02004209 mlx5_eth_lag_cleanup(dev);
Or Gerlitzca5b91d2016-11-27 16:51:36 +02004210 if (MLX5_CAP_GEN(dev->mdev, roce))
4211 mlx5_nic_vport_disable_roce(dev->mdev);
Achiad Shochatfc24fc52015-12-23 18:47:17 +02004212}
4213
Parav Pandite1f24a72017-04-16 07:29:29 +03004214struct mlx5_ib_counter {
Kamal Heib7c16f472017-01-18 15:25:09 +02004215 const char *name;
4216 size_t offset;
4217};
4218
4219#define INIT_Q_COUNTER(_name) \
4220 { .name = #_name, .offset = MLX5_BYTE_OFF(query_q_counter_out, _name)}
4221
Parav Pandite1f24a72017-04-16 07:29:29 +03004222static const struct mlx5_ib_counter basic_q_cnts[] = {
Kamal Heib7c16f472017-01-18 15:25:09 +02004223 INIT_Q_COUNTER(rx_write_requests),
4224 INIT_Q_COUNTER(rx_read_requests),
4225 INIT_Q_COUNTER(rx_atomic_requests),
4226 INIT_Q_COUNTER(out_of_buffer),
4227};
4228
Parav Pandite1f24a72017-04-16 07:29:29 +03004229static const struct mlx5_ib_counter out_of_seq_q_cnts[] = {
Kamal Heib7c16f472017-01-18 15:25:09 +02004230 INIT_Q_COUNTER(out_of_sequence),
4231};
4232
Parav Pandite1f24a72017-04-16 07:29:29 +03004233static const struct mlx5_ib_counter retrans_q_cnts[] = {
Kamal Heib7c16f472017-01-18 15:25:09 +02004234 INIT_Q_COUNTER(duplicate_request),
4235 INIT_Q_COUNTER(rnr_nak_retry_err),
4236 INIT_Q_COUNTER(packet_seq_err),
4237 INIT_Q_COUNTER(implied_nak_seq_err),
4238 INIT_Q_COUNTER(local_ack_timeout_err),
4239};
4240
Parav Pandite1f24a72017-04-16 07:29:29 +03004241#define INIT_CONG_COUNTER(_name) \
4242 { .name = #_name, .offset = \
4243 MLX5_BYTE_OFF(query_cong_statistics_out, _name ## _high)}
4244
4245static const struct mlx5_ib_counter cong_cnts[] = {
4246 INIT_CONG_COUNTER(rp_cnp_ignored),
4247 INIT_CONG_COUNTER(rp_cnp_handled),
4248 INIT_CONG_COUNTER(np_ecn_marked_roce_packets),
4249 INIT_CONG_COUNTER(np_cnp_sent),
4250};
4251
Parav Pandit58dcb602017-06-19 07:19:37 +03004252static const struct mlx5_ib_counter extended_err_cnts[] = {
4253 INIT_Q_COUNTER(resp_local_length_error),
4254 INIT_Q_COUNTER(resp_cqe_error),
4255 INIT_Q_COUNTER(req_cqe_error),
4256 INIT_Q_COUNTER(req_remote_invalid_request),
4257 INIT_Q_COUNTER(req_remote_access_errors),
4258 INIT_Q_COUNTER(resp_remote_access_errors),
4259 INIT_Q_COUNTER(resp_cqe_flush_error),
4260 INIT_Q_COUNTER(req_cqe_flush_error),
4261};
4262
Parav Pandite1f24a72017-04-16 07:29:29 +03004263static void mlx5_ib_dealloc_counters(struct mlx5_ib_dev *dev)
Mark Bloch0837e862016-06-17 15:10:55 +03004264{
Daniel Jurgensaac44922018-01-04 17:25:40 +02004265 int i;
Mark Bloch0837e862016-06-17 15:10:55 +03004266
Kamal Heib7c16f472017-01-18 15:25:09 +02004267 for (i = 0; i < dev->num_ports; i++) {
Daniel Jurgensaac44922018-01-04 17:25:40 +02004268 if (dev->port[i].cnts.set_id)
4269 mlx5_core_dealloc_q_counter(dev->mdev,
4270 dev->port[i].cnts.set_id);
Parav Pandite1f24a72017-04-16 07:29:29 +03004271 kfree(dev->port[i].cnts.names);
4272 kfree(dev->port[i].cnts.offsets);
Kamal Heib7c16f472017-01-18 15:25:09 +02004273 }
4274}
4275
Parav Pandite1f24a72017-04-16 07:29:29 +03004276static int __mlx5_ib_alloc_counters(struct mlx5_ib_dev *dev,
4277 struct mlx5_ib_counters *cnts)
Kamal Heib7c16f472017-01-18 15:25:09 +02004278{
4279 u32 num_counters;
4280
4281 num_counters = ARRAY_SIZE(basic_q_cnts);
4282
4283 if (MLX5_CAP_GEN(dev->mdev, out_of_seq_cnt))
4284 num_counters += ARRAY_SIZE(out_of_seq_q_cnts);
4285
4286 if (MLX5_CAP_GEN(dev->mdev, retransmission_q_counters))
4287 num_counters += ARRAY_SIZE(retrans_q_cnts);
Parav Pandit58dcb602017-06-19 07:19:37 +03004288
4289 if (MLX5_CAP_GEN(dev->mdev, enhanced_error_q_counters))
4290 num_counters += ARRAY_SIZE(extended_err_cnts);
4291
Parav Pandite1f24a72017-04-16 07:29:29 +03004292 cnts->num_q_counters = num_counters;
Kamal Heib7c16f472017-01-18 15:25:09 +02004293
Parav Pandite1f24a72017-04-16 07:29:29 +03004294 if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) {
4295 cnts->num_cong_counters = ARRAY_SIZE(cong_cnts);
4296 num_counters += ARRAY_SIZE(cong_cnts);
4297 }
4298
4299 cnts->names = kcalloc(num_counters, sizeof(cnts->names), GFP_KERNEL);
4300 if (!cnts->names)
Kamal Heib7c16f472017-01-18 15:25:09 +02004301 return -ENOMEM;
4302
Parav Pandite1f24a72017-04-16 07:29:29 +03004303 cnts->offsets = kcalloc(num_counters,
4304 sizeof(cnts->offsets), GFP_KERNEL);
4305 if (!cnts->offsets)
Kamal Heib7c16f472017-01-18 15:25:09 +02004306 goto err_names;
4307
Kamal Heib7c16f472017-01-18 15:25:09 +02004308 return 0;
4309
4310err_names:
Parav Pandite1f24a72017-04-16 07:29:29 +03004311 kfree(cnts->names);
Daniel Jurgensaac44922018-01-04 17:25:40 +02004312 cnts->names = NULL;
Kamal Heib7c16f472017-01-18 15:25:09 +02004313 return -ENOMEM;
4314}
4315
Parav Pandite1f24a72017-04-16 07:29:29 +03004316static void mlx5_ib_fill_counters(struct mlx5_ib_dev *dev,
4317 const char **names,
4318 size_t *offsets)
Kamal Heib7c16f472017-01-18 15:25:09 +02004319{
4320 int i;
4321 int j = 0;
4322
4323 for (i = 0; i < ARRAY_SIZE(basic_q_cnts); i++, j++) {
4324 names[j] = basic_q_cnts[i].name;
4325 offsets[j] = basic_q_cnts[i].offset;
4326 }
4327
4328 if (MLX5_CAP_GEN(dev->mdev, out_of_seq_cnt)) {
4329 for (i = 0; i < ARRAY_SIZE(out_of_seq_q_cnts); i++, j++) {
4330 names[j] = out_of_seq_q_cnts[i].name;
4331 offsets[j] = out_of_seq_q_cnts[i].offset;
4332 }
4333 }
4334
4335 if (MLX5_CAP_GEN(dev->mdev, retransmission_q_counters)) {
4336 for (i = 0; i < ARRAY_SIZE(retrans_q_cnts); i++, j++) {
4337 names[j] = retrans_q_cnts[i].name;
4338 offsets[j] = retrans_q_cnts[i].offset;
4339 }
4340 }
Parav Pandite1f24a72017-04-16 07:29:29 +03004341
Parav Pandit58dcb602017-06-19 07:19:37 +03004342 if (MLX5_CAP_GEN(dev->mdev, enhanced_error_q_counters)) {
4343 for (i = 0; i < ARRAY_SIZE(extended_err_cnts); i++, j++) {
4344 names[j] = extended_err_cnts[i].name;
4345 offsets[j] = extended_err_cnts[i].offset;
4346 }
4347 }
4348
Parav Pandite1f24a72017-04-16 07:29:29 +03004349 if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) {
4350 for (i = 0; i < ARRAY_SIZE(cong_cnts); i++, j++) {
4351 names[j] = cong_cnts[i].name;
4352 offsets[j] = cong_cnts[i].offset;
4353 }
4354 }
Mark Bloch0837e862016-06-17 15:10:55 +03004355}
4356
Parav Pandite1f24a72017-04-16 07:29:29 +03004357static int mlx5_ib_alloc_counters(struct mlx5_ib_dev *dev)
Mark Bloch0837e862016-06-17 15:10:55 +03004358{
Daniel Jurgensaac44922018-01-04 17:25:40 +02004359 int err = 0;
Mark Bloch0837e862016-06-17 15:10:55 +03004360 int i;
Mark Bloch0837e862016-06-17 15:10:55 +03004361
4362 for (i = 0; i < dev->num_ports; i++) {
Daniel Jurgensaac44922018-01-04 17:25:40 +02004363 err = __mlx5_ib_alloc_counters(dev, &dev->port[i].cnts);
4364 if (err)
4365 goto err_alloc;
Kamal Heib7c16f472017-01-18 15:25:09 +02004366
Daniel Jurgensaac44922018-01-04 17:25:40 +02004367 mlx5_ib_fill_counters(dev, dev->port[i].cnts.names,
4368 dev->port[i].cnts.offsets);
4369
4370 err = mlx5_core_alloc_q_counter(dev->mdev,
4371 &dev->port[i].cnts.set_id);
4372 if (err) {
Mark Bloch0837e862016-06-17 15:10:55 +03004373 mlx5_ib_warn(dev,
4374 "couldn't allocate queue counter for port %d, err %d\n",
Daniel Jurgensaac44922018-01-04 17:25:40 +02004375 i + 1, err);
4376 goto err_alloc;
Mark Bloch0837e862016-06-17 15:10:55 +03004377 }
Daniel Jurgensaac44922018-01-04 17:25:40 +02004378 dev->port[i].cnts.set_id_valid = true;
Mark Bloch0837e862016-06-17 15:10:55 +03004379 }
4380
4381 return 0;
4382
Daniel Jurgensaac44922018-01-04 17:25:40 +02004383err_alloc:
4384 mlx5_ib_dealloc_counters(dev);
4385 return err;
Mark Bloch0837e862016-06-17 15:10:55 +03004386}
4387
Mark Bloch0ad17a82016-06-17 15:10:56 +03004388static struct rdma_hw_stats *mlx5_ib_alloc_hw_stats(struct ib_device *ibdev,
4389 u8 port_num)
4390{
Kamal Heib7c16f472017-01-18 15:25:09 +02004391 struct mlx5_ib_dev *dev = to_mdev(ibdev);
4392 struct mlx5_ib_port *port = &dev->port[port_num - 1];
Mark Bloch0ad17a82016-06-17 15:10:56 +03004393
4394 /* We support only per port stats */
4395 if (port_num == 0)
4396 return NULL;
4397
Parav Pandite1f24a72017-04-16 07:29:29 +03004398 return rdma_alloc_hw_stats_struct(port->cnts.names,
4399 port->cnts.num_q_counters +
4400 port->cnts.num_cong_counters,
Mark Bloch0ad17a82016-06-17 15:10:56 +03004401 RDMA_HW_STATS_DEFAULT_LIFESPAN);
4402}
4403
Daniel Jurgensaac44922018-01-04 17:25:40 +02004404static int mlx5_ib_query_q_counters(struct mlx5_core_dev *mdev,
Parav Pandite1f24a72017-04-16 07:29:29 +03004405 struct mlx5_ib_port *port,
4406 struct rdma_hw_stats *stats)
4407{
4408 int outlen = MLX5_ST_SZ_BYTES(query_q_counter_out);
4409 void *out;
4410 __be32 val;
4411 int ret, i;
4412
Leon Romanovsky1b9a07e2017-05-10 21:32:18 +03004413 out = kvzalloc(outlen, GFP_KERNEL);
Parav Pandite1f24a72017-04-16 07:29:29 +03004414 if (!out)
4415 return -ENOMEM;
4416
Daniel Jurgensaac44922018-01-04 17:25:40 +02004417 ret = mlx5_core_query_q_counter(mdev,
Parav Pandite1f24a72017-04-16 07:29:29 +03004418 port->cnts.set_id, 0,
4419 out, outlen);
4420 if (ret)
4421 goto free;
4422
4423 for (i = 0; i < port->cnts.num_q_counters; i++) {
4424 val = *(__be32 *)(out + port->cnts.offsets[i]);
4425 stats->value[i] = (u64)be32_to_cpu(val);
4426 }
4427
4428free:
4429 kvfree(out);
4430 return ret;
4431}
4432
Mark Bloch0ad17a82016-06-17 15:10:56 +03004433static int mlx5_ib_get_hw_stats(struct ib_device *ibdev,
4434 struct rdma_hw_stats *stats,
Kamal Heib7c16f472017-01-18 15:25:09 +02004435 u8 port_num, int index)
Mark Bloch0ad17a82016-06-17 15:10:56 +03004436{
4437 struct mlx5_ib_dev *dev = to_mdev(ibdev);
Kamal Heib7c16f472017-01-18 15:25:09 +02004438 struct mlx5_ib_port *port = &dev->port[port_num - 1];
Daniel Jurgensaac44922018-01-04 17:25:40 +02004439 struct mlx5_core_dev *mdev;
Parav Pandite1f24a72017-04-16 07:29:29 +03004440 int ret, num_counters;
Daniel Jurgensaac44922018-01-04 17:25:40 +02004441 u8 mdev_port_num;
Mark Bloch0ad17a82016-06-17 15:10:56 +03004442
Kamal Heib7c16f472017-01-18 15:25:09 +02004443 if (!stats)
Parav Pandite1f24a72017-04-16 07:29:29 +03004444 return -EINVAL;
Mark Bloch0ad17a82016-06-17 15:10:56 +03004445
Daniel Jurgensaac44922018-01-04 17:25:40 +02004446 num_counters = port->cnts.num_q_counters + port->cnts.num_cong_counters;
4447
4448 /* q_counters are per IB device, query the master mdev */
4449 ret = mlx5_ib_query_q_counters(dev->mdev, port, stats);
Mark Bloch0ad17a82016-06-17 15:10:56 +03004450 if (ret)
Parav Pandite1f24a72017-04-16 07:29:29 +03004451 return ret;
Mark Bloch0ad17a82016-06-17 15:10:56 +03004452
Parav Pandite1f24a72017-04-16 07:29:29 +03004453 if (MLX5_CAP_GEN(dev->mdev, cc_query_allowed)) {
Daniel Jurgensaac44922018-01-04 17:25:40 +02004454 mdev = mlx5_ib_get_native_port_mdev(dev, port_num,
4455 &mdev_port_num);
4456 if (!mdev) {
4457 /* If port is not affiliated yet, its in down state
4458 * which doesn't have any counters yet, so it would be
4459 * zero. So no need to read from the HCA.
4460 */
4461 goto done;
4462 }
Majd Dibbiny71a0ff62017-12-21 17:38:26 +02004463 ret = mlx5_lag_query_cong_counters(dev->mdev,
4464 stats->value +
4465 port->cnts.num_q_counters,
4466 port->cnts.num_cong_counters,
4467 port->cnts.offsets +
4468 port->cnts.num_q_counters);
Daniel Jurgensaac44922018-01-04 17:25:40 +02004469
4470 mlx5_ib_put_native_port_mdev(dev, port_num);
Parav Pandite1f24a72017-04-16 07:29:29 +03004471 if (ret)
4472 return ret;
Mark Bloch0ad17a82016-06-17 15:10:56 +03004473 }
Kamal Heib7c16f472017-01-18 15:25:09 +02004474
Daniel Jurgensaac44922018-01-04 17:25:40 +02004475done:
Parav Pandite1f24a72017-04-16 07:29:29 +03004476 return num_counters;
Mark Bloch0ad17a82016-06-17 15:10:56 +03004477}
4478
Niranjana Vishwanathapura8e959602017-06-30 13:14:46 -07004479static void mlx5_ib_free_rdma_netdev(struct net_device *netdev)
4480{
4481 return mlx5_rdma_netdev_free(netdev);
4482}
4483
Erez Shitrit693dfd52017-04-27 17:01:34 +03004484static struct net_device*
4485mlx5_ib_alloc_rdma_netdev(struct ib_device *hca,
4486 u8 port_num,
4487 enum rdma_netdev_t type,
4488 const char *name,
4489 unsigned char name_assign_type,
4490 void (*setup)(struct net_device *))
4491{
Niranjana Vishwanathapura8e959602017-06-30 13:14:46 -07004492 struct net_device *netdev;
4493 struct rdma_netdev *rn;
4494
Erez Shitrit693dfd52017-04-27 17:01:34 +03004495 if (type != RDMA_NETDEV_IPOIB)
4496 return ERR_PTR(-EOPNOTSUPP);
4497
Niranjana Vishwanathapura8e959602017-06-30 13:14:46 -07004498 netdev = mlx5_rdma_netdev_alloc(to_mdev(hca)->mdev, hca,
4499 name, setup);
4500 if (likely(!IS_ERR_OR_NULL(netdev))) {
4501 rn = netdev_priv(netdev);
4502 rn->free_rdma_netdev = mlx5_ib_free_rdma_netdev;
4503 }
4504 return netdev;
Erez Shitrit693dfd52017-04-27 17:01:34 +03004505}
4506
Maor Gottliebfe248c32017-05-30 10:29:14 +03004507static void delay_drop_debugfs_cleanup(struct mlx5_ib_dev *dev)
4508{
4509 if (!dev->delay_drop.dbg)
4510 return;
4511 debugfs_remove_recursive(dev->delay_drop.dbg->dir_debugfs);
4512 kfree(dev->delay_drop.dbg);
4513 dev->delay_drop.dbg = NULL;
4514}
4515
Maor Gottlieb03404e82017-05-30 10:29:13 +03004516static void cancel_delay_drop(struct mlx5_ib_dev *dev)
4517{
4518 if (!(dev->ib_dev.attrs.raw_packet_caps & IB_RAW_PACKET_CAP_DELAY_DROP))
4519 return;
4520
4521 cancel_work_sync(&dev->delay_drop.delay_drop_work);
Maor Gottliebfe248c32017-05-30 10:29:14 +03004522 delay_drop_debugfs_cleanup(dev);
4523}
4524
4525static ssize_t delay_drop_timeout_read(struct file *filp, char __user *buf,
4526 size_t count, loff_t *pos)
4527{
4528 struct mlx5_ib_delay_drop *delay_drop = filp->private_data;
4529 char lbuf[20];
4530 int len;
4531
4532 len = snprintf(lbuf, sizeof(lbuf), "%u\n", delay_drop->timeout);
4533 return simple_read_from_buffer(buf, count, pos, lbuf, len);
4534}
4535
4536static ssize_t delay_drop_timeout_write(struct file *filp, const char __user *buf,
4537 size_t count, loff_t *pos)
4538{
4539 struct mlx5_ib_delay_drop *delay_drop = filp->private_data;
4540 u32 timeout;
4541 u32 var;
4542
4543 if (kstrtouint_from_user(buf, count, 0, &var))
4544 return -EFAULT;
4545
4546 timeout = min_t(u32, roundup(var, 100), MLX5_MAX_DELAY_DROP_TIMEOUT_MS *
4547 1000);
4548 if (timeout != var)
4549 mlx5_ib_dbg(delay_drop->dev, "Round delay drop timeout to %u usec\n",
4550 timeout);
4551
4552 delay_drop->timeout = timeout;
4553
4554 return count;
4555}
4556
4557static const struct file_operations fops_delay_drop_timeout = {
4558 .owner = THIS_MODULE,
4559 .open = simple_open,
4560 .write = delay_drop_timeout_write,
4561 .read = delay_drop_timeout_read,
4562};
4563
4564static int delay_drop_debugfs_init(struct mlx5_ib_dev *dev)
4565{
4566 struct mlx5_ib_dbg_delay_drop *dbg;
4567
4568 if (!mlx5_debugfs_root)
4569 return 0;
4570
4571 dbg = kzalloc(sizeof(*dbg), GFP_KERNEL);
4572 if (!dbg)
4573 return -ENOMEM;
4574
Sudip Mukherjeecbafad82017-09-18 12:28:48 +01004575 dev->delay_drop.dbg = dbg;
4576
Maor Gottliebfe248c32017-05-30 10:29:14 +03004577 dbg->dir_debugfs =
4578 debugfs_create_dir("delay_drop",
4579 dev->mdev->priv.dbg_root);
4580 if (!dbg->dir_debugfs)
Sudip Mukherjeecbafad82017-09-18 12:28:48 +01004581 goto out_debugfs;
Maor Gottliebfe248c32017-05-30 10:29:14 +03004582
4583 dbg->events_cnt_debugfs =
4584 debugfs_create_atomic_t("num_timeout_events", 0400,
4585 dbg->dir_debugfs,
4586 &dev->delay_drop.events_cnt);
4587 if (!dbg->events_cnt_debugfs)
4588 goto out_debugfs;
4589
4590 dbg->rqs_cnt_debugfs =
4591 debugfs_create_atomic_t("num_rqs", 0400,
4592 dbg->dir_debugfs,
4593 &dev->delay_drop.rqs_cnt);
4594 if (!dbg->rqs_cnt_debugfs)
4595 goto out_debugfs;
4596
4597 dbg->timeout_debugfs =
4598 debugfs_create_file("timeout", 0600,
4599 dbg->dir_debugfs,
4600 &dev->delay_drop,
4601 &fops_delay_drop_timeout);
4602 if (!dbg->timeout_debugfs)
4603 goto out_debugfs;
4604
4605 return 0;
4606
4607out_debugfs:
4608 delay_drop_debugfs_cleanup(dev);
4609 return -ENOMEM;
Maor Gottlieb03404e82017-05-30 10:29:13 +03004610}
4611
4612static void init_delay_drop(struct mlx5_ib_dev *dev)
4613{
4614 if (!(dev->ib_dev.attrs.raw_packet_caps & IB_RAW_PACKET_CAP_DELAY_DROP))
4615 return;
4616
4617 mutex_init(&dev->delay_drop.lock);
4618 dev->delay_drop.dev = dev;
4619 dev->delay_drop.activate = false;
4620 dev->delay_drop.timeout = MLX5_MAX_DELAY_DROP_TIMEOUT_MS * 1000;
4621 INIT_WORK(&dev->delay_drop.delay_drop_work, delay_drop_handler);
Maor Gottliebfe248c32017-05-30 10:29:14 +03004622 atomic_set(&dev->delay_drop.rqs_cnt, 0);
4623 atomic_set(&dev->delay_drop.events_cnt, 0);
4624
4625 if (delay_drop_debugfs_init(dev))
4626 mlx5_ib_warn(dev, "Failed to init delay drop debugfs\n");
Maor Gottlieb03404e82017-05-30 10:29:13 +03004627}
4628
Leon Romanovsky84305d712017-08-17 15:50:53 +03004629static const struct cpumask *
4630mlx5_ib_get_vector_affinity(struct ib_device *ibdev, int comp_vector)
Sagi Grimberg40b24402017-07-13 11:09:42 +03004631{
4632 struct mlx5_ib_dev *dev = to_mdev(ibdev);
4633
4634 return mlx5_get_vector_affinity(dev->mdev, comp_vector);
4635}
4636
Daniel Jurgens32f69e42018-01-04 17:25:36 +02004637/* The mlx5_ib_multiport_mutex should be held when calling this function */
4638static void mlx5_ib_unbind_slave_port(struct mlx5_ib_dev *ibdev,
4639 struct mlx5_ib_multiport_info *mpi)
4640{
4641 u8 port_num = mlx5_core_native_port_num(mpi->mdev) - 1;
4642 struct mlx5_ib_port *port = &ibdev->port[port_num];
4643 int comps;
4644 int err;
4645 int i;
4646
Parav Pandita9e546e2018-01-04 17:25:39 +02004647 mlx5_ib_cleanup_cong_debugfs(ibdev, port_num);
4648
Daniel Jurgens32f69e42018-01-04 17:25:36 +02004649 spin_lock(&port->mp.mpi_lock);
4650 if (!mpi->ibdev) {
4651 spin_unlock(&port->mp.mpi_lock);
4652 return;
4653 }
4654 mpi->ibdev = NULL;
4655
4656 spin_unlock(&port->mp.mpi_lock);
4657 mlx5_remove_netdev_notifier(ibdev, port_num);
4658 spin_lock(&port->mp.mpi_lock);
4659
4660 comps = mpi->mdev_refcnt;
4661 if (comps) {
4662 mpi->unaffiliate = true;
4663 init_completion(&mpi->unref_comp);
4664 spin_unlock(&port->mp.mpi_lock);
4665
4666 for (i = 0; i < comps; i++)
4667 wait_for_completion(&mpi->unref_comp);
4668
4669 spin_lock(&port->mp.mpi_lock);
4670 mpi->unaffiliate = false;
4671 }
4672
4673 port->mp.mpi = NULL;
4674
4675 list_add_tail(&mpi->list, &mlx5_ib_unaffiliated_port_list);
4676
4677 spin_unlock(&port->mp.mpi_lock);
4678
4679 err = mlx5_nic_vport_unaffiliate_multiport(mpi->mdev);
4680
4681 mlx5_ib_dbg(ibdev, "unaffiliated port %d\n", port_num + 1);
4682 /* Log an error, still needed to cleanup the pointers and add
4683 * it back to the list.
4684 */
4685 if (err)
4686 mlx5_ib_err(ibdev, "Failed to unaffiliate port %u\n",
4687 port_num + 1);
4688
4689 ibdev->roce[port_num].last_port_state = IB_PORT_DOWN;
4690}
4691
4692/* The mlx5_ib_multiport_mutex should be held when calling this function */
4693static bool mlx5_ib_bind_slave_port(struct mlx5_ib_dev *ibdev,
4694 struct mlx5_ib_multiport_info *mpi)
4695{
4696 u8 port_num = mlx5_core_native_port_num(mpi->mdev) - 1;
4697 int err;
4698
4699 spin_lock(&ibdev->port[port_num].mp.mpi_lock);
4700 if (ibdev->port[port_num].mp.mpi) {
4701 mlx5_ib_warn(ibdev, "port %d already affiliated.\n",
4702 port_num + 1);
4703 spin_unlock(&ibdev->port[port_num].mp.mpi_lock);
4704 return false;
4705 }
4706
4707 ibdev->port[port_num].mp.mpi = mpi;
4708 mpi->ibdev = ibdev;
4709 spin_unlock(&ibdev->port[port_num].mp.mpi_lock);
4710
4711 err = mlx5_nic_vport_affiliate_multiport(ibdev->mdev, mpi->mdev);
4712 if (err)
4713 goto unbind;
4714
4715 err = get_port_caps(ibdev, mlx5_core_native_port_num(mpi->mdev));
4716 if (err)
4717 goto unbind;
4718
4719 err = mlx5_add_netdev_notifier(ibdev, port_num);
4720 if (err) {
4721 mlx5_ib_err(ibdev, "failed adding netdev notifier for port %u\n",
4722 port_num + 1);
4723 goto unbind;
4724 }
4725
Parav Pandita9e546e2018-01-04 17:25:39 +02004726 err = mlx5_ib_init_cong_debugfs(ibdev, port_num);
4727 if (err)
4728 goto unbind;
4729
Daniel Jurgens32f69e42018-01-04 17:25:36 +02004730 return true;
4731
4732unbind:
4733 mlx5_ib_unbind_slave_port(ibdev, mpi);
4734 return false;
4735}
4736
4737static int mlx5_ib_init_multiport_master(struct mlx5_ib_dev *dev)
4738{
4739 int port_num = mlx5_core_native_port_num(dev->mdev) - 1;
4740 enum rdma_link_layer ll = mlx5_ib_port_link_layer(&dev->ib_dev,
4741 port_num + 1);
4742 struct mlx5_ib_multiport_info *mpi;
4743 int err;
4744 int i;
4745
4746 if (!mlx5_core_is_mp_master(dev->mdev) || ll != IB_LINK_LAYER_ETHERNET)
4747 return 0;
4748
4749 err = mlx5_query_nic_vport_system_image_guid(dev->mdev,
4750 &dev->sys_image_guid);
4751 if (err)
4752 return err;
4753
4754 err = mlx5_nic_vport_enable_roce(dev->mdev);
4755 if (err)
4756 return err;
4757
4758 mutex_lock(&mlx5_ib_multiport_mutex);
4759 for (i = 0; i < dev->num_ports; i++) {
4760 bool bound = false;
4761
4762 /* build a stub multiport info struct for the native port. */
4763 if (i == port_num) {
4764 mpi = kzalloc(sizeof(*mpi), GFP_KERNEL);
4765 if (!mpi) {
4766 mutex_unlock(&mlx5_ib_multiport_mutex);
4767 mlx5_nic_vport_disable_roce(dev->mdev);
4768 return -ENOMEM;
4769 }
4770
4771 mpi->is_master = true;
4772 mpi->mdev = dev->mdev;
4773 mpi->sys_image_guid = dev->sys_image_guid;
4774 dev->port[i].mp.mpi = mpi;
4775 mpi->ibdev = dev;
4776 mpi = NULL;
4777 continue;
4778 }
4779
4780 list_for_each_entry(mpi, &mlx5_ib_unaffiliated_port_list,
4781 list) {
4782 if (dev->sys_image_guid == mpi->sys_image_guid &&
4783 (mlx5_core_native_port_num(mpi->mdev) - 1) == i) {
4784 bound = mlx5_ib_bind_slave_port(dev, mpi);
4785 }
4786
4787 if (bound) {
4788 dev_dbg(&mpi->mdev->pdev->dev, "removing port from unaffiliated list.\n");
4789 mlx5_ib_dbg(dev, "port %d bound\n", i + 1);
4790 list_del(&mpi->list);
4791 break;
4792 }
4793 }
4794 if (!bound) {
4795 get_port_caps(dev, i + 1);
4796 mlx5_ib_dbg(dev, "no free port found for port %d\n",
4797 i + 1);
4798 }
4799 }
4800
4801 list_add_tail(&dev->ib_dev_list, &mlx5_ib_dev_list);
4802 mutex_unlock(&mlx5_ib_multiport_mutex);
4803 return err;
4804}
4805
4806static void mlx5_ib_cleanup_multiport_master(struct mlx5_ib_dev *dev)
4807{
4808 int port_num = mlx5_core_native_port_num(dev->mdev) - 1;
4809 enum rdma_link_layer ll = mlx5_ib_port_link_layer(&dev->ib_dev,
4810 port_num + 1);
4811 int i;
4812
4813 if (!mlx5_core_is_mp_master(dev->mdev) || ll != IB_LINK_LAYER_ETHERNET)
4814 return;
4815
4816 mutex_lock(&mlx5_ib_multiport_mutex);
4817 for (i = 0; i < dev->num_ports; i++) {
4818 if (dev->port[i].mp.mpi) {
4819 /* Destroy the native port stub */
4820 if (i == port_num) {
4821 kfree(dev->port[i].mp.mpi);
4822 dev->port[i].mp.mpi = NULL;
4823 } else {
4824 mlx5_ib_dbg(dev, "unbinding port_num: %d\n", i + 1);
4825 mlx5_ib_unbind_slave_port(dev, dev->port[i].mp.mpi);
4826 }
4827 }
4828 }
4829
4830 mlx5_ib_dbg(dev, "removing from devlist\n");
4831 list_del(&dev->ib_dev_list);
4832 mutex_unlock(&mlx5_ib_multiport_mutex);
4833
4834 mlx5_nic_vport_disable_roce(dev->mdev);
4835}
4836
Aviad Yehezkelc6475a02018-03-28 09:27:50 +03004837ADD_UVERBS_ATTRIBUTES_SIMPLE(mlx5_ib_flow_action, UVERBS_OBJECT_FLOW_ACTION,
4838 UVERBS_METHOD_FLOW_ACTION_ESP_CREATE,
4839 &UVERBS_ATTR_PTR_IN(MLX5_IB_ATTR_CREATE_FLOW_ACTION_FLAGS,
4840 UVERBS_ATTR_TYPE(u64),
4841 UA_FLAGS(UVERBS_ATTR_SPEC_F_MANDATORY)));
4842
4843#define NUM_TREES 1
Matan Barak8c846602018-03-28 09:27:41 +03004844static int populate_specs_root(struct mlx5_ib_dev *dev)
4845{
4846 const struct uverbs_object_tree_def *default_root[NUM_TREES + 1] = {
4847 uverbs_default_get_objects()};
4848 size_t num_trees = 1;
4849
Aviad Yehezkelc6475a02018-03-28 09:27:50 +03004850 if (mlx5_accel_ipsec_device_caps(dev->mdev) & MLX5_ACCEL_IPSEC_CAP_DEVICE &&
4851 !WARN_ON(num_trees >= ARRAY_SIZE(default_root)))
4852 default_root[num_trees++] = &mlx5_ib_flow_action;
4853
Matan Barak8c846602018-03-28 09:27:41 +03004854 dev->ib_dev.specs_root =
4855 uverbs_alloc_spec_tree(num_trees, default_root);
4856
4857 return PTR_ERR_OR_ZERO(dev->ib_dev.specs_root);
4858}
4859
4860static void depopulate_specs_root(struct mlx5_ib_dev *dev)
4861{
4862 uverbs_free_spec_tree(dev->ib_dev.specs_root);
4863}
4864
Mark Blochb5ca15a2018-01-23 11:16:30 +00004865void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev)
Eli Cohene126ba92013-07-07 17:25:49 +03004866{
Daniel Jurgens32f69e42018-01-04 17:25:36 +02004867 mlx5_ib_cleanup_multiport_master(dev);
Mark Bloch3cc297d2018-01-01 13:07:03 +02004868#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
4869 cleanup_srcu_struct(&dev->mr_srcu);
4870#endif
Mark Bloch16c19752018-01-01 13:06:58 +02004871 kfree(dev->port);
4872}
4873
Mark Blochb5ca15a2018-01-23 11:16:30 +00004874int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02004875{
4876 struct mlx5_core_dev *mdev = dev->mdev;
Aviv Heller4babcf92016-09-18 20:48:03 +03004877 const char *name;
Eli Cohene126ba92013-07-07 17:25:49 +03004878 int err;
Daniel Jurgens32f69e42018-01-04 17:25:36 +02004879 int i;
Eli Cohene126ba92013-07-07 17:25:49 +03004880
Daniel Jurgens508562d2018-01-04 17:25:34 +02004881 dev->port = kcalloc(dev->num_ports, sizeof(*dev->port),
Mark Bloch0837e862016-06-17 15:10:55 +03004882 GFP_KERNEL);
4883 if (!dev->port)
Mark Bloch16c19752018-01-01 13:06:58 +02004884 return -ENOMEM;
Mark Bloch0837e862016-06-17 15:10:55 +03004885
Daniel Jurgens32f69e42018-01-04 17:25:36 +02004886 for (i = 0; i < dev->num_ports; i++) {
4887 spin_lock_init(&dev->port[i].mp.mpi_lock);
4888 rwlock_init(&dev->roce[i].netdev_lock);
4889 }
4890
4891 err = mlx5_ib_init_multiport_master(dev);
Eli Cohene126ba92013-07-07 17:25:49 +03004892 if (err)
Mark Bloch0837e862016-06-17 15:10:55 +03004893 goto err_free_port;
Eli Cohene126ba92013-07-07 17:25:49 +03004894
Daniel Jurgens32f69e42018-01-04 17:25:36 +02004895 if (!mlx5_core_mp_enabled(mdev)) {
Daniel Jurgens32f69e42018-01-04 17:25:36 +02004896 for (i = 1; i <= dev->num_ports; i++) {
4897 err = get_port_caps(dev, i);
4898 if (err)
4899 break;
4900 }
4901 } else {
4902 err = get_port_caps(dev, mlx5_core_native_port_num(mdev));
4903 }
4904 if (err)
4905 goto err_mp;
4906
Majd Dibbiny1b5daf12015-06-04 19:30:46 +03004907 if (mlx5_use_mad_ifc(dev))
4908 get_ext_port_caps(dev);
Eli Cohene126ba92013-07-07 17:25:49 +03004909
Aviv Heller4babcf92016-09-18 20:48:03 +03004910 if (!mlx5_lag_is_active(mdev))
4911 name = "mlx5_%d";
4912 else
4913 name = "mlx5_bond_%d";
4914
4915 strlcpy(dev->ib_dev.name, name, IB_DEVICE_NAME_MAX);
Eli Cohene126ba92013-07-07 17:25:49 +03004916 dev->ib_dev.owner = THIS_MODULE;
4917 dev->ib_dev.node_type = RDMA_NODE_IB_CA;
Sagi Grimbergc6790aa2015-09-24 10:34:23 +03004918 dev->ib_dev.local_dma_lkey = 0 /* not supported for now */;
Daniel Jurgens508562d2018-01-04 17:25:34 +02004919 dev->ib_dev.phys_port_cnt = dev->num_ports;
Saeed Mahameed233d05d2015-04-02 17:07:32 +03004920 dev->ib_dev.num_comp_vectors =
4921 dev->mdev->priv.eq_table.num_comp_vectors;
Bart Van Assche9b0c2892017-01-20 13:04:21 -08004922 dev->ib_dev.dev.parent = &mdev->pdev->dev;
Eli Cohene126ba92013-07-07 17:25:49 +03004923
Mark Bloch3cc297d2018-01-01 13:07:03 +02004924 mutex_init(&dev->cap_mask_mutex);
4925 INIT_LIST_HEAD(&dev->qp_list);
4926 spin_lock_init(&dev->reset_flow_resource_lock);
4927
4928#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
4929 err = init_srcu_struct(&dev->mr_srcu);
4930 if (err)
4931 goto err_free_port;
4932#endif
4933
Mark Bloch16c19752018-01-01 13:06:58 +02004934 return 0;
Daniel Jurgens32f69e42018-01-04 17:25:36 +02004935err_mp:
4936 mlx5_ib_cleanup_multiport_master(dev);
Mark Bloch16c19752018-01-01 13:06:58 +02004937
4938err_free_port:
4939 kfree(dev->port);
4940
4941 return -ENOMEM;
4942}
4943
Mark Bloch9a4ca382018-01-16 14:42:35 +00004944static int mlx5_ib_stage_flow_db_init(struct mlx5_ib_dev *dev)
4945{
4946 dev->flow_db = kzalloc(sizeof(*dev->flow_db), GFP_KERNEL);
4947
4948 if (!dev->flow_db)
4949 return -ENOMEM;
4950
4951 mutex_init(&dev->flow_db->lock);
4952
4953 return 0;
4954}
4955
Mark Blochb5ca15a2018-01-23 11:16:30 +00004956int mlx5_ib_stage_rep_flow_db_init(struct mlx5_ib_dev *dev)
4957{
4958 struct mlx5_ib_dev *nic_dev;
4959
4960 nic_dev = mlx5_ib_get_uplink_ibdev(dev->mdev->priv.eswitch);
4961
4962 if (!nic_dev)
4963 return -EINVAL;
4964
4965 dev->flow_db = nic_dev->flow_db;
4966
4967 return 0;
4968}
4969
Mark Bloch9a4ca382018-01-16 14:42:35 +00004970static void mlx5_ib_stage_flow_db_cleanup(struct mlx5_ib_dev *dev)
4971{
4972 kfree(dev->flow_db);
4973}
4974
Mark Blochb5ca15a2018-01-23 11:16:30 +00004975int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02004976{
4977 struct mlx5_core_dev *mdev = dev->mdev;
Mark Bloch16c19752018-01-01 13:06:58 +02004978 int err;
4979
Eli Cohene126ba92013-07-07 17:25:49 +03004980 dev->ib_dev.uverbs_abi_ver = MLX5_IB_UVERBS_ABI_VERSION;
4981 dev->ib_dev.uverbs_cmd_mask =
4982 (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) |
4983 (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) |
4984 (1ull << IB_USER_VERBS_CMD_QUERY_PORT) |
4985 (1ull << IB_USER_VERBS_CMD_ALLOC_PD) |
4986 (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) |
Moni Shoua41c450f2016-11-23 08:23:26 +02004987 (1ull << IB_USER_VERBS_CMD_CREATE_AH) |
4988 (1ull << IB_USER_VERBS_CMD_DESTROY_AH) |
Eli Cohene126ba92013-07-07 17:25:49 +03004989 (1ull << IB_USER_VERBS_CMD_REG_MR) |
Noa Osherovich56e11d62016-02-29 16:46:51 +02004990 (1ull << IB_USER_VERBS_CMD_REREG_MR) |
Eli Cohene126ba92013-07-07 17:25:49 +03004991 (1ull << IB_USER_VERBS_CMD_DEREG_MR) |
4992 (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) |
4993 (1ull << IB_USER_VERBS_CMD_CREATE_CQ) |
4994 (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) |
4995 (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) |
4996 (1ull << IB_USER_VERBS_CMD_CREATE_QP) |
4997 (1ull << IB_USER_VERBS_CMD_MODIFY_QP) |
4998 (1ull << IB_USER_VERBS_CMD_QUERY_QP) |
4999 (1ull << IB_USER_VERBS_CMD_DESTROY_QP) |
5000 (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) |
5001 (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) |
5002 (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) |
5003 (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) |
5004 (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) |
5005 (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ) |
5006 (1ull << IB_USER_VERBS_CMD_CREATE_XSRQ) |
5007 (1ull << IB_USER_VERBS_CMD_OPEN_QP);
Haggai Eran1707cb42015-02-08 13:28:52 +02005008 dev->ib_dev.uverbs_ex_cmd_mask =
Matan Barakd4584dd2016-01-28 17:51:46 +02005009 (1ull << IB_USER_VERBS_EX_CMD_QUERY_DEVICE) |
5010 (1ull << IB_USER_VERBS_EX_CMD_CREATE_CQ) |
Bodong Wang7d29f342016-12-01 13:43:16 +02005011 (1ull << IB_USER_VERBS_EX_CMD_CREATE_QP) |
Yonatan Cohenb0e9df62017-11-13 10:51:15 +02005012 (1ull << IB_USER_VERBS_EX_CMD_MODIFY_QP) |
5013 (1ull << IB_USER_VERBS_EX_CMD_MODIFY_CQ);
Eli Cohene126ba92013-07-07 17:25:49 +03005014
5015 dev->ib_dev.query_device = mlx5_ib_query_device;
Achiad Shochatebd61f62015-12-23 18:47:16 +02005016 dev->ib_dev.get_link_layer = mlx5_ib_port_link_layer;
Eli Cohene126ba92013-07-07 17:25:49 +03005017 dev->ib_dev.query_gid = mlx5_ib_query_gid;
Achiad Shochat3cca2602015-12-23 18:47:23 +02005018 dev->ib_dev.add_gid = mlx5_ib_add_gid;
5019 dev->ib_dev.del_gid = mlx5_ib_del_gid;
Eli Cohene126ba92013-07-07 17:25:49 +03005020 dev->ib_dev.query_pkey = mlx5_ib_query_pkey;
5021 dev->ib_dev.modify_device = mlx5_ib_modify_device;
5022 dev->ib_dev.modify_port = mlx5_ib_modify_port;
5023 dev->ib_dev.alloc_ucontext = mlx5_ib_alloc_ucontext;
5024 dev->ib_dev.dealloc_ucontext = mlx5_ib_dealloc_ucontext;
5025 dev->ib_dev.mmap = mlx5_ib_mmap;
5026 dev->ib_dev.alloc_pd = mlx5_ib_alloc_pd;
5027 dev->ib_dev.dealloc_pd = mlx5_ib_dealloc_pd;
5028 dev->ib_dev.create_ah = mlx5_ib_create_ah;
5029 dev->ib_dev.query_ah = mlx5_ib_query_ah;
5030 dev->ib_dev.destroy_ah = mlx5_ib_destroy_ah;
5031 dev->ib_dev.create_srq = mlx5_ib_create_srq;
5032 dev->ib_dev.modify_srq = mlx5_ib_modify_srq;
5033 dev->ib_dev.query_srq = mlx5_ib_query_srq;
5034 dev->ib_dev.destroy_srq = mlx5_ib_destroy_srq;
5035 dev->ib_dev.post_srq_recv = mlx5_ib_post_srq_recv;
5036 dev->ib_dev.create_qp = mlx5_ib_create_qp;
5037 dev->ib_dev.modify_qp = mlx5_ib_modify_qp;
5038 dev->ib_dev.query_qp = mlx5_ib_query_qp;
5039 dev->ib_dev.destroy_qp = mlx5_ib_destroy_qp;
5040 dev->ib_dev.post_send = mlx5_ib_post_send;
5041 dev->ib_dev.post_recv = mlx5_ib_post_recv;
5042 dev->ib_dev.create_cq = mlx5_ib_create_cq;
5043 dev->ib_dev.modify_cq = mlx5_ib_modify_cq;
5044 dev->ib_dev.resize_cq = mlx5_ib_resize_cq;
5045 dev->ib_dev.destroy_cq = mlx5_ib_destroy_cq;
5046 dev->ib_dev.poll_cq = mlx5_ib_poll_cq;
5047 dev->ib_dev.req_notify_cq = mlx5_ib_arm_cq;
5048 dev->ib_dev.get_dma_mr = mlx5_ib_get_dma_mr;
5049 dev->ib_dev.reg_user_mr = mlx5_ib_reg_user_mr;
Noa Osherovich56e11d62016-02-29 16:46:51 +02005050 dev->ib_dev.rereg_user_mr = mlx5_ib_rereg_user_mr;
Eli Cohene126ba92013-07-07 17:25:49 +03005051 dev->ib_dev.dereg_mr = mlx5_ib_dereg_mr;
5052 dev->ib_dev.attach_mcast = mlx5_ib_mcg_attach;
5053 dev->ib_dev.detach_mcast = mlx5_ib_mcg_detach;
5054 dev->ib_dev.process_mad = mlx5_ib_process_mad;
Sagi Grimberg9bee1782015-07-30 10:32:35 +03005055 dev->ib_dev.alloc_mr = mlx5_ib_alloc_mr;
Sagi Grimberg8a187ee2015-10-13 19:11:26 +03005056 dev->ib_dev.map_mr_sg = mlx5_ib_map_mr_sg;
Sagi Grimbergd5436ba2014-02-23 14:19:12 +02005057 dev->ib_dev.check_mr_status = mlx5_ib_check_mr_status;
Ira Weinyc7342822016-06-15 02:22:01 -04005058 dev->ib_dev.get_dev_fw_str = get_dev_fw_str;
Sagi Grimberg40b24402017-07-13 11:09:42 +03005059 dev->ib_dev.get_vector_affinity = mlx5_ib_get_vector_affinity;
Niranjana Vishwanathapura8e959602017-06-30 13:14:46 -07005060 if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads))
Alex Vesker022d0382017-06-14 09:59:06 +03005061 dev->ib_dev.alloc_rdma_netdev = mlx5_ib_alloc_rdma_netdev;
Niranjana Vishwanathapura8e959602017-06-30 13:14:46 -07005062
Eli Coheneff901d2016-03-11 22:58:42 +02005063 if (mlx5_core_is_pf(mdev)) {
5064 dev->ib_dev.get_vf_config = mlx5_ib_get_vf_config;
5065 dev->ib_dev.set_vf_link_state = mlx5_ib_set_vf_link_state;
5066 dev->ib_dev.get_vf_stats = mlx5_ib_get_vf_stats;
5067 dev->ib_dev.set_vf_guid = mlx5_ib_set_vf_guid;
5068 }
Eli Cohene126ba92013-07-07 17:25:49 +03005069
Maor Gottlieb7c2344c2016-06-17 14:56:44 +03005070 dev->ib_dev.disassociate_ucontext = mlx5_ib_disassociate_ucontext;
5071
Max Gurtovoy6e8484c2017-05-28 10:53:11 +03005072 dev->umr_fence = mlx5_get_umr_fence(MLX5_CAP_GEN(mdev, umr_fence));
5073
Matan Barakd2370e02016-02-29 18:05:30 +02005074 if (MLX5_CAP_GEN(mdev, imaicl)) {
5075 dev->ib_dev.alloc_mw = mlx5_ib_alloc_mw;
5076 dev->ib_dev.dealloc_mw = mlx5_ib_dealloc_mw;
5077 dev->ib_dev.uverbs_cmd_mask |=
5078 (1ull << IB_USER_VERBS_CMD_ALLOC_MW) |
5079 (1ull << IB_USER_VERBS_CMD_DEALLOC_MW);
5080 }
5081
Saeed Mahameed938fe832015-05-28 22:28:41 +03005082 if (MLX5_CAP_GEN(mdev, xrc)) {
Eli Cohene126ba92013-07-07 17:25:49 +03005083 dev->ib_dev.alloc_xrcd = mlx5_ib_alloc_xrcd;
5084 dev->ib_dev.dealloc_xrcd = mlx5_ib_dealloc_xrcd;
5085 dev->ib_dev.uverbs_cmd_mask |=
5086 (1ull << IB_USER_VERBS_CMD_OPEN_XRCD) |
5087 (1ull << IB_USER_VERBS_CMD_CLOSE_XRCD);
5088 }
5089
Yishai Hadas81e30882017-06-08 16:15:09 +03005090 dev->ib_dev.create_flow = mlx5_ib_create_flow;
5091 dev->ib_dev.destroy_flow = mlx5_ib_destroy_flow;
5092 dev->ib_dev.uverbs_ex_cmd_mask |=
5093 (1ull << IB_USER_VERBS_EX_CMD_CREATE_FLOW) |
5094 (1ull << IB_USER_VERBS_EX_CMD_DESTROY_FLOW);
Aviad Yehezkelc6475a02018-03-28 09:27:50 +03005095 dev->ib_dev.create_flow_action_esp = mlx5_ib_create_flow_action_esp;
5096 dev->ib_dev.destroy_flow_action = mlx5_ib_destroy_flow_action;
Matan Barak349705c2018-03-28 09:27:51 +03005097 dev->ib_dev.modify_flow_action_esp = mlx5_ib_modify_flow_action_esp;
Matan Barak0ede73b2018-03-19 15:02:34 +02005098 dev->ib_dev.driver_id = RDMA_DRIVER_MLX5;
Yishai Hadas81e30882017-06-08 16:15:09 +03005099
Eli Cohene126ba92013-07-07 17:25:49 +03005100 err = init_node_data(dev);
5101 if (err)
Mark Bloch16c19752018-01-01 13:06:58 +02005102 return err;
Eli Cohene126ba92013-07-07 17:25:49 +03005103
Mark Blochc8b89922018-01-01 13:07:02 +02005104 if ((MLX5_CAP_GEN(dev->mdev, port_type) == MLX5_CAP_PORT_TYPE_ETH) &&
Jason Gunthorpee7996a92018-01-29 13:26:40 -07005105 (MLX5_CAP_GEN(dev->mdev, disable_local_lb_uc) ||
5106 MLX5_CAP_GEN(dev->mdev, disable_local_lb_mc)))
Mark Blochc8b89922018-01-01 13:07:02 +02005107 mutex_init(&dev->lb_mutex);
5108
Mark Bloch16c19752018-01-01 13:06:58 +02005109 return 0;
5110}
5111
Mark Bloch8e6efa32017-11-06 12:22:13 +00005112static int mlx5_ib_stage_non_default_cb(struct mlx5_ib_dev *dev)
5113{
5114 dev->ib_dev.get_port_immutable = mlx5_port_immutable;
5115 dev->ib_dev.query_port = mlx5_ib_query_port;
5116
5117 return 0;
5118}
5119
Mark Blochb5ca15a2018-01-23 11:16:30 +00005120int mlx5_ib_stage_rep_non_default_cb(struct mlx5_ib_dev *dev)
Mark Bloch8e6efa32017-11-06 12:22:13 +00005121{
5122 dev->ib_dev.get_port_immutable = mlx5_port_rep_immutable;
5123 dev->ib_dev.query_port = mlx5_ib_rep_query_port;
5124
5125 return 0;
5126}
5127
5128static int mlx5_ib_stage_common_roce_init(struct mlx5_ib_dev *dev,
5129 u8 port_num)
5130{
5131 int i;
5132
5133 for (i = 0; i < dev->num_ports; i++) {
5134 dev->roce[i].dev = dev;
5135 dev->roce[i].native_port_num = i + 1;
5136 dev->roce[i].last_port_state = IB_PORT_DOWN;
5137 }
5138
5139 dev->ib_dev.get_netdev = mlx5_ib_get_netdev;
5140 dev->ib_dev.create_wq = mlx5_ib_create_wq;
5141 dev->ib_dev.modify_wq = mlx5_ib_modify_wq;
5142 dev->ib_dev.destroy_wq = mlx5_ib_destroy_wq;
5143 dev->ib_dev.create_rwq_ind_table = mlx5_ib_create_rwq_ind_table;
5144 dev->ib_dev.destroy_rwq_ind_table = mlx5_ib_destroy_rwq_ind_table;
5145
5146 dev->ib_dev.uverbs_ex_cmd_mask |=
5147 (1ull << IB_USER_VERBS_EX_CMD_CREATE_WQ) |
5148 (1ull << IB_USER_VERBS_EX_CMD_MODIFY_WQ) |
5149 (1ull << IB_USER_VERBS_EX_CMD_DESTROY_WQ) |
5150 (1ull << IB_USER_VERBS_EX_CMD_CREATE_RWQ_IND_TBL) |
5151 (1ull << IB_USER_VERBS_EX_CMD_DESTROY_RWQ_IND_TBL);
5152
5153 return mlx5_add_netdev_notifier(dev, port_num);
5154}
5155
5156static void mlx5_ib_stage_common_roce_cleanup(struct mlx5_ib_dev *dev)
5157{
5158 u8 port_num = mlx5_core_native_port_num(dev->mdev) - 1;
5159
5160 mlx5_remove_netdev_notifier(dev, port_num);
5161}
5162
5163int mlx5_ib_stage_rep_roce_init(struct mlx5_ib_dev *dev)
5164{
5165 struct mlx5_core_dev *mdev = dev->mdev;
5166 enum rdma_link_layer ll;
5167 int port_type_cap;
5168 int err = 0;
5169 u8 port_num;
5170
5171 port_num = mlx5_core_native_port_num(dev->mdev) - 1;
5172 port_type_cap = MLX5_CAP_GEN(mdev, port_type);
5173 ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);
5174
5175 if (ll == IB_LINK_LAYER_ETHERNET)
5176 err = mlx5_ib_stage_common_roce_init(dev, port_num);
5177
5178 return err;
5179}
5180
5181void mlx5_ib_stage_rep_roce_cleanup(struct mlx5_ib_dev *dev)
5182{
5183 mlx5_ib_stage_common_roce_cleanup(dev);
5184}
5185
Mark Bloch16c19752018-01-01 13:06:58 +02005186static int mlx5_ib_stage_roce_init(struct mlx5_ib_dev *dev)
5187{
5188 struct mlx5_core_dev *mdev = dev->mdev;
5189 enum rdma_link_layer ll;
5190 int port_type_cap;
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005191 u8 port_num;
Mark Bloch16c19752018-01-01 13:06:58 +02005192 int err;
5193
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005194 port_num = mlx5_core_native_port_num(dev->mdev) - 1;
Mark Bloch16c19752018-01-01 13:06:58 +02005195 port_type_cap = MLX5_CAP_GEN(mdev, port_type);
5196 ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);
5197
Achiad Shochatfc24fc52015-12-23 18:47:17 +02005198 if (ll == IB_LINK_LAYER_ETHERNET) {
Mark Bloch8e6efa32017-11-06 12:22:13 +00005199 err = mlx5_ib_stage_common_roce_init(dev, port_num);
Achiad Shochatfc24fc52015-12-23 18:47:17 +02005200 if (err)
Mark Bloch16c19752018-01-01 13:06:58 +02005201 return err;
Mark Bloch8e6efa32017-11-06 12:22:13 +00005202
5203 err = mlx5_enable_eth(dev, port_num);
5204 if (err)
5205 goto cleanup;
Achiad Shochatfc24fc52015-12-23 18:47:17 +02005206 }
5207
Mark Bloch16c19752018-01-01 13:06:58 +02005208 return 0;
Mark Bloch8e6efa32017-11-06 12:22:13 +00005209cleanup:
5210 mlx5_ib_stage_common_roce_cleanup(dev);
5211
5212 return err;
Mark Bloch16c19752018-01-01 13:06:58 +02005213}
Eli Cohene126ba92013-07-07 17:25:49 +03005214
Mark Bloch16c19752018-01-01 13:06:58 +02005215static void mlx5_ib_stage_roce_cleanup(struct mlx5_ib_dev *dev)
5216{
5217 struct mlx5_core_dev *mdev = dev->mdev;
5218 enum rdma_link_layer ll;
5219 int port_type_cap;
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005220 u8 port_num;
Eli Cohene126ba92013-07-07 17:25:49 +03005221
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005222 port_num = mlx5_core_native_port_num(dev->mdev) - 1;
Mark Bloch16c19752018-01-01 13:06:58 +02005223 port_type_cap = MLX5_CAP_GEN(mdev, port_type);
5224 ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);
5225
5226 if (ll == IB_LINK_LAYER_ETHERNET) {
5227 mlx5_disable_eth(dev);
Mark Bloch8e6efa32017-11-06 12:22:13 +00005228 mlx5_ib_stage_common_roce_cleanup(dev);
Kamal Heib45bded22017-01-18 14:10:32 +02005229 }
Mark Bloch16c19752018-01-01 13:06:58 +02005230}
Haggai Eran6aec21f2014-12-11 17:04:23 +02005231
Mark Blochb5ca15a2018-01-23 11:16:30 +00005232int mlx5_ib_stage_dev_res_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005233{
5234 return create_dev_resources(&dev->devr);
5235}
Parav Pandit4a2da0b2017-05-30 10:05:15 +03005236
Mark Blochb5ca15a2018-01-23 11:16:30 +00005237void mlx5_ib_stage_dev_res_cleanup(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005238{
5239 destroy_dev_resources(&dev->devr);
5240}
5241
5242static int mlx5_ib_stage_odp_init(struct mlx5_ib_dev *dev)
5243{
Mark Bloch07321b32018-01-01 13:07:00 +02005244 mlx5_ib_internal_fill_odp_caps(dev);
5245
Mark Bloch16c19752018-01-01 13:06:58 +02005246 return mlx5_ib_odp_init_one(dev);
5247}
5248
Mark Blochb5ca15a2018-01-23 11:16:30 +00005249int mlx5_ib_stage_counters_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005250{
Mark Bloch5e1e7612018-01-01 13:07:01 +02005251 if (MLX5_CAP_GEN(dev->mdev, max_qp_cnt)) {
5252 dev->ib_dev.get_hw_stats = mlx5_ib_get_hw_stats;
5253 dev->ib_dev.alloc_hw_stats = mlx5_ib_alloc_hw_stats;
5254
5255 return mlx5_ib_alloc_counters(dev);
5256 }
Mark Bloch16c19752018-01-01 13:06:58 +02005257
5258 return 0;
5259}
5260
Mark Blochb5ca15a2018-01-23 11:16:30 +00005261void mlx5_ib_stage_counters_cleanup(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005262{
5263 if (MLX5_CAP_GEN(dev->mdev, max_qp_cnt))
5264 mlx5_ib_dealloc_counters(dev);
5265}
5266
5267static int mlx5_ib_stage_cong_debugfs_init(struct mlx5_ib_dev *dev)
5268{
Parav Pandita9e546e2018-01-04 17:25:39 +02005269 return mlx5_ib_init_cong_debugfs(dev,
5270 mlx5_core_native_port_num(dev->mdev) - 1);
Mark Bloch16c19752018-01-01 13:06:58 +02005271}
5272
5273static void mlx5_ib_stage_cong_debugfs_cleanup(struct mlx5_ib_dev *dev)
5274{
Parav Pandita9e546e2018-01-04 17:25:39 +02005275 mlx5_ib_cleanup_cong_debugfs(dev,
5276 mlx5_core_native_port_num(dev->mdev) - 1);
Mark Bloch16c19752018-01-01 13:06:58 +02005277}
5278
5279static int mlx5_ib_stage_uar_init(struct mlx5_ib_dev *dev)
5280{
Eli Cohen5fe9dec2017-01-03 23:55:25 +02005281 dev->mdev->priv.uar = mlx5_get_uars_page(dev->mdev);
5282 if (!dev->mdev->priv.uar)
Mark Bloch16c19752018-01-01 13:06:58 +02005283 return -ENOMEM;
5284 return 0;
5285}
5286
5287static void mlx5_ib_stage_uar_cleanup(struct mlx5_ib_dev *dev)
5288{
5289 mlx5_put_uars_page(dev->mdev, dev->mdev->priv.uar);
5290}
5291
Mark Blochb5ca15a2018-01-23 11:16:30 +00005292int mlx5_ib_stage_bfrag_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005293{
5294 int err;
Eli Cohen5fe9dec2017-01-03 23:55:25 +02005295
5296 err = mlx5_alloc_bfreg(dev->mdev, &dev->bfreg, false, false);
5297 if (err)
Mark Bloch16c19752018-01-01 13:06:58 +02005298 return err;
Eli Cohen5fe9dec2017-01-03 23:55:25 +02005299
5300 err = mlx5_alloc_bfreg(dev->mdev, &dev->fp_bfreg, false, true);
5301 if (err)
Mark Bloch16c19752018-01-01 13:06:58 +02005302 mlx5_free_bfreg(dev->mdev, &dev->fp_bfreg);
Eli Cohen5fe9dec2017-01-03 23:55:25 +02005303
Mark Bloch16c19752018-01-01 13:06:58 +02005304 return err;
5305}
Mark Bloch0837e862016-06-17 15:10:55 +03005306
Mark Blochb5ca15a2018-01-23 11:16:30 +00005307void mlx5_ib_stage_bfrag_cleanup(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005308{
5309 mlx5_free_bfreg(dev->mdev, &dev->fp_bfreg);
5310 mlx5_free_bfreg(dev->mdev, &dev->bfreg);
5311}
Eli Cohene126ba92013-07-07 17:25:49 +03005312
Matan Barak8c846602018-03-28 09:27:41 +03005313static int mlx5_ib_stage_populate_specs(struct mlx5_ib_dev *dev)
5314{
5315 return populate_specs_root(dev);
5316}
5317
Mark Blochb5ca15a2018-01-23 11:16:30 +00005318int mlx5_ib_stage_ib_reg_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005319{
5320 return ib_register_device(&dev->ib_dev, NULL);
5321}
5322
Matan Barak8c846602018-03-28 09:27:41 +03005323static void mlx5_ib_stage_depopulate_specs(struct mlx5_ib_dev *dev)
5324{
5325 depopulate_specs_root(dev);
5326}
5327
Doug Ledford2d873442018-03-14 18:49:12 -04005328void mlx5_ib_stage_pre_ib_reg_umr_cleanup(struct mlx5_ib_dev *dev)
Mark Bloch42cea832018-03-14 09:14:15 +02005329{
5330 destroy_umrc_res(dev);
5331}
5332
Mark Blochb5ca15a2018-01-23 11:16:30 +00005333void mlx5_ib_stage_ib_reg_cleanup(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005334{
5335 ib_unregister_device(&dev->ib_dev);
5336}
5337
Doug Ledford2d873442018-03-14 18:49:12 -04005338int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005339{
5340 return create_umr_res(dev);
5341}
5342
Mark Bloch16c19752018-01-01 13:06:58 +02005343static int mlx5_ib_stage_delay_drop_init(struct mlx5_ib_dev *dev)
5344{
Maor Gottlieb03404e82017-05-30 10:29:13 +03005345 init_delay_drop(dev);
5346
Mark Bloch16c19752018-01-01 13:06:58 +02005347 return 0;
5348}
5349
5350static void mlx5_ib_stage_delay_drop_cleanup(struct mlx5_ib_dev *dev)
5351{
5352 cancel_delay_drop(dev);
5353}
5354
Mark Blochb5ca15a2018-01-23 11:16:30 +00005355int mlx5_ib_stage_class_attr_init(struct mlx5_ib_dev *dev)
Mark Bloch16c19752018-01-01 13:06:58 +02005356{
5357 int err;
5358 int i;
5359
Eli Cohene126ba92013-07-07 17:25:49 +03005360 for (i = 0; i < ARRAY_SIZE(mlx5_class_attributes); i++) {
Wei Yongjun281d1a92013-07-30 07:54:26 +08005361 err = device_create_file(&dev->ib_dev.dev,
5362 mlx5_class_attributes[i]);
5363 if (err)
Mark Bloch16c19752018-01-01 13:06:58 +02005364 return err;
Eli Cohene126ba92013-07-07 17:25:49 +03005365 }
5366
Mark Bloch16c19752018-01-01 13:06:58 +02005367 return 0;
5368}
5369
Mark Blochfc385b72018-01-16 14:34:48 +00005370static int mlx5_ib_stage_rep_reg_init(struct mlx5_ib_dev *dev)
5371{
5372 mlx5_ib_register_vport_reps(dev);
5373
5374 return 0;
5375}
5376
5377static void mlx5_ib_stage_rep_reg_cleanup(struct mlx5_ib_dev *dev)
5378{
5379 mlx5_ib_unregister_vport_reps(dev);
5380}
5381
Mark Blochb5ca15a2018-01-23 11:16:30 +00005382void __mlx5_ib_remove(struct mlx5_ib_dev *dev,
5383 const struct mlx5_ib_profile *profile,
5384 int stage)
Mark Bloch16c19752018-01-01 13:06:58 +02005385{
5386 /* Number of stages to cleanup */
5387 while (stage) {
5388 stage--;
5389 if (profile->stage[stage].cleanup)
5390 profile->stage[stage].cleanup(dev);
5391 }
5392
5393 ib_dealloc_device((struct ib_device *)dev);
5394}
5395
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005396static void *mlx5_ib_add_slave_port(struct mlx5_core_dev *mdev, u8 port_num);
5397
Mark Blochb5ca15a2018-01-23 11:16:30 +00005398void *__mlx5_ib_add(struct mlx5_ib_dev *dev,
5399 const struct mlx5_ib_profile *profile)
Mark Bloch16c19752018-01-01 13:06:58 +02005400{
Mark Bloch16c19752018-01-01 13:06:58 +02005401 int err;
5402 int i;
5403
5404 printk_once(KERN_INFO "%s", mlx5_version);
5405
Mark Bloch16c19752018-01-01 13:06:58 +02005406 for (i = 0; i < MLX5_IB_STAGE_MAX; i++) {
5407 if (profile->stage[i].init) {
5408 err = profile->stage[i].init(dev);
5409 if (err)
5410 goto err_out;
5411 }
5412 }
5413
5414 dev->profile = profile;
Eli Cohene126ba92013-07-07 17:25:49 +03005415 dev->ib_active = true;
5416
Jack Morgenstein9603b612014-07-28 23:30:22 +03005417 return dev;
Eli Cohene126ba92013-07-07 17:25:49 +03005418
Mark Bloch16c19752018-01-01 13:06:58 +02005419err_out:
5420 __mlx5_ib_remove(dev, profile, i);
Eli Cohene126ba92013-07-07 17:25:49 +03005421
Jack Morgenstein9603b612014-07-28 23:30:22 +03005422 return NULL;
Eli Cohene126ba92013-07-07 17:25:49 +03005423}
5424
Mark Bloch16c19752018-01-01 13:06:58 +02005425static const struct mlx5_ib_profile pf_profile = {
5426 STAGE_CREATE(MLX5_IB_STAGE_INIT,
5427 mlx5_ib_stage_init_init,
5428 mlx5_ib_stage_init_cleanup),
Mark Bloch9a4ca382018-01-16 14:42:35 +00005429 STAGE_CREATE(MLX5_IB_STAGE_FLOW_DB,
5430 mlx5_ib_stage_flow_db_init,
5431 mlx5_ib_stage_flow_db_cleanup),
Mark Bloch16c19752018-01-01 13:06:58 +02005432 STAGE_CREATE(MLX5_IB_STAGE_CAPS,
5433 mlx5_ib_stage_caps_init,
5434 NULL),
Mark Bloch8e6efa32017-11-06 12:22:13 +00005435 STAGE_CREATE(MLX5_IB_STAGE_NON_DEFAULT_CB,
5436 mlx5_ib_stage_non_default_cb,
5437 NULL),
Mark Bloch16c19752018-01-01 13:06:58 +02005438 STAGE_CREATE(MLX5_IB_STAGE_ROCE,
5439 mlx5_ib_stage_roce_init,
5440 mlx5_ib_stage_roce_cleanup),
5441 STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,
5442 mlx5_ib_stage_dev_res_init,
5443 mlx5_ib_stage_dev_res_cleanup),
5444 STAGE_CREATE(MLX5_IB_STAGE_ODP,
5445 mlx5_ib_stage_odp_init,
Mark Bloch3cc297d2018-01-01 13:07:03 +02005446 NULL),
Mark Bloch16c19752018-01-01 13:06:58 +02005447 STAGE_CREATE(MLX5_IB_STAGE_COUNTERS,
5448 mlx5_ib_stage_counters_init,
5449 mlx5_ib_stage_counters_cleanup),
5450 STAGE_CREATE(MLX5_IB_STAGE_CONG_DEBUGFS,
5451 mlx5_ib_stage_cong_debugfs_init,
5452 mlx5_ib_stage_cong_debugfs_cleanup),
5453 STAGE_CREATE(MLX5_IB_STAGE_UAR,
5454 mlx5_ib_stage_uar_init,
5455 mlx5_ib_stage_uar_cleanup),
5456 STAGE_CREATE(MLX5_IB_STAGE_BFREG,
5457 mlx5_ib_stage_bfrag_init,
5458 mlx5_ib_stage_bfrag_cleanup),
Mark Bloch42cea832018-03-14 09:14:15 +02005459 STAGE_CREATE(MLX5_IB_STAGE_PRE_IB_REG_UMR,
5460 NULL,
5461 mlx5_ib_stage_pre_ib_reg_umr_cleanup),
Matan Barak8c846602018-03-28 09:27:41 +03005462 STAGE_CREATE(MLX5_IB_STAGE_SPECS,
5463 mlx5_ib_stage_populate_specs,
5464 mlx5_ib_stage_depopulate_specs),
Mark Bloch16c19752018-01-01 13:06:58 +02005465 STAGE_CREATE(MLX5_IB_STAGE_IB_REG,
5466 mlx5_ib_stage_ib_reg_init,
5467 mlx5_ib_stage_ib_reg_cleanup),
Mark Bloch42cea832018-03-14 09:14:15 +02005468 STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR,
5469 mlx5_ib_stage_post_ib_reg_umr_init,
5470 NULL),
Mark Bloch16c19752018-01-01 13:06:58 +02005471 STAGE_CREATE(MLX5_IB_STAGE_DELAY_DROP,
5472 mlx5_ib_stage_delay_drop_init,
5473 mlx5_ib_stage_delay_drop_cleanup),
5474 STAGE_CREATE(MLX5_IB_STAGE_CLASS_ATTR,
5475 mlx5_ib_stage_class_attr_init,
5476 NULL),
Mark Bloch16c19752018-01-01 13:06:58 +02005477};
5478
Mark Blochb5ca15a2018-01-23 11:16:30 +00005479static const struct mlx5_ib_profile nic_rep_profile = {
5480 STAGE_CREATE(MLX5_IB_STAGE_INIT,
5481 mlx5_ib_stage_init_init,
5482 mlx5_ib_stage_init_cleanup),
5483 STAGE_CREATE(MLX5_IB_STAGE_FLOW_DB,
5484 mlx5_ib_stage_flow_db_init,
5485 mlx5_ib_stage_flow_db_cleanup),
5486 STAGE_CREATE(MLX5_IB_STAGE_CAPS,
5487 mlx5_ib_stage_caps_init,
5488 NULL),
5489 STAGE_CREATE(MLX5_IB_STAGE_NON_DEFAULT_CB,
5490 mlx5_ib_stage_rep_non_default_cb,
5491 NULL),
5492 STAGE_CREATE(MLX5_IB_STAGE_ROCE,
5493 mlx5_ib_stage_rep_roce_init,
5494 mlx5_ib_stage_rep_roce_cleanup),
5495 STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,
5496 mlx5_ib_stage_dev_res_init,
5497 mlx5_ib_stage_dev_res_cleanup),
5498 STAGE_CREATE(MLX5_IB_STAGE_COUNTERS,
5499 mlx5_ib_stage_counters_init,
5500 mlx5_ib_stage_counters_cleanup),
5501 STAGE_CREATE(MLX5_IB_STAGE_UAR,
5502 mlx5_ib_stage_uar_init,
5503 mlx5_ib_stage_uar_cleanup),
5504 STAGE_CREATE(MLX5_IB_STAGE_BFREG,
5505 mlx5_ib_stage_bfrag_init,
5506 mlx5_ib_stage_bfrag_cleanup),
Doug Ledford2d873442018-03-14 18:49:12 -04005507 STAGE_CREATE(MLX5_IB_STAGE_PRE_IB_REG_UMR,
5508 NULL,
5509 mlx5_ib_stage_pre_ib_reg_umr_cleanup),
Matan Barak8c846602018-03-28 09:27:41 +03005510 STAGE_CREATE(MLX5_IB_STAGE_SPECS,
5511 mlx5_ib_stage_populate_specs,
5512 mlx5_ib_stage_depopulate_specs),
Mark Blochb5ca15a2018-01-23 11:16:30 +00005513 STAGE_CREATE(MLX5_IB_STAGE_IB_REG,
5514 mlx5_ib_stage_ib_reg_init,
5515 mlx5_ib_stage_ib_reg_cleanup),
Doug Ledford2d873442018-03-14 18:49:12 -04005516 STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR,
5517 mlx5_ib_stage_post_ib_reg_umr_init,
5518 NULL),
Mark Blochb5ca15a2018-01-23 11:16:30 +00005519 STAGE_CREATE(MLX5_IB_STAGE_CLASS_ATTR,
5520 mlx5_ib_stage_class_attr_init,
5521 NULL),
5522 STAGE_CREATE(MLX5_IB_STAGE_REP_REG,
5523 mlx5_ib_stage_rep_reg_init,
5524 mlx5_ib_stage_rep_reg_cleanup),
5525};
5526
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005527static void *mlx5_ib_add_slave_port(struct mlx5_core_dev *mdev, u8 port_num)
5528{
5529 struct mlx5_ib_multiport_info *mpi;
5530 struct mlx5_ib_dev *dev;
5531 bool bound = false;
5532 int err;
5533
5534 mpi = kzalloc(sizeof(*mpi), GFP_KERNEL);
5535 if (!mpi)
5536 return NULL;
5537
5538 mpi->mdev = mdev;
5539
5540 err = mlx5_query_nic_vport_system_image_guid(mdev,
5541 &mpi->sys_image_guid);
5542 if (err) {
5543 kfree(mpi);
5544 return NULL;
5545 }
5546
5547 mutex_lock(&mlx5_ib_multiport_mutex);
5548 list_for_each_entry(dev, &mlx5_ib_dev_list, ib_dev_list) {
5549 if (dev->sys_image_guid == mpi->sys_image_guid)
5550 bound = mlx5_ib_bind_slave_port(dev, mpi);
5551
5552 if (bound) {
5553 rdma_roce_rescan_device(&dev->ib_dev);
5554 break;
5555 }
5556 }
5557
5558 if (!bound) {
5559 list_add_tail(&mpi->list, &mlx5_ib_unaffiliated_port_list);
5560 dev_dbg(&mdev->pdev->dev, "no suitable IB device found to bind to, added to unaffiliated list.\n");
5561 } else {
5562 mlx5_ib_dbg(dev, "bound port %u\n", port_num + 1);
5563 }
5564 mutex_unlock(&mlx5_ib_multiport_mutex);
5565
5566 return mpi;
5567}
5568
Mark Bloch16c19752018-01-01 13:06:58 +02005569static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
5570{
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005571 enum rdma_link_layer ll;
Mark Blochb5ca15a2018-01-23 11:16:30 +00005572 struct mlx5_ib_dev *dev;
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005573 int port_type_cap;
5574
Mark Blochb5ca15a2018-01-23 11:16:30 +00005575 printk_once(KERN_INFO "%s", mlx5_version);
5576
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005577 port_type_cap = MLX5_CAP_GEN(mdev, port_type);
5578 ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);
5579
5580 if (mlx5_core_is_mp_slave(mdev) && ll == IB_LINK_LAYER_ETHERNET) {
5581 u8 port_num = mlx5_core_native_port_num(mdev) - 1;
5582
5583 return mlx5_ib_add_slave_port(mdev, port_num);
5584 }
5585
Mark Blochb5ca15a2018-01-23 11:16:30 +00005586 dev = (struct mlx5_ib_dev *)ib_alloc_device(sizeof(*dev));
5587 if (!dev)
5588 return NULL;
5589
5590 dev->mdev = mdev;
5591 dev->num_ports = max(MLX5_CAP_GEN(mdev, num_ports),
5592 MLX5_CAP_GEN(mdev, num_vhca_ports));
5593
5594 if (MLX5_VPORT_MANAGER(mdev) &&
5595 mlx5_ib_eswitch_mode(mdev->priv.eswitch) == SRIOV_OFFLOADS) {
5596 dev->rep = mlx5_ib_vport_rep(mdev->priv.eswitch, 0);
5597
5598 return __mlx5_ib_add(dev, &nic_rep_profile);
5599 }
5600
5601 return __mlx5_ib_add(dev, &pf_profile);
Mark Bloch16c19752018-01-01 13:06:58 +02005602}
5603
Jack Morgenstein9603b612014-07-28 23:30:22 +03005604static void mlx5_ib_remove(struct mlx5_core_dev *mdev, void *context)
Eli Cohene126ba92013-07-07 17:25:49 +03005605{
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005606 struct mlx5_ib_multiport_info *mpi;
5607 struct mlx5_ib_dev *dev;
Haggai Eran6aec21f2014-12-11 17:04:23 +02005608
Daniel Jurgens32f69e42018-01-04 17:25:36 +02005609 if (mlx5_core_is_mp_slave(mdev)) {
5610 mpi = context;
5611 mutex_lock(&mlx5_ib_multiport_mutex);
5612 if (mpi->ibdev)
5613 mlx5_ib_unbind_slave_port(mpi->ibdev, mpi);
5614 list_del(&mpi->list);
5615 mutex_unlock(&mlx5_ib_multiport_mutex);
5616 return;
5617 }
5618
5619 dev = context;
Mark Bloch16c19752018-01-01 13:06:58 +02005620 __mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);
Eli Cohene126ba92013-07-07 17:25:49 +03005621}
5622
Jack Morgenstein9603b612014-07-28 23:30:22 +03005623static struct mlx5_interface mlx5_ib_interface = {
5624 .add = mlx5_ib_add,
5625 .remove = mlx5_ib_remove,
5626 .event = mlx5_ib_event,
Artemy Kovalyovd9aaed82017-01-02 11:37:46 +02005627#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
5628 .pfault = mlx5_ib_pfault,
5629#endif
Saeed Mahameed64613d942015-04-02 17:07:34 +03005630 .protocol = MLX5_INTERFACE_PROTOCOL_IB,
Eli Cohene126ba92013-07-07 17:25:49 +03005631};
5632
Ilya Lesokhinc44ef992018-03-13 15:18:48 +02005633unsigned long mlx5_ib_get_xlt_emergency_page(void)
5634{
5635 mutex_lock(&xlt_emergency_page_mutex);
5636 return xlt_emergency_page;
5637}
5638
5639void mlx5_ib_put_xlt_emergency_page(void)
5640{
5641 mutex_unlock(&xlt_emergency_page_mutex);
5642}
5643
Eli Cohene126ba92013-07-07 17:25:49 +03005644static int __init mlx5_ib_init(void)
5645{
Haggai Eran6aec21f2014-12-11 17:04:23 +02005646 int err;
5647
Ilya Lesokhinc44ef992018-03-13 15:18:48 +02005648 xlt_emergency_page = __get_free_page(GFP_KERNEL);
5649 if (!xlt_emergency_page)
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02005650 return -ENOMEM;
5651
Ilya Lesokhinc44ef992018-03-13 15:18:48 +02005652 mutex_init(&xlt_emergency_page_mutex);
5653
5654 mlx5_ib_event_wq = alloc_ordered_workqueue("mlx5_ib_event_wq", 0);
5655 if (!mlx5_ib_event_wq) {
5656 free_page(xlt_emergency_page);
5657 return -ENOMEM;
5658 }
5659
Artemy Kovalyov81713d32017-01-18 16:58:11 +02005660 mlx5_ib_odp_init();
Jack Morgenstein9603b612014-07-28 23:30:22 +03005661
Haggai Eran6aec21f2014-12-11 17:04:23 +02005662 err = mlx5_register_interface(&mlx5_ib_interface);
Haggai Eran6aec21f2014-12-11 17:04:23 +02005663
5664 return err;
Eli Cohene126ba92013-07-07 17:25:49 +03005665}
5666
5667static void __exit mlx5_ib_cleanup(void)
5668{
Jack Morgenstein9603b612014-07-28 23:30:22 +03005669 mlx5_unregister_interface(&mlx5_ib_interface);
Daniel Jurgensd69a24e2018-01-04 17:25:37 +02005670 destroy_workqueue(mlx5_ib_event_wq);
Ilya Lesokhinc44ef992018-03-13 15:18:48 +02005671 mutex_destroy(&xlt_emergency_page_mutex);
5672 free_page(xlt_emergency_page);
Eli Cohene126ba92013-07-07 17:25:49 +03005673}
5674
5675module_init(mlx5_ib_init);
5676module_exit(mlx5_ib_cleanup);