4961 lines · c
1// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB2/*3 * Copyright (c) 2013-2020, Mellanox Technologies inc. All rights reserved.4 * Copyright (c) 2020, Intel Corporation. All rights reserved.5 */6 7#include <linux/debugfs.h>8#include <linux/highmem.h>9#include <linux/module.h>10#include <linux/init.h>11#include <linux/errno.h>12#include <linux/pci.h>13#include <linux/dma-mapping.h>14#include <linux/slab.h>15#include <linux/bitmap.h>16#include <linux/sched.h>17#include <linux/sched/mm.h>18#include <linux/sched/task.h>19#include <linux/delay.h>20#include <rdma/ib_user_verbs.h>21#include <rdma/ib_addr.h>22#include <rdma/ib_cache.h>23#include <linux/mlx5/port.h>24#include <linux/mlx5/vport.h>25#include <linux/mlx5/fs.h>26#include <linux/mlx5/eswitch.h>27#include <linux/mlx5/driver.h>28#include <linux/list.h>29#include <rdma/ib_smi.h>30#include <rdma/ib_umem_odp.h>31#include <rdma/lag.h>32#include <linux/in.h>33#include <linux/etherdevice.h>34#include "mlx5_ib.h"35#include "ib_rep.h"36#include "cmd.h"37#include "devx.h"38#include "dm.h"39#include "fs.h"40#include "srq.h"41#include "qp.h"42#include "wr.h"43#include "restrack.h"44#include "counters.h"45#include "umr.h"46#include <rdma/uverbs_std_types.h>47#include <rdma/uverbs_ioctl.h>48#include <rdma/mlx5_user_ioctl_verbs.h>49#include <rdma/mlx5_user_ioctl_cmds.h>50#include "macsec.h"51#include "data_direct.h"52 53#define UVERBS_MODULE_NAME mlx5_ib54#include <rdma/uverbs_named_ioctl.h>55 56MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");57MODULE_DESCRIPTION("Mellanox 5th generation network adapters (ConnectX series) IB driver");58MODULE_LICENSE("Dual BSD/GPL");59 60struct mlx5_ib_event_work {61 struct work_struct work;62 union {63 struct mlx5_ib_dev *dev;64 struct mlx5_ib_multiport_info *mpi;65 };66 bool is_slave;67 unsigned int event;68 void *param;69};70 71enum {72 MLX5_ATOMIC_SIZE_QP_8BYTES = 1 << 3,73};74 75static struct workqueue_struct *mlx5_ib_event_wq;76static LIST_HEAD(mlx5_ib_unaffiliated_port_list);77static LIST_HEAD(mlx5_ib_dev_list);78/*79 * This mutex should be held when accessing either of the above lists80 */81static DEFINE_MUTEX(mlx5_ib_multiport_mutex);82 83struct mlx5_ib_dev *mlx5_ib_get_ibdev_from_mpi(struct mlx5_ib_multiport_info *mpi)84{85 struct mlx5_ib_dev *dev;86 87 mutex_lock(&mlx5_ib_multiport_mutex);88 dev = mpi->ibdev;89 mutex_unlock(&mlx5_ib_multiport_mutex);90 return dev;91}92 93static enum rdma_link_layer94mlx5_port_type_cap_to_rdma_ll(int port_type_cap)95{96 switch (port_type_cap) {97 case MLX5_CAP_PORT_TYPE_IB:98 return IB_LINK_LAYER_INFINIBAND;99 case MLX5_CAP_PORT_TYPE_ETH:100 return IB_LINK_LAYER_ETHERNET;101 default:102 return IB_LINK_LAYER_UNSPECIFIED;103 }104}105 106static enum rdma_link_layer107mlx5_ib_port_link_layer(struct ib_device *device, u32 port_num)108{109 struct mlx5_ib_dev *dev = to_mdev(device);110 int port_type_cap = MLX5_CAP_GEN(dev->mdev, port_type);111 112 return mlx5_port_type_cap_to_rdma_ll(port_type_cap);113}114 115static int get_port_state(struct ib_device *ibdev,116 u32 port_num,117 enum ib_port_state *state)118{119 struct ib_port_attr attr;120 int ret;121 122 memset(&attr, 0, sizeof(attr));123 ret = ibdev->ops.query_port(ibdev, port_num, &attr);124 if (!ret)125 *state = attr.state;126 return ret;127}128 129static struct mlx5_roce *mlx5_get_rep_roce(struct mlx5_ib_dev *dev,130 struct net_device *ndev,131 struct net_device *upper,132 u32 *port_num)133{134 struct net_device *rep_ndev;135 struct mlx5_ib_port *port;136 int i;137 138 for (i = 0; i < dev->num_ports; i++) {139 port = &dev->port[i];140 if (!port->rep)141 continue;142 143 if (upper == ndev && port->rep->vport == MLX5_VPORT_UPLINK) {144 *port_num = i + 1;145 return &port->roce;146 }147 148 if (upper && port->rep->vport == MLX5_VPORT_UPLINK)149 continue;150 rep_ndev = ib_device_get_netdev(&dev->ib_dev, i + 1);151 if (rep_ndev && rep_ndev == ndev) {152 dev_put(rep_ndev);153 *port_num = i + 1;154 return &port->roce;155 }156 157 dev_put(rep_ndev);158 }159 160 return NULL;161}162 163static bool mlx5_netdev_send_event(struct mlx5_ib_dev *dev,164 struct net_device *ndev,165 struct net_device *upper,166 struct net_device *ib_ndev)167{168 if (!dev->ib_active)169 return false;170 171 /* Event is about our upper device */172 if (upper == ndev)173 return true;174 175 /* RDMA device is not in lag and not in switchdev */176 if (!dev->is_rep && !upper && ndev == ib_ndev)177 return true;178 179 /* RDMA devie is in switchdev */180 if (dev->is_rep && ndev == ib_ndev)181 return true;182 183 return false;184}185 186static struct net_device *mlx5_ib_get_rep_uplink_netdev(struct mlx5_ib_dev *ibdev)187{188 struct mlx5_ib_port *port;189 int i;190 191 for (i = 0; i < ibdev->num_ports; i++) {192 port = &ibdev->port[i];193 if (port->rep && port->rep->vport == MLX5_VPORT_UPLINK) {194 return ib_device_get_netdev(&ibdev->ib_dev, i + 1);195 }196 }197 198 return NULL;199}200 201static int mlx5_netdev_event(struct notifier_block *this,202 unsigned long event, void *ptr)203{204 struct mlx5_roce *roce = container_of(this, struct mlx5_roce, nb);205 struct net_device *ndev = netdev_notifier_info_to_dev(ptr);206 u32 port_num = roce->native_port_num;207 struct net_device *ib_ndev = NULL;208 struct mlx5_core_dev *mdev;209 struct mlx5_ib_dev *ibdev;210 211 ibdev = roce->dev;212 mdev = mlx5_ib_get_native_port_mdev(ibdev, port_num, NULL);213 if (!mdev)214 return NOTIFY_DONE;215 216 switch (event) {217 case NETDEV_REGISTER:218 /* Should already be registered during the load */219 if (ibdev->is_rep)220 break;221 222 ib_ndev = ib_device_get_netdev(&ibdev->ib_dev, port_num);223 /* Exit if already registered */224 if (ib_ndev)225 goto put_ndev;226 227 if (ndev->dev.parent == mdev->device)228 ib_device_set_netdev(&ibdev->ib_dev, ndev, port_num);229 break;230 231 case NETDEV_UNREGISTER:232 /* In case of reps, ib device goes away before the netdevs */233 if (ibdev->is_rep)234 break;235 ib_ndev = ib_device_get_netdev(&ibdev->ib_dev, port_num);236 if (ib_ndev == ndev)237 ib_device_set_netdev(&ibdev->ib_dev, NULL, port_num);238 goto put_ndev;239 240 case NETDEV_CHANGE:241 case NETDEV_UP:242 case NETDEV_DOWN: {243 struct net_device *upper = NULL;244 245 if (mlx5_lag_is_roce(mdev) || mlx5_lag_is_sriov(mdev)) {246 struct net_device *lag_ndev;247 248 if(mlx5_lag_is_roce(mdev))249 lag_ndev = ib_device_get_netdev(&ibdev->ib_dev, 1);250 else /* sriov lag */251 lag_ndev = mlx5_ib_get_rep_uplink_netdev(ibdev);252 253 if (lag_ndev) {254 upper = netdev_master_upper_dev_get(lag_ndev);255 dev_put(lag_ndev);256 } else {257 goto done;258 }259 }260 261 if (ibdev->is_rep)262 roce = mlx5_get_rep_roce(ibdev, ndev, upper, &port_num);263 if (!roce)264 return NOTIFY_DONE;265 266 ib_ndev = ib_device_get_netdev(&ibdev->ib_dev, port_num);267 268 if (mlx5_netdev_send_event(ibdev, ndev, upper, ib_ndev)) {269 struct ib_event ibev = { };270 enum ib_port_state port_state;271 272 if (get_port_state(&ibdev->ib_dev, port_num,273 &port_state))274 goto put_ndev;275 276 if (roce->last_port_state == port_state)277 goto put_ndev;278 279 roce->last_port_state = port_state;280 ibev.device = &ibdev->ib_dev;281 if (port_state == IB_PORT_DOWN)282 ibev.event = IB_EVENT_PORT_ERR;283 else if (port_state == IB_PORT_ACTIVE)284 ibev.event = IB_EVENT_PORT_ACTIVE;285 else286 goto put_ndev;287 288 ibev.element.port_num = port_num;289 ib_dispatch_event(&ibev);290 }291 break;292 }293 294 default:295 break;296 }297put_ndev:298 dev_put(ib_ndev);299done:300 mlx5_ib_put_native_port_mdev(ibdev, port_num);301 return NOTIFY_DONE;302}303 304struct mlx5_core_dev *mlx5_ib_get_native_port_mdev(struct mlx5_ib_dev *ibdev,305 u32 ib_port_num,306 u32 *native_port_num)307{308 enum rdma_link_layer ll = mlx5_ib_port_link_layer(&ibdev->ib_dev,309 ib_port_num);310 struct mlx5_core_dev *mdev = NULL;311 struct mlx5_ib_multiport_info *mpi;312 struct mlx5_ib_port *port;313 314 if (ibdev->ib_dev.type == RDMA_DEVICE_TYPE_SMI) {315 if (native_port_num)316 *native_port_num = smi_to_native_portnum(ibdev,317 ib_port_num);318 return ibdev->mdev;319 320 }321 322 if (!mlx5_core_mp_enabled(ibdev->mdev) ||323 ll != IB_LINK_LAYER_ETHERNET) {324 if (native_port_num)325 *native_port_num = ib_port_num;326 return ibdev->mdev;327 }328 329 if (native_port_num)330 *native_port_num = 1;331 332 port = &ibdev->port[ib_port_num - 1];333 spin_lock(&port->mp.mpi_lock);334 mpi = ibdev->port[ib_port_num - 1].mp.mpi;335 if (mpi && !mpi->unaffiliate) {336 mdev = mpi->mdev;337 /* If it's the master no need to refcount, it'll exist338 * as long as the ib_dev exists.339 */340 if (!mpi->is_master)341 mpi->mdev_refcnt++;342 }343 spin_unlock(&port->mp.mpi_lock);344 345 return mdev;346}347 348void mlx5_ib_put_native_port_mdev(struct mlx5_ib_dev *ibdev, u32 port_num)349{350 enum rdma_link_layer ll = mlx5_ib_port_link_layer(&ibdev->ib_dev,351 port_num);352 struct mlx5_ib_multiport_info *mpi;353 struct mlx5_ib_port *port;354 355 if (!mlx5_core_mp_enabled(ibdev->mdev) || ll != IB_LINK_LAYER_ETHERNET)356 return;357 358 port = &ibdev->port[port_num - 1];359 360 spin_lock(&port->mp.mpi_lock);361 mpi = ibdev->port[port_num - 1].mp.mpi;362 if (mpi->is_master)363 goto out;364 365 mpi->mdev_refcnt--;366 if (mpi->unaffiliate)367 complete(&mpi->unref_comp);368out:369 spin_unlock(&port->mp.mpi_lock);370}371 372static int translate_eth_legacy_proto_oper(u32 eth_proto_oper,373 u16 *active_speed, u8 *active_width)374{375 switch (eth_proto_oper) {376 case MLX5E_PROT_MASK(MLX5E_1000BASE_CX_SGMII):377 case MLX5E_PROT_MASK(MLX5E_1000BASE_KX):378 case MLX5E_PROT_MASK(MLX5E_100BASE_TX):379 case MLX5E_PROT_MASK(MLX5E_1000BASE_T):380 *active_width = IB_WIDTH_1X;381 *active_speed = IB_SPEED_SDR;382 break;383 case MLX5E_PROT_MASK(MLX5E_10GBASE_T):384 case MLX5E_PROT_MASK(MLX5E_10GBASE_CX4):385 case MLX5E_PROT_MASK(MLX5E_10GBASE_KX4):386 case MLX5E_PROT_MASK(MLX5E_10GBASE_KR):387 case MLX5E_PROT_MASK(MLX5E_10GBASE_CR):388 case MLX5E_PROT_MASK(MLX5E_10GBASE_SR):389 case MLX5E_PROT_MASK(MLX5E_10GBASE_ER):390 *active_width = IB_WIDTH_1X;391 *active_speed = IB_SPEED_QDR;392 break;393 case MLX5E_PROT_MASK(MLX5E_25GBASE_CR):394 case MLX5E_PROT_MASK(MLX5E_25GBASE_KR):395 case MLX5E_PROT_MASK(MLX5E_25GBASE_SR):396 *active_width = IB_WIDTH_1X;397 *active_speed = IB_SPEED_EDR;398 break;399 case MLX5E_PROT_MASK(MLX5E_40GBASE_CR4):400 case MLX5E_PROT_MASK(MLX5E_40GBASE_KR4):401 case MLX5E_PROT_MASK(MLX5E_40GBASE_SR4):402 case MLX5E_PROT_MASK(MLX5E_40GBASE_LR4):403 *active_width = IB_WIDTH_4X;404 *active_speed = IB_SPEED_QDR;405 break;406 case MLX5E_PROT_MASK(MLX5E_50GBASE_CR2):407 case MLX5E_PROT_MASK(MLX5E_50GBASE_KR2):408 case MLX5E_PROT_MASK(MLX5E_50GBASE_SR2):409 *active_width = IB_WIDTH_1X;410 *active_speed = IB_SPEED_HDR;411 break;412 case MLX5E_PROT_MASK(MLX5E_56GBASE_R4):413 *active_width = IB_WIDTH_4X;414 *active_speed = IB_SPEED_FDR;415 break;416 case MLX5E_PROT_MASK(MLX5E_100GBASE_CR4):417 case MLX5E_PROT_MASK(MLX5E_100GBASE_SR4):418 case MLX5E_PROT_MASK(MLX5E_100GBASE_KR4):419 case MLX5E_PROT_MASK(MLX5E_100GBASE_LR4):420 *active_width = IB_WIDTH_4X;421 *active_speed = IB_SPEED_EDR;422 break;423 default:424 return -EINVAL;425 }426 427 return 0;428}429 430static int translate_eth_ext_proto_oper(u32 eth_proto_oper, u16 *active_speed,431 u8 *active_width)432{433 switch (eth_proto_oper) {434 case MLX5E_PROT_MASK(MLX5E_SGMII_100M):435 case MLX5E_PROT_MASK(MLX5E_1000BASE_X_SGMII):436 *active_width = IB_WIDTH_1X;437 *active_speed = IB_SPEED_SDR;438 break;439 case MLX5E_PROT_MASK(MLX5E_5GBASE_R):440 *active_width = IB_WIDTH_1X;441 *active_speed = IB_SPEED_DDR;442 break;443 case MLX5E_PROT_MASK(MLX5E_10GBASE_XFI_XAUI_1):444 *active_width = IB_WIDTH_1X;445 *active_speed = IB_SPEED_QDR;446 break;447 case MLX5E_PROT_MASK(MLX5E_40GBASE_XLAUI_4_XLPPI_4):448 *active_width = IB_WIDTH_4X;449 *active_speed = IB_SPEED_QDR;450 break;451 case MLX5E_PROT_MASK(MLX5E_25GAUI_1_25GBASE_CR_KR):452 *active_width = IB_WIDTH_1X;453 *active_speed = IB_SPEED_EDR;454 break;455 case MLX5E_PROT_MASK(MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2):456 *active_width = IB_WIDTH_2X;457 *active_speed = IB_SPEED_EDR;458 break;459 case MLX5E_PROT_MASK(MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR):460 *active_width = IB_WIDTH_1X;461 *active_speed = IB_SPEED_HDR;462 break;463 case MLX5E_PROT_MASK(MLX5E_CAUI_4_100GBASE_CR4_KR4):464 *active_width = IB_WIDTH_4X;465 *active_speed = IB_SPEED_EDR;466 break;467 case MLX5E_PROT_MASK(MLX5E_100GAUI_2_100GBASE_CR2_KR2):468 *active_width = IB_WIDTH_2X;469 *active_speed = IB_SPEED_HDR;470 break;471 case MLX5E_PROT_MASK(MLX5E_100GAUI_1_100GBASE_CR_KR):472 *active_width = IB_WIDTH_1X;473 *active_speed = IB_SPEED_NDR;474 break;475 case MLX5E_PROT_MASK(MLX5E_200GAUI_4_200GBASE_CR4_KR4):476 *active_width = IB_WIDTH_4X;477 *active_speed = IB_SPEED_HDR;478 break;479 case MLX5E_PROT_MASK(MLX5E_200GAUI_2_200GBASE_CR2_KR2):480 *active_width = IB_WIDTH_2X;481 *active_speed = IB_SPEED_NDR;482 break;483 case MLX5E_PROT_MASK(MLX5E_400GAUI_8_400GBASE_CR8):484 *active_width = IB_WIDTH_8X;485 *active_speed = IB_SPEED_HDR;486 break;487 case MLX5E_PROT_MASK(MLX5E_400GAUI_4_400GBASE_CR4_KR4):488 *active_width = IB_WIDTH_4X;489 *active_speed = IB_SPEED_NDR;490 break;491 case MLX5E_PROT_MASK(MLX5E_800GAUI_8_800GBASE_CR8_KR8):492 *active_width = IB_WIDTH_8X;493 *active_speed = IB_SPEED_NDR;494 break;495 default:496 return -EINVAL;497 }498 499 return 0;500}501 502static int translate_eth_proto_oper(u32 eth_proto_oper, u16 *active_speed,503 u8 *active_width, bool ext)504{505 return ext ?506 translate_eth_ext_proto_oper(eth_proto_oper, active_speed,507 active_width) :508 translate_eth_legacy_proto_oper(eth_proto_oper, active_speed,509 active_width);510}511 512static int mlx5_query_port_roce(struct ib_device *device, u32 port_num,513 struct ib_port_attr *props)514{515 struct mlx5_ib_dev *dev = to_mdev(device);516 u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};517 struct mlx5_core_dev *mdev;518 struct net_device *ndev, *upper;519 enum ib_mtu ndev_ib_mtu;520 bool put_mdev = true;521 u32 eth_prot_oper;522 u32 mdev_port_num;523 bool ext;524 int err;525 526 mdev = mlx5_ib_get_native_port_mdev(dev, port_num, &mdev_port_num);527 if (!mdev) {528 /* This means the port isn't affiliated yet. Get the529 * info for the master port instead.530 */531 put_mdev = false;532 mdev = dev->mdev;533 mdev_port_num = 1;534 port_num = 1;535 }536 537 /* Possible bad flows are checked before filling out props so in case538 * of an error it will still be zeroed out.539 * Use native port in case of reps540 */541 if (dev->is_rep)542 err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN,543 1, 0);544 else545 err = mlx5_query_port_ptys(mdev, out, sizeof(out), MLX5_PTYS_EN,546 mdev_port_num, 0);547 if (err)548 goto out;549 ext = !!MLX5_GET_ETH_PROTO(ptys_reg, out, true, eth_proto_capability);550 eth_prot_oper = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_oper);551 552 props->active_width = IB_WIDTH_4X;553 props->active_speed = IB_SPEED_QDR;554 555 translate_eth_proto_oper(eth_prot_oper, &props->active_speed,556 &props->active_width, ext);557 558 if (!dev->is_rep && dev->mdev->roce.roce_en) {559 u16 qkey_viol_cntr;560 561 props->port_cap_flags |= IB_PORT_CM_SUP;562 props->ip_gids = true;563 props->gid_tbl_len = MLX5_CAP_ROCE(dev->mdev,564 roce_address_table_size);565 mlx5_query_nic_vport_qkey_viol_cntr(mdev, &qkey_viol_cntr);566 props->qkey_viol_cntr = qkey_viol_cntr;567 }568 props->max_mtu = IB_MTU_4096;569 props->max_msg_sz = 1 << MLX5_CAP_GEN(dev->mdev, log_max_msg);570 props->pkey_tbl_len = 1;571 props->state = IB_PORT_DOWN;572 props->phys_state = IB_PORT_PHYS_STATE_DISABLED;573 574 /* If this is a stub query for an unaffiliated port stop here */575 if (!put_mdev)576 goto out;577 578 ndev = ib_device_get_netdev(device, port_num);579 if (!ndev)580 goto out;581 582 if (mlx5_lag_is_roce(mdev) || mlx5_lag_is_sriov(mdev)) {583 rcu_read_lock();584 upper = netdev_master_upper_dev_get_rcu(ndev);585 if (upper) {586 dev_put(ndev);587 ndev = upper;588 dev_hold(ndev);589 }590 rcu_read_unlock();591 }592 593 if (netif_running(ndev) && netif_carrier_ok(ndev)) {594 props->state = IB_PORT_ACTIVE;595 props->phys_state = IB_PORT_PHYS_STATE_LINK_UP;596 }597 598 ndev_ib_mtu = iboe_get_mtu(ndev->mtu);599 600 dev_put(ndev);601 602 props->active_mtu = min(props->max_mtu, ndev_ib_mtu);603out:604 if (put_mdev)605 mlx5_ib_put_native_port_mdev(dev, port_num);606 return err;607}608 609int set_roce_addr(struct mlx5_ib_dev *dev, u32 port_num,610 unsigned int index, const union ib_gid *gid,611 const struct ib_gid_attr *attr)612{613 enum ib_gid_type gid_type;614 u16 vlan_id = 0xffff;615 u8 roce_version = 0;616 u8 roce_l3_type = 0;617 u8 mac[ETH_ALEN];618 int ret;619 620 gid_type = attr->gid_type;621 if (gid) {622 ret = rdma_read_gid_l2_fields(attr, &vlan_id, &mac[0]);623 if (ret)624 return ret;625 }626 627 switch (gid_type) {628 case IB_GID_TYPE_ROCE:629 roce_version = MLX5_ROCE_VERSION_1;630 break;631 case IB_GID_TYPE_ROCE_UDP_ENCAP:632 roce_version = MLX5_ROCE_VERSION_2;633 if (gid && ipv6_addr_v4mapped((void *)gid))634 roce_l3_type = MLX5_ROCE_L3_TYPE_IPV4;635 else636 roce_l3_type = MLX5_ROCE_L3_TYPE_IPV6;637 break;638 639 default:640 mlx5_ib_warn(dev, "Unexpected GID type %u\n", gid_type);641 }642 643 return mlx5_core_roce_gid_set(dev->mdev, index, roce_version,644 roce_l3_type, gid->raw, mac,645 vlan_id < VLAN_CFI_MASK, vlan_id,646 port_num);647}648 649static int mlx5_ib_add_gid(const struct ib_gid_attr *attr,650 __always_unused void **context)651{652 int ret;653 654 ret = mlx5r_add_gid_macsec_operations(attr);655 if (ret)656 return ret;657 658 return set_roce_addr(to_mdev(attr->device), attr->port_num,659 attr->index, &attr->gid, attr);660}661 662static int mlx5_ib_del_gid(const struct ib_gid_attr *attr,663 __always_unused void **context)664{665 int ret;666 667 ret = set_roce_addr(to_mdev(attr->device), attr->port_num,668 attr->index, NULL, attr);669 if (ret)670 return ret;671 672 mlx5r_del_gid_macsec_operations(attr);673 return 0;674}675 676__be16 mlx5_get_roce_udp_sport_min(const struct mlx5_ib_dev *dev,677 const struct ib_gid_attr *attr)678{679 if (attr->gid_type != IB_GID_TYPE_ROCE_UDP_ENCAP)680 return 0;681 682 return cpu_to_be16(MLX5_CAP_ROCE(dev->mdev, r_roce_min_src_udp_port));683}684 685static int mlx5_use_mad_ifc(struct mlx5_ib_dev *dev)686{687 if (MLX5_CAP_GEN(dev->mdev, port_type) == MLX5_CAP_PORT_TYPE_IB)688 return !MLX5_CAP_GEN(dev->mdev, ib_virt);689 return 0;690}691 692enum {693 MLX5_VPORT_ACCESS_METHOD_MAD,694 MLX5_VPORT_ACCESS_METHOD_HCA,695 MLX5_VPORT_ACCESS_METHOD_NIC,696};697 698static int mlx5_get_vport_access_method(struct ib_device *ibdev)699{700 if (mlx5_use_mad_ifc(to_mdev(ibdev)))701 return MLX5_VPORT_ACCESS_METHOD_MAD;702 703 if (mlx5_ib_port_link_layer(ibdev, 1) ==704 IB_LINK_LAYER_ETHERNET)705 return MLX5_VPORT_ACCESS_METHOD_NIC;706 707 return MLX5_VPORT_ACCESS_METHOD_HCA;708}709 710static void get_atomic_caps(struct mlx5_ib_dev *dev,711 u8 atomic_size_qp,712 struct ib_device_attr *props)713{714 u8 tmp;715 u8 atomic_operations = MLX5_CAP_ATOMIC(dev->mdev, atomic_operations);716 u8 atomic_req_8B_endianness_mode =717 MLX5_CAP_ATOMIC(dev->mdev, atomic_req_8B_endianness_mode);718 719 /* Check if HW supports 8 bytes standard atomic operations and capable720 * of host endianness respond721 */722 tmp = MLX5_ATOMIC_OPS_CMP_SWAP | MLX5_ATOMIC_OPS_FETCH_ADD;723 if (((atomic_operations & tmp) == tmp) &&724 (atomic_size_qp & MLX5_ATOMIC_SIZE_QP_8BYTES) &&725 (atomic_req_8B_endianness_mode)) {726 props->atomic_cap = IB_ATOMIC_HCA;727 } else {728 props->atomic_cap = IB_ATOMIC_NONE;729 }730}731 732static void get_atomic_caps_qp(struct mlx5_ib_dev *dev,733 struct ib_device_attr *props)734{735 u8 atomic_size_qp = MLX5_CAP_ATOMIC(dev->mdev, atomic_size_qp);736 737 get_atomic_caps(dev, atomic_size_qp, props);738}739 740static int mlx5_query_system_image_guid(struct ib_device *ibdev,741 __be64 *sys_image_guid)742{743 struct mlx5_ib_dev *dev = to_mdev(ibdev);744 struct mlx5_core_dev *mdev = dev->mdev;745 u64 tmp;746 int err;747 748 switch (mlx5_get_vport_access_method(ibdev)) {749 case MLX5_VPORT_ACCESS_METHOD_MAD:750 return mlx5_query_mad_ifc_system_image_guid(ibdev,751 sys_image_guid);752 753 case MLX5_VPORT_ACCESS_METHOD_HCA:754 err = mlx5_query_hca_vport_system_image_guid(mdev, &tmp);755 break;756 757 case MLX5_VPORT_ACCESS_METHOD_NIC:758 err = mlx5_query_nic_vport_system_image_guid(mdev, &tmp);759 break;760 761 default:762 return -EINVAL;763 }764 765 if (!err)766 *sys_image_guid = cpu_to_be64(tmp);767 768 return err;769 770}771 772static int mlx5_query_max_pkeys(struct ib_device *ibdev,773 u16 *max_pkeys)774{775 struct mlx5_ib_dev *dev = to_mdev(ibdev);776 struct mlx5_core_dev *mdev = dev->mdev;777 778 switch (mlx5_get_vport_access_method(ibdev)) {779 case MLX5_VPORT_ACCESS_METHOD_MAD:780 return mlx5_query_mad_ifc_max_pkeys(ibdev, max_pkeys);781 782 case MLX5_VPORT_ACCESS_METHOD_HCA:783 case MLX5_VPORT_ACCESS_METHOD_NIC:784 *max_pkeys = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(mdev,785 pkey_table_size));786 return 0;787 788 default:789 return -EINVAL;790 }791}792 793static int mlx5_query_vendor_id(struct ib_device *ibdev,794 u32 *vendor_id)795{796 struct mlx5_ib_dev *dev = to_mdev(ibdev);797 798 switch (mlx5_get_vport_access_method(ibdev)) {799 case MLX5_VPORT_ACCESS_METHOD_MAD:800 return mlx5_query_mad_ifc_vendor_id(ibdev, vendor_id);801 802 case MLX5_VPORT_ACCESS_METHOD_HCA:803 case MLX5_VPORT_ACCESS_METHOD_NIC:804 return mlx5_core_query_vendor_id(dev->mdev, vendor_id);805 806 default:807 return -EINVAL;808 }809}810 811static int mlx5_query_node_guid(struct mlx5_ib_dev *dev,812 __be64 *node_guid)813{814 u64 tmp;815 int err;816 817 switch (mlx5_get_vport_access_method(&dev->ib_dev)) {818 case MLX5_VPORT_ACCESS_METHOD_MAD:819 return mlx5_query_mad_ifc_node_guid(dev, node_guid);820 821 case MLX5_VPORT_ACCESS_METHOD_HCA:822 err = mlx5_query_hca_vport_node_guid(dev->mdev, &tmp);823 break;824 825 case MLX5_VPORT_ACCESS_METHOD_NIC:826 err = mlx5_query_nic_vport_node_guid(dev->mdev, &tmp);827 break;828 829 default:830 return -EINVAL;831 }832 833 if (!err)834 *node_guid = cpu_to_be64(tmp);835 836 return err;837}838 839struct mlx5_reg_node_desc {840 u8 desc[IB_DEVICE_NODE_DESC_MAX];841};842 843static int mlx5_query_node_desc(struct mlx5_ib_dev *dev, char *node_desc)844{845 struct mlx5_reg_node_desc in;846 847 if (mlx5_use_mad_ifc(dev))848 return mlx5_query_mad_ifc_node_desc(dev, node_desc);849 850 memset(&in, 0, sizeof(in));851 852 return mlx5_core_access_reg(dev->mdev, &in, sizeof(in), node_desc,853 sizeof(struct mlx5_reg_node_desc),854 MLX5_REG_NODE_DESC, 0, 0);855}856 857static void fill_esw_mgr_reg_c0(struct mlx5_core_dev *mdev,858 struct mlx5_ib_query_device_resp *resp)859{860 struct mlx5_eswitch *esw = mdev->priv.eswitch;861 u16 vport = mlx5_eswitch_manager_vport(mdev);862 863 resp->reg_c0.value = mlx5_eswitch_get_vport_metadata_for_match(esw,864 vport);865 resp->reg_c0.mask = mlx5_eswitch_get_vport_metadata_mask();866}867 868static int mlx5_ib_query_device(struct ib_device *ibdev,869 struct ib_device_attr *props,870 struct ib_udata *uhw)871{872 size_t uhw_outlen = (uhw) ? uhw->outlen : 0;873 struct mlx5_ib_dev *dev = to_mdev(ibdev);874 struct mlx5_core_dev *mdev = dev->mdev;875 int err = -ENOMEM;876 int max_sq_desc;877 int max_rq_sg;878 int max_sq_sg;879 u64 min_page_size = 1ull << MLX5_CAP_GEN(mdev, log_pg_sz);880 bool raw_support = !mlx5_core_mp_enabled(mdev);881 struct mlx5_ib_query_device_resp resp = {};882 size_t resp_len;883 u64 max_tso;884 885 resp_len = sizeof(resp.comp_mask) + sizeof(resp.response_length);886 if (uhw_outlen && uhw_outlen < resp_len)887 return -EINVAL;888 889 resp.response_length = resp_len;890 891 if (uhw && uhw->inlen && !ib_is_udata_cleared(uhw, 0, uhw->inlen))892 return -EINVAL;893 894 memset(props, 0, sizeof(*props));895 err = mlx5_query_system_image_guid(ibdev,896 &props->sys_image_guid);897 if (err)898 return err;899 900 props->max_pkeys = dev->pkey_table_len;901 902 err = mlx5_query_vendor_id(ibdev, &props->vendor_id);903 if (err)904 return err;905 906 props->fw_ver = ((u64)fw_rev_maj(dev->mdev) << 32) |907 (fw_rev_min(dev->mdev) << 16) |908 fw_rev_sub(dev->mdev);909 props->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT |910 IB_DEVICE_PORT_ACTIVE_EVENT |911 IB_DEVICE_SYS_IMAGE_GUID |912 IB_DEVICE_RC_RNR_NAK_GEN;913 914 if (MLX5_CAP_GEN(mdev, pkv))915 props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;916 if (MLX5_CAP_GEN(mdev, qkv))917 props->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR;918 if (MLX5_CAP_GEN(mdev, apm))919 props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG;920 if (MLX5_CAP_GEN(mdev, xrc))921 props->device_cap_flags |= IB_DEVICE_XRC;922 if (MLX5_CAP_GEN(mdev, imaicl)) {923 props->device_cap_flags |= IB_DEVICE_MEM_WINDOW |924 IB_DEVICE_MEM_WINDOW_TYPE_2B;925 props->max_mw = 1 << MLX5_CAP_GEN(mdev, log_max_mkey);926 /* We support 'Gappy' memory registration too */927 props->kernel_cap_flags |= IBK_SG_GAPS_REG;928 }929 /* IB_WR_REG_MR always requires changing the entity size with UMR */930 if (!MLX5_CAP_GEN(dev->mdev, umr_modify_entity_size_disabled))931 props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;932 if (MLX5_CAP_GEN(mdev, sho)) {933 props->kernel_cap_flags |= IBK_INTEGRITY_HANDOVER;934 /* At this stage no support for signature handover */935 props->sig_prot_cap = IB_PROT_T10DIF_TYPE_1 |936 IB_PROT_T10DIF_TYPE_2 |937 IB_PROT_T10DIF_TYPE_3;938 props->sig_guard_cap = IB_GUARD_T10DIF_CRC |939 IB_GUARD_T10DIF_CSUM;940 }941 if (MLX5_CAP_GEN(mdev, block_lb_mc))942 props->kernel_cap_flags |= IBK_BLOCK_MULTICAST_LOOPBACK;943 944 if (MLX5_CAP_GEN(dev->mdev, eth_net_offloads) && raw_support) {945 if (MLX5_CAP_ETH(mdev, csum_cap)) {946 /* Legacy bit to support old userspace libraries */947 props->device_cap_flags |= IB_DEVICE_RAW_IP_CSUM;948 props->raw_packet_caps |= IB_RAW_PACKET_CAP_IP_CSUM;949 }950 951 if (MLX5_CAP_ETH(dev->mdev, vlan_cap))952 props->raw_packet_caps |=953 IB_RAW_PACKET_CAP_CVLAN_STRIPPING;954 955 if (offsetofend(typeof(resp), tso_caps) <= uhw_outlen) {956 max_tso = MLX5_CAP_ETH(mdev, max_lso_cap);957 if (max_tso) {958 resp.tso_caps.max_tso = 1 << max_tso;959 resp.tso_caps.supported_qpts |=960 1 << IB_QPT_RAW_PACKET;961 resp.response_length += sizeof(resp.tso_caps);962 }963 }964 965 if (offsetofend(typeof(resp), rss_caps) <= uhw_outlen) {966 resp.rss_caps.rx_hash_function =967 MLX5_RX_HASH_FUNC_TOEPLITZ;968 resp.rss_caps.rx_hash_fields_mask =969 MLX5_RX_HASH_SRC_IPV4 |970 MLX5_RX_HASH_DST_IPV4 |971 MLX5_RX_HASH_SRC_IPV6 |972 MLX5_RX_HASH_DST_IPV6 |973 MLX5_RX_HASH_SRC_PORT_TCP |974 MLX5_RX_HASH_DST_PORT_TCP |975 MLX5_RX_HASH_SRC_PORT_UDP |976 MLX5_RX_HASH_DST_PORT_UDP |977 MLX5_RX_HASH_INNER;978 resp.response_length += sizeof(resp.rss_caps);979 }980 } else {981 if (offsetofend(typeof(resp), tso_caps) <= uhw_outlen)982 resp.response_length += sizeof(resp.tso_caps);983 if (offsetofend(typeof(resp), rss_caps) <= uhw_outlen)984 resp.response_length += sizeof(resp.rss_caps);985 }986 987 if (MLX5_CAP_GEN(mdev, ipoib_basic_offloads)) {988 props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;989 props->kernel_cap_flags |= IBK_UD_TSO;990 }991 992 if (MLX5_CAP_GEN(dev->mdev, rq_delay_drop) &&993 MLX5_CAP_GEN(dev->mdev, general_notification_event) &&994 raw_support)995 props->raw_packet_caps |= IB_RAW_PACKET_CAP_DELAY_DROP;996 997 if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads) &&998 MLX5_CAP_IPOIB_ENHANCED(mdev, csum_cap))999 props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;1000 1001 if (MLX5_CAP_GEN(dev->mdev, eth_net_offloads) &&1002 MLX5_CAP_ETH(dev->mdev, scatter_fcs) &&1003 raw_support) {1004 /* Legacy bit to support old userspace libraries */1005 props->device_cap_flags |= IB_DEVICE_RAW_SCATTER_FCS;1006 props->raw_packet_caps |= IB_RAW_PACKET_CAP_SCATTER_FCS;1007 }1008 1009 if (MLX5_CAP_DEV_MEM(mdev, memic)) {1010 props->max_dm_size =1011 MLX5_CAP_DEV_MEM(mdev, max_memic_size);1012 }1013 1014 if (mlx5_get_flow_namespace(dev->mdev, MLX5_FLOW_NAMESPACE_BYPASS))1015 props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING;1016 1017 if (MLX5_CAP_GEN(mdev, end_pad))1018 props->device_cap_flags |= IB_DEVICE_PCI_WRITE_END_PADDING;1019 1020 props->vendor_part_id = mdev->pdev->device;1021 props->hw_ver = mdev->pdev->revision;1022 1023 props->max_mr_size = ~0ull;1024 props->page_size_cap = ~(min_page_size - 1);1025 props->max_qp = 1 << MLX5_CAP_GEN(mdev, log_max_qp);1026 props->max_qp_wr = 1 << MLX5_CAP_GEN(mdev, log_max_qp_sz);1027 max_rq_sg = MLX5_CAP_GEN(mdev, max_wqe_sz_rq) /1028 sizeof(struct mlx5_wqe_data_seg);1029 max_sq_desc = min_t(int, MLX5_CAP_GEN(mdev, max_wqe_sz_sq), 512);1030 max_sq_sg = (max_sq_desc - sizeof(struct mlx5_wqe_ctrl_seg) -1031 sizeof(struct mlx5_wqe_raddr_seg)) /1032 sizeof(struct mlx5_wqe_data_seg);1033 props->max_send_sge = max_sq_sg;1034 props->max_recv_sge = max_rq_sg;1035 props->max_sge_rd = MLX5_MAX_SGE_RD;1036 props->max_cq = 1 << MLX5_CAP_GEN(mdev, log_max_cq);1037 props->max_cqe = (1 << MLX5_CAP_GEN(mdev, log_max_cq_sz)) - 1;1038 props->max_mr = 1 << MLX5_CAP_GEN(mdev, log_max_mkey);1039 props->max_pd = 1 << MLX5_CAP_GEN(mdev, log_max_pd);1040 props->max_qp_rd_atom = 1 << MLX5_CAP_GEN(mdev, log_max_ra_req_qp);1041 props->max_qp_init_rd_atom = 1 << MLX5_CAP_GEN(mdev, log_max_ra_res_qp);1042 props->max_srq = 1 << MLX5_CAP_GEN(mdev, log_max_srq);1043 props->max_srq_wr = (1 << MLX5_CAP_GEN(mdev, log_max_srq_sz)) - 1;1044 props->local_ca_ack_delay = MLX5_CAP_GEN(mdev, local_ca_ack_delay);1045 props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp;1046 props->max_srq_sge = max_rq_sg - 1;1047 props->max_fast_reg_page_list_len =1048 1 << MLX5_CAP_GEN(mdev, log_max_klm_list_size);1049 props->max_pi_fast_reg_page_list_len =1050 props->max_fast_reg_page_list_len / 2;1051 props->max_sgl_rd =1052 MLX5_CAP_GEN(mdev, max_sgl_for_optimized_performance);1053 get_atomic_caps_qp(dev, props);1054 props->masked_atomic_cap = IB_ATOMIC_NONE;1055 props->max_mcast_grp = 1 << MLX5_CAP_GEN(mdev, log_max_mcg);1056 props->max_mcast_qp_attach = MLX5_CAP_GEN(mdev, max_qp_mcg);1057 props->max_total_mcast_qp_attach = props->max_mcast_qp_attach *1058 props->max_mcast_grp;1059 props->max_ah = INT_MAX;1060 props->hca_core_clock = MLX5_CAP_GEN(mdev, device_frequency_khz);1061 props->timestamp_mask = 0x7FFFFFFFFFFFFFFFULL;1062 1063 if (IS_ENABLED(CONFIG_INFINIBAND_ON_DEMAND_PAGING)) {1064 if (dev->odp_caps.general_caps & IB_ODP_SUPPORT)1065 props->kernel_cap_flags |= IBK_ON_DEMAND_PAGING;1066 props->odp_caps = dev->odp_caps;1067 if (!uhw) {1068 /* ODP for kernel QPs is not implemented for receive1069 * WQEs and SRQ WQEs1070 */1071 props->odp_caps.per_transport_caps.rc_odp_caps &=1072 ~(IB_ODP_SUPPORT_READ |1073 IB_ODP_SUPPORT_SRQ_RECV);1074 props->odp_caps.per_transport_caps.uc_odp_caps &=1075 ~(IB_ODP_SUPPORT_READ |1076 IB_ODP_SUPPORT_SRQ_RECV);1077 props->odp_caps.per_transport_caps.ud_odp_caps &=1078 ~(IB_ODP_SUPPORT_READ |1079 IB_ODP_SUPPORT_SRQ_RECV);1080 props->odp_caps.per_transport_caps.xrc_odp_caps &=1081 ~(IB_ODP_SUPPORT_READ |1082 IB_ODP_SUPPORT_SRQ_RECV);1083 }1084 }1085 1086 if (mlx5_core_is_vf(mdev))1087 props->kernel_cap_flags |= IBK_VIRTUAL_FUNCTION;1088 1089 if (mlx5_ib_port_link_layer(ibdev, 1) ==1090 IB_LINK_LAYER_ETHERNET && raw_support) {1091 props->rss_caps.max_rwq_indirection_tables =1092 1 << MLX5_CAP_GEN(dev->mdev, log_max_rqt);1093 props->rss_caps.max_rwq_indirection_table_size =1094 1 << MLX5_CAP_GEN(dev->mdev, log_max_rqt_size);1095 props->rss_caps.supported_qpts = 1 << IB_QPT_RAW_PACKET;1096 props->max_wq_type_rq =1097 1 << MLX5_CAP_GEN(dev->mdev, log_max_rq);1098 }1099 1100 if (MLX5_CAP_GEN(mdev, tag_matching)) {1101 props->tm_caps.max_num_tags =1102 (1 << MLX5_CAP_GEN(mdev, log_tag_matching_list_sz)) - 1;1103 props->tm_caps.max_ops =1104 1 << MLX5_CAP_GEN(mdev, log_max_qp_sz);1105 props->tm_caps.max_sge = MLX5_TM_MAX_SGE;1106 }1107 1108 if (MLX5_CAP_GEN(mdev, tag_matching) &&1109 MLX5_CAP_GEN(mdev, rndv_offload_rc)) {1110 props->tm_caps.flags = IB_TM_CAP_RNDV_RC;1111 props->tm_caps.max_rndv_hdr_size = MLX5_TM_MAX_RNDV_MSG_SIZE;1112 }1113 1114 if (MLX5_CAP_GEN(dev->mdev, cq_moderation)) {1115 props->cq_caps.max_cq_moderation_count =1116 MLX5_MAX_CQ_COUNT;1117 props->cq_caps.max_cq_moderation_period =1118 MLX5_MAX_CQ_PERIOD;1119 }1120 1121 if (offsetofend(typeof(resp), cqe_comp_caps) <= uhw_outlen) {1122 resp.response_length += sizeof(resp.cqe_comp_caps);1123 1124 if (MLX5_CAP_GEN(dev->mdev, cqe_compression)) {1125 resp.cqe_comp_caps.max_num =1126 MLX5_CAP_GEN(dev->mdev,1127 cqe_compression_max_num);1128 1129 resp.cqe_comp_caps.supported_format =1130 MLX5_IB_CQE_RES_FORMAT_HASH |1131 MLX5_IB_CQE_RES_FORMAT_CSUM;1132 1133 if (MLX5_CAP_GEN(dev->mdev, mini_cqe_resp_stride_index))1134 resp.cqe_comp_caps.supported_format |=1135 MLX5_IB_CQE_RES_FORMAT_CSUM_STRIDX;1136 }1137 }1138 1139 if (offsetofend(typeof(resp), packet_pacing_caps) <= uhw_outlen &&1140 raw_support) {1141 if (MLX5_CAP_QOS(mdev, packet_pacing) &&1142 MLX5_CAP_GEN(mdev, qos)) {1143 resp.packet_pacing_caps.qp_rate_limit_max =1144 MLX5_CAP_QOS(mdev, packet_pacing_max_rate);1145 resp.packet_pacing_caps.qp_rate_limit_min =1146 MLX5_CAP_QOS(mdev, packet_pacing_min_rate);1147 resp.packet_pacing_caps.supported_qpts |=1148 1 << IB_QPT_RAW_PACKET;1149 if (MLX5_CAP_QOS(mdev, packet_pacing_burst_bound) &&1150 MLX5_CAP_QOS(mdev, packet_pacing_typical_size))1151 resp.packet_pacing_caps.cap_flags |=1152 MLX5_IB_PP_SUPPORT_BURST;1153 }1154 resp.response_length += sizeof(resp.packet_pacing_caps);1155 }1156 1157 if (offsetofend(typeof(resp), mlx5_ib_support_multi_pkt_send_wqes) <=1158 uhw_outlen) {1159 if (MLX5_CAP_ETH(mdev, multi_pkt_send_wqe))1160 resp.mlx5_ib_support_multi_pkt_send_wqes =1161 MLX5_IB_ALLOW_MPW;1162 1163 if (MLX5_CAP_ETH(mdev, enhanced_multi_pkt_send_wqe))1164 resp.mlx5_ib_support_multi_pkt_send_wqes |=1165 MLX5_IB_SUPPORT_EMPW;1166 1167 resp.response_length +=1168 sizeof(resp.mlx5_ib_support_multi_pkt_send_wqes);1169 }1170 1171 if (offsetofend(typeof(resp), flags) <= uhw_outlen) {1172 resp.response_length += sizeof(resp.flags);1173 1174 if (MLX5_CAP_GEN(mdev, cqe_compression_128))1175 resp.flags |=1176 MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_COMP;1177 1178 if (MLX5_CAP_GEN(mdev, cqe_128_always))1179 resp.flags |= MLX5_IB_QUERY_DEV_RESP_FLAGS_CQE_128B_PAD;1180 if (MLX5_CAP_GEN(mdev, qp_packet_based))1181 resp.flags |=1182 MLX5_IB_QUERY_DEV_RESP_PACKET_BASED_CREDIT_MODE;1183 1184 resp.flags |= MLX5_IB_QUERY_DEV_RESP_FLAGS_SCAT2CQE_DCT;1185 }1186 1187 if (offsetofend(typeof(resp), sw_parsing_caps) <= uhw_outlen) {1188 resp.response_length += sizeof(resp.sw_parsing_caps);1189 if (MLX5_CAP_ETH(mdev, swp)) {1190 resp.sw_parsing_caps.sw_parsing_offloads |=1191 MLX5_IB_SW_PARSING;1192 1193 if (MLX5_CAP_ETH(mdev, swp_csum))1194 resp.sw_parsing_caps.sw_parsing_offloads |=1195 MLX5_IB_SW_PARSING_CSUM;1196 1197 if (MLX5_CAP_ETH(mdev, swp_lso))1198 resp.sw_parsing_caps.sw_parsing_offloads |=1199 MLX5_IB_SW_PARSING_LSO;1200 1201 if (resp.sw_parsing_caps.sw_parsing_offloads)1202 resp.sw_parsing_caps.supported_qpts =1203 BIT(IB_QPT_RAW_PACKET);1204 }1205 }1206 1207 if (offsetofend(typeof(resp), striding_rq_caps) <= uhw_outlen &&1208 raw_support) {1209 resp.response_length += sizeof(resp.striding_rq_caps);1210 if (MLX5_CAP_GEN(mdev, striding_rq)) {1211 resp.striding_rq_caps.min_single_stride_log_num_of_bytes =1212 MLX5_MIN_SINGLE_STRIDE_LOG_NUM_BYTES;1213 resp.striding_rq_caps.max_single_stride_log_num_of_bytes =1214 MLX5_MAX_SINGLE_STRIDE_LOG_NUM_BYTES;1215 if (MLX5_CAP_GEN(dev->mdev, ext_stride_num_range))1216 resp.striding_rq_caps1217 .min_single_wqe_log_num_of_strides =1218 MLX5_EXT_MIN_SINGLE_WQE_LOG_NUM_STRIDES;1219 else1220 resp.striding_rq_caps1221 .min_single_wqe_log_num_of_strides =1222 MLX5_MIN_SINGLE_WQE_LOG_NUM_STRIDES;1223 resp.striding_rq_caps.max_single_wqe_log_num_of_strides =1224 MLX5_MAX_SINGLE_WQE_LOG_NUM_STRIDES;1225 resp.striding_rq_caps.supported_qpts =1226 BIT(IB_QPT_RAW_PACKET);1227 }1228 }1229 1230 if (offsetofend(typeof(resp), tunnel_offloads_caps) <= uhw_outlen) {1231 resp.response_length += sizeof(resp.tunnel_offloads_caps);1232 if (MLX5_CAP_ETH(mdev, tunnel_stateless_vxlan))1233 resp.tunnel_offloads_caps |=1234 MLX5_IB_TUNNELED_OFFLOADS_VXLAN;1235 if (MLX5_CAP_ETH(mdev, tunnel_stateless_geneve_rx))1236 resp.tunnel_offloads_caps |=1237 MLX5_IB_TUNNELED_OFFLOADS_GENEVE;1238 if (MLX5_CAP_ETH(mdev, tunnel_stateless_gre))1239 resp.tunnel_offloads_caps |=1240 MLX5_IB_TUNNELED_OFFLOADS_GRE;1241 if (MLX5_CAP_ETH(mdev, tunnel_stateless_mpls_over_gre))1242 resp.tunnel_offloads_caps |=1243 MLX5_IB_TUNNELED_OFFLOADS_MPLS_GRE;1244 if (MLX5_CAP_ETH(mdev, tunnel_stateless_mpls_over_udp))1245 resp.tunnel_offloads_caps |=1246 MLX5_IB_TUNNELED_OFFLOADS_MPLS_UDP;1247 }1248 1249 if (offsetofend(typeof(resp), dci_streams_caps) <= uhw_outlen) {1250 resp.response_length += sizeof(resp.dci_streams_caps);1251 1252 resp.dci_streams_caps.max_log_num_concurent =1253 MLX5_CAP_GEN(mdev, log_max_dci_stream_channels);1254 1255 resp.dci_streams_caps.max_log_num_errored =1256 MLX5_CAP_GEN(mdev, log_max_dci_errored_streams);1257 }1258 1259 if (offsetofend(typeof(resp), reserved) <= uhw_outlen)1260 resp.response_length += sizeof(resp.reserved);1261 1262 if (offsetofend(typeof(resp), reg_c0) <= uhw_outlen) {1263 struct mlx5_eswitch *esw = mdev->priv.eswitch;1264 1265 resp.response_length += sizeof(resp.reg_c0);1266 1267 if (mlx5_eswitch_mode(mdev) == MLX5_ESWITCH_OFFLOADS &&1268 mlx5_eswitch_vport_match_metadata_enabled(esw))1269 fill_esw_mgr_reg_c0(mdev, &resp);1270 }1271 1272 if (uhw_outlen) {1273 err = ib_copy_to_udata(uhw, &resp, resp.response_length);1274 1275 if (err)1276 return err;1277 }1278 1279 return 0;1280}1281 1282static void translate_active_width(struct ib_device *ibdev, u16 active_width,1283 u8 *ib_width)1284{1285 struct mlx5_ib_dev *dev = to_mdev(ibdev);1286 1287 if (active_width & MLX5_PTYS_WIDTH_1X)1288 *ib_width = IB_WIDTH_1X;1289 else if (active_width & MLX5_PTYS_WIDTH_2X)1290 *ib_width = IB_WIDTH_2X;1291 else if (active_width & MLX5_PTYS_WIDTH_4X)1292 *ib_width = IB_WIDTH_4X;1293 else if (active_width & MLX5_PTYS_WIDTH_8X)1294 *ib_width = IB_WIDTH_8X;1295 else if (active_width & MLX5_PTYS_WIDTH_12X)1296 *ib_width = IB_WIDTH_12X;1297 else {1298 mlx5_ib_dbg(dev, "Invalid active_width %d, setting width to default value: 4x\n",1299 active_width);1300 *ib_width = IB_WIDTH_4X;1301 }1302 1303 return;1304}1305 1306static int mlx5_mtu_to_ib_mtu(int mtu)1307{1308 switch (mtu) {1309 case 256: return 1;1310 case 512: return 2;1311 case 1024: return 3;1312 case 2048: return 4;1313 case 4096: return 5;1314 default:1315 pr_warn("invalid mtu\n");1316 return -1;1317 }1318}1319 1320enum ib_max_vl_num {1321 __IB_MAX_VL_0 = 1,1322 __IB_MAX_VL_0_1 = 2,1323 __IB_MAX_VL_0_3 = 3,1324 __IB_MAX_VL_0_7 = 4,1325 __IB_MAX_VL_0_14 = 5,1326};1327 1328enum mlx5_vl_hw_cap {1329 MLX5_VL_HW_0 = 1,1330 MLX5_VL_HW_0_1 = 2,1331 MLX5_VL_HW_0_2 = 3,1332 MLX5_VL_HW_0_3 = 4,1333 MLX5_VL_HW_0_4 = 5,1334 MLX5_VL_HW_0_5 = 6,1335 MLX5_VL_HW_0_6 = 7,1336 MLX5_VL_HW_0_7 = 8,1337 MLX5_VL_HW_0_14 = 151338};1339 1340static int translate_max_vl_num(struct ib_device *ibdev, u8 vl_hw_cap,1341 u8 *max_vl_num)1342{1343 switch (vl_hw_cap) {1344 case MLX5_VL_HW_0:1345 *max_vl_num = __IB_MAX_VL_0;1346 break;1347 case MLX5_VL_HW_0_1:1348 *max_vl_num = __IB_MAX_VL_0_1;1349 break;1350 case MLX5_VL_HW_0_3:1351 *max_vl_num = __IB_MAX_VL_0_3;1352 break;1353 case MLX5_VL_HW_0_7:1354 *max_vl_num = __IB_MAX_VL_0_7;1355 break;1356 case MLX5_VL_HW_0_14:1357 *max_vl_num = __IB_MAX_VL_0_14;1358 break;1359 1360 default:1361 return -EINVAL;1362 }1363 1364 return 0;1365}1366 1367static int mlx5_query_hca_port(struct ib_device *ibdev, u32 port,1368 struct ib_port_attr *props)1369{1370 struct mlx5_ib_dev *dev = to_mdev(ibdev);1371 struct mlx5_core_dev *mdev = dev->mdev;1372 struct mlx5_hca_vport_context *rep;1373 u8 vl_hw_cap, plane_index = 0;1374 u16 max_mtu;1375 u16 oper_mtu;1376 int err;1377 u16 ib_link_width_oper;1378 1379 rep = kzalloc(sizeof(*rep), GFP_KERNEL);1380 if (!rep) {1381 err = -ENOMEM;1382 goto out;1383 }1384 1385 /* props being zeroed by the caller, avoid zeroing it here */1386 1387 if (ibdev->type == RDMA_DEVICE_TYPE_SMI) {1388 plane_index = port;1389 port = smi_to_native_portnum(dev, port);1390 }1391 1392 err = mlx5_query_hca_vport_context(mdev, 0, port, 0, rep);1393 if (err)1394 goto out;1395 1396 props->lid = rep->lid;1397 props->lmc = rep->lmc;1398 props->sm_lid = rep->sm_lid;1399 props->sm_sl = rep->sm_sl;1400 props->state = rep->vport_state;1401 props->phys_state = rep->port_physical_state;1402 1403 props->port_cap_flags = rep->cap_mask1;1404 if (dev->num_plane) {1405 props->port_cap_flags |= IB_PORT_SM_DISABLED;1406 props->port_cap_flags &= ~IB_PORT_SM;1407 } else if (ibdev->type == RDMA_DEVICE_TYPE_SMI)1408 props->port_cap_flags &= ~IB_PORT_CM_SUP;1409 1410 props->gid_tbl_len = mlx5_get_gid_table_len(MLX5_CAP_GEN(mdev, gid_table_size));1411 props->max_msg_sz = 1 << MLX5_CAP_GEN(mdev, log_max_msg);1412 props->pkey_tbl_len = mlx5_to_sw_pkey_sz(MLX5_CAP_GEN(mdev, pkey_table_size));1413 props->bad_pkey_cntr = rep->pkey_violation_counter;1414 props->qkey_viol_cntr = rep->qkey_violation_counter;1415 props->subnet_timeout = rep->subnet_timeout;1416 props->init_type_reply = rep->init_type_reply;1417 1418 if (props->port_cap_flags & IB_PORT_CAP_MASK2_SUP)1419 props->port_cap_flags2 = rep->cap_mask2;1420 1421 err = mlx5_query_ib_port_oper(mdev, &ib_link_width_oper,1422 &props->active_speed, port, plane_index);1423 if (err)1424 goto out;1425 1426 translate_active_width(ibdev, ib_link_width_oper, &props->active_width);1427 1428 mlx5_query_port_max_mtu(mdev, &max_mtu, port);1429 1430 props->max_mtu = mlx5_mtu_to_ib_mtu(max_mtu);1431 1432 mlx5_query_port_oper_mtu(mdev, &oper_mtu, port);1433 1434 props->active_mtu = mlx5_mtu_to_ib_mtu(oper_mtu);1435 1436 err = mlx5_query_port_vl_hw_cap(mdev, &vl_hw_cap, port);1437 if (err)1438 goto out;1439 1440 err = translate_max_vl_num(ibdev, vl_hw_cap,1441 &props->max_vl_num);1442out:1443 kfree(rep);1444 return err;1445}1446 1447int mlx5_ib_query_port(struct ib_device *ibdev, u32 port,1448 struct ib_port_attr *props)1449{1450 unsigned int count;1451 int ret;1452 1453 switch (mlx5_get_vport_access_method(ibdev)) {1454 case MLX5_VPORT_ACCESS_METHOD_MAD:1455 ret = mlx5_query_mad_ifc_port(ibdev, port, props);1456 break;1457 1458 case MLX5_VPORT_ACCESS_METHOD_HCA:1459 ret = mlx5_query_hca_port(ibdev, port, props);1460 break;1461 1462 case MLX5_VPORT_ACCESS_METHOD_NIC:1463 ret = mlx5_query_port_roce(ibdev, port, props);1464 break;1465 1466 default:1467 ret = -EINVAL;1468 }1469 1470 if (!ret && props) {1471 struct mlx5_ib_dev *dev = to_mdev(ibdev);1472 struct mlx5_core_dev *mdev;1473 bool put_mdev = true;1474 1475 mdev = mlx5_ib_get_native_port_mdev(dev, port, NULL);1476 if (!mdev) {1477 /* If the port isn't affiliated yet query the master.1478 * The master and slave will have the same values.1479 */1480 mdev = dev->mdev;1481 port = 1;1482 put_mdev = false;1483 }1484 count = mlx5_core_reserved_gids_count(mdev);1485 if (put_mdev)1486 mlx5_ib_put_native_port_mdev(dev, port);1487 props->gid_tbl_len -= count;1488 }1489 return ret;1490}1491 1492static int mlx5_ib_rep_query_port(struct ib_device *ibdev, u32 port,1493 struct ib_port_attr *props)1494{1495 return mlx5_query_port_roce(ibdev, port, props);1496}1497 1498static int mlx5_ib_rep_query_pkey(struct ib_device *ibdev, u32 port, u16 index,1499 u16 *pkey)1500{1501 /* Default special Pkey for representor device port as per the1502 * IB specification 1.3 section 10.9.1.2.1503 */1504 *pkey = 0xffff;1505 return 0;1506}1507 1508static int mlx5_ib_query_gid(struct ib_device *ibdev, u32 port, int index,1509 union ib_gid *gid)1510{1511 struct mlx5_ib_dev *dev = to_mdev(ibdev);1512 struct mlx5_core_dev *mdev = dev->mdev;1513 1514 switch (mlx5_get_vport_access_method(ibdev)) {1515 case MLX5_VPORT_ACCESS_METHOD_MAD:1516 return mlx5_query_mad_ifc_gids(ibdev, port, index, gid);1517 1518 case MLX5_VPORT_ACCESS_METHOD_HCA:1519 return mlx5_query_hca_vport_gid(mdev, 0, port, 0, index, gid);1520 1521 default:1522 return -EINVAL;1523 }1524 1525}1526 1527static int mlx5_query_hca_nic_pkey(struct ib_device *ibdev, u32 port,1528 u16 index, u16 *pkey)1529{1530 struct mlx5_ib_dev *dev = to_mdev(ibdev);1531 struct mlx5_core_dev *mdev;1532 bool put_mdev = true;1533 u32 mdev_port_num;1534 int err;1535 1536 mdev = mlx5_ib_get_native_port_mdev(dev, port, &mdev_port_num);1537 if (!mdev) {1538 /* The port isn't affiliated yet, get the PKey from the master1539 * port. For RoCE the PKey tables will be the same.1540 */1541 put_mdev = false;1542 mdev = dev->mdev;1543 mdev_port_num = 1;1544 }1545 1546 err = mlx5_query_hca_vport_pkey(mdev, 0, mdev_port_num, 0,1547 index, pkey);1548 if (put_mdev)1549 mlx5_ib_put_native_port_mdev(dev, port);1550 1551 return err;1552}1553 1554static int mlx5_ib_query_pkey(struct ib_device *ibdev, u32 port, u16 index,1555 u16 *pkey)1556{1557 switch (mlx5_get_vport_access_method(ibdev)) {1558 case MLX5_VPORT_ACCESS_METHOD_MAD:1559 return mlx5_query_mad_ifc_pkey(ibdev, port, index, pkey);1560 1561 case MLX5_VPORT_ACCESS_METHOD_HCA:1562 case MLX5_VPORT_ACCESS_METHOD_NIC:1563 return mlx5_query_hca_nic_pkey(ibdev, port, index, pkey);1564 default:1565 return -EINVAL;1566 }1567}1568 1569static int mlx5_ib_modify_device(struct ib_device *ibdev, int mask,1570 struct ib_device_modify *props)1571{1572 struct mlx5_ib_dev *dev = to_mdev(ibdev);1573 struct mlx5_reg_node_desc in;1574 struct mlx5_reg_node_desc out;1575 int err;1576 1577 if (mask & ~IB_DEVICE_MODIFY_NODE_DESC)1578 return -EOPNOTSUPP;1579 1580 if (!(mask & IB_DEVICE_MODIFY_NODE_DESC))1581 return 0;1582 1583 /*1584 * If possible, pass node desc to FW, so it can generate1585 * a 144 trap. If cmd fails, just ignore.1586 */1587 memcpy(&in, props->node_desc, IB_DEVICE_NODE_DESC_MAX);1588 err = mlx5_core_access_reg(dev->mdev, &in, sizeof(in), &out,1589 sizeof(out), MLX5_REG_NODE_DESC, 0, 1);1590 if (err)1591 return err;1592 1593 memcpy(ibdev->node_desc, props->node_desc, IB_DEVICE_NODE_DESC_MAX);1594 1595 return err;1596}1597 1598static int set_port_caps_atomic(struct mlx5_ib_dev *dev, u32 port_num, u32 mask,1599 u32 value)1600{1601 struct mlx5_hca_vport_context ctx = {};1602 struct mlx5_core_dev *mdev;1603 u32 mdev_port_num;1604 int err;1605 1606 mdev = mlx5_ib_get_native_port_mdev(dev, port_num, &mdev_port_num);1607 if (!mdev)1608 return -ENODEV;1609 1610 err = mlx5_query_hca_vport_context(mdev, 0, mdev_port_num, 0, &ctx);1611 if (err)1612 goto out;1613 1614 if (~ctx.cap_mask1_perm & mask) {1615 mlx5_ib_warn(dev, "trying to change bitmask 0x%X but change supported 0x%X\n",1616 mask, ctx.cap_mask1_perm);1617 err = -EINVAL;1618 goto out;1619 }1620 1621 ctx.cap_mask1 = value;1622 ctx.cap_mask1_perm = mask;1623 err = mlx5_core_modify_hca_vport_context(mdev, 0, mdev_port_num,1624 0, &ctx);1625 1626out:1627 mlx5_ib_put_native_port_mdev(dev, port_num);1628 1629 return err;1630}1631 1632static int mlx5_ib_modify_port(struct ib_device *ibdev, u32 port, int mask,1633 struct ib_port_modify *props)1634{1635 struct mlx5_ib_dev *dev = to_mdev(ibdev);1636 struct ib_port_attr attr;1637 u32 tmp;1638 int err;1639 u32 change_mask;1640 u32 value;1641 bool is_ib = (mlx5_ib_port_link_layer(ibdev, port) ==1642 IB_LINK_LAYER_INFINIBAND);1643 1644 /* CM layer calls ib_modify_port() regardless of the link layer. For1645 * Ethernet ports, qkey violation and Port capabilities are meaningless.1646 */1647 if (!is_ib)1648 return 0;1649 1650 if (MLX5_CAP_GEN(dev->mdev, ib_virt) && is_ib) {1651 change_mask = props->clr_port_cap_mask | props->set_port_cap_mask;1652 value = ~props->clr_port_cap_mask | props->set_port_cap_mask;1653 return set_port_caps_atomic(dev, port, change_mask, value);1654 }1655 1656 mutex_lock(&dev->cap_mask_mutex);1657 1658 err = ib_query_port(ibdev, port, &attr);1659 if (err)1660 goto out;1661 1662 tmp = (attr.port_cap_flags | props->set_port_cap_mask) &1663 ~props->clr_port_cap_mask;1664 1665 err = mlx5_set_port_caps(dev->mdev, port, tmp);1666 1667out:1668 mutex_unlock(&dev->cap_mask_mutex);1669 return err;1670}1671 1672static void print_lib_caps(struct mlx5_ib_dev *dev, u64 caps)1673{1674 mlx5_ib_dbg(dev, "MLX5_LIB_CAP_4K_UAR = %s\n",1675 caps & MLX5_LIB_CAP_4K_UAR ? "y" : "n");1676}1677 1678static u16 calc_dynamic_bfregs(int uars_per_sys_page)1679{1680 /* Large page with non 4k uar support might limit the dynamic size */1681 if (uars_per_sys_page == 1 && PAGE_SIZE > 4096)1682 return MLX5_MIN_DYN_BFREGS;1683 1684 return MLX5_MAX_DYN_BFREGS;1685}1686 1687static int calc_total_bfregs(struct mlx5_ib_dev *dev, bool lib_uar_4k,1688 struct mlx5_ib_alloc_ucontext_req_v2 *req,1689 struct mlx5_bfreg_info *bfregi)1690{1691 int uars_per_sys_page;1692 int bfregs_per_sys_page;1693 int ref_bfregs = req->total_num_bfregs;1694 1695 if (req->total_num_bfregs == 0)1696 return -EINVAL;1697 1698 BUILD_BUG_ON(MLX5_MAX_BFREGS % MLX5_NON_FP_BFREGS_IN_PAGE);1699 BUILD_BUG_ON(MLX5_MAX_BFREGS < MLX5_NON_FP_BFREGS_IN_PAGE);1700 1701 if (req->total_num_bfregs > MLX5_MAX_BFREGS)1702 return -ENOMEM;1703 1704 uars_per_sys_page = get_uars_per_sys_page(dev, lib_uar_4k);1705 bfregs_per_sys_page = uars_per_sys_page * MLX5_NON_FP_BFREGS_PER_UAR;1706 /* This holds the required static allocation asked by the user */1707 req->total_num_bfregs = ALIGN(req->total_num_bfregs, bfregs_per_sys_page);1708 if (req->num_low_latency_bfregs > req->total_num_bfregs - 1)1709 return -EINVAL;1710 1711 bfregi->num_static_sys_pages = req->total_num_bfregs / bfregs_per_sys_page;1712 bfregi->num_dyn_bfregs = ALIGN(calc_dynamic_bfregs(uars_per_sys_page), bfregs_per_sys_page);1713 bfregi->total_num_bfregs = req->total_num_bfregs + bfregi->num_dyn_bfregs;1714 bfregi->num_sys_pages = bfregi->total_num_bfregs / bfregs_per_sys_page;1715 1716 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",1717 MLX5_CAP_GEN(dev->mdev, uar_4k) ? "yes" : "no",1718 lib_uar_4k ? "yes" : "no", ref_bfregs,1719 req->total_num_bfregs, bfregi->total_num_bfregs,1720 bfregi->num_sys_pages);1721 1722 return 0;1723}1724 1725static int allocate_uars(struct mlx5_ib_dev *dev, struct mlx5_ib_ucontext *context)1726{1727 struct mlx5_bfreg_info *bfregi;1728 int err;1729 int i;1730 1731 bfregi = &context->bfregi;1732 for (i = 0; i < bfregi->num_static_sys_pages; i++) {1733 err = mlx5_cmd_uar_alloc(dev->mdev, &bfregi->sys_pages[i],1734 context->devx_uid);1735 if (err)1736 goto error;1737 1738 mlx5_ib_dbg(dev, "allocated uar %d\n", bfregi->sys_pages[i]);1739 }1740 1741 for (i = bfregi->num_static_sys_pages; i < bfregi->num_sys_pages; i++)1742 bfregi->sys_pages[i] = MLX5_IB_INVALID_UAR_INDEX;1743 1744 return 0;1745 1746error:1747 for (--i; i >= 0; i--)1748 if (mlx5_cmd_uar_dealloc(dev->mdev, bfregi->sys_pages[i],1749 context->devx_uid))1750 mlx5_ib_warn(dev, "failed to free uar %d\n", i);1751 1752 return err;1753}1754 1755static void deallocate_uars(struct mlx5_ib_dev *dev,1756 struct mlx5_ib_ucontext *context)1757{1758 struct mlx5_bfreg_info *bfregi;1759 int i;1760 1761 bfregi = &context->bfregi;1762 for (i = 0; i < bfregi->num_sys_pages; i++)1763 if (i < bfregi->num_static_sys_pages ||1764 bfregi->sys_pages[i] != MLX5_IB_INVALID_UAR_INDEX)1765 mlx5_cmd_uar_dealloc(dev->mdev, bfregi->sys_pages[i],1766 context->devx_uid);1767}1768 1769int mlx5_ib_enable_lb(struct mlx5_ib_dev *dev, bool td, bool qp)1770{1771 int err = 0;1772 1773 mutex_lock(&dev->lb.mutex);1774 if (td)1775 dev->lb.user_td++;1776 if (qp)1777 dev->lb.qps++;1778 1779 if (dev->lb.user_td == 2 ||1780 dev->lb.qps == 1) {1781 if (!dev->lb.enabled) {1782 err = mlx5_nic_vport_update_local_lb(dev->mdev, true);1783 dev->lb.enabled = true;1784 }1785 }1786 1787 mutex_unlock(&dev->lb.mutex);1788 1789 return err;1790}1791 1792void mlx5_ib_disable_lb(struct mlx5_ib_dev *dev, bool td, bool qp)1793{1794 mutex_lock(&dev->lb.mutex);1795 if (td)1796 dev->lb.user_td--;1797 if (qp)1798 dev->lb.qps--;1799 1800 if (dev->lb.user_td == 1 &&1801 dev->lb.qps == 0) {1802 if (dev->lb.enabled) {1803 mlx5_nic_vport_update_local_lb(dev->mdev, false);1804 dev->lb.enabled = false;1805 }1806 }1807 1808 mutex_unlock(&dev->lb.mutex);1809}1810 1811static int mlx5_ib_alloc_transport_domain(struct mlx5_ib_dev *dev, u32 *tdn,1812 u16 uid)1813{1814 int err;1815 1816 if (!MLX5_CAP_GEN(dev->mdev, log_max_transport_domain))1817 return 0;1818 1819 err = mlx5_cmd_alloc_transport_domain(dev->mdev, tdn, uid);1820 if (err)1821 return err;1822 1823 if ((MLX5_CAP_GEN(dev->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) ||1824 (!MLX5_CAP_GEN(dev->mdev, disable_local_lb_uc) &&1825 !MLX5_CAP_GEN(dev->mdev, disable_local_lb_mc)))1826 return err;1827 1828 return mlx5_ib_enable_lb(dev, true, false);1829}1830 1831static void mlx5_ib_dealloc_transport_domain(struct mlx5_ib_dev *dev, u32 tdn,1832 u16 uid)1833{1834 if (!MLX5_CAP_GEN(dev->mdev, log_max_transport_domain))1835 return;1836 1837 mlx5_cmd_dealloc_transport_domain(dev->mdev, tdn, uid);1838 1839 if ((MLX5_CAP_GEN(dev->mdev, port_type) != MLX5_CAP_PORT_TYPE_ETH) ||1840 (!MLX5_CAP_GEN(dev->mdev, disable_local_lb_uc) &&1841 !MLX5_CAP_GEN(dev->mdev, disable_local_lb_mc)))1842 return;1843 1844 mlx5_ib_disable_lb(dev, true, false);1845}1846 1847static int set_ucontext_resp(struct ib_ucontext *uctx,1848 struct mlx5_ib_alloc_ucontext_resp *resp)1849{1850 struct ib_device *ibdev = uctx->device;1851 struct mlx5_ib_dev *dev = to_mdev(ibdev);1852 struct mlx5_ib_ucontext *context = to_mucontext(uctx);1853 struct mlx5_bfreg_info *bfregi = &context->bfregi;1854 1855 if (MLX5_CAP_GEN(dev->mdev, dump_fill_mkey)) {1856 resp->dump_fill_mkey = dev->mkeys.dump_fill_mkey;1857 resp->comp_mask |=1858 MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_DUMP_FILL_MKEY;1859 }1860 1861 resp->qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp);1862 if (mlx5_wc_support_get(dev->mdev))1863 resp->bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev,1864 log_bf_reg_size);1865 resp->cache_line_size = cache_line_size();1866 resp->max_sq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq);1867 resp->max_rq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq);1868 resp->max_send_wqebb = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz);1869 resp->max_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp_sz);1870 resp->max_srq_recv_wr = 1 << MLX5_CAP_GEN(dev->mdev, log_max_srq_sz);1871 resp->cqe_version = context->cqe_version;1872 resp->log_uar_size = MLX5_CAP_GEN(dev->mdev, uar_4k) ?1873 MLX5_ADAPTER_PAGE_SHIFT : PAGE_SHIFT;1874 resp->num_uars_per_page = MLX5_CAP_GEN(dev->mdev, uar_4k) ?1875 MLX5_CAP_GEN(dev->mdev,1876 num_of_uars_per_page) : 1;1877 resp->tot_bfregs = bfregi->lib_uar_dyn ? 0 :1878 bfregi->total_num_bfregs - bfregi->num_dyn_bfregs;1879 resp->num_ports = dev->num_ports;1880 resp->cmds_supp_uhw |= MLX5_USER_CMDS_SUPP_UHW_QUERY_DEVICE |1881 MLX5_USER_CMDS_SUPP_UHW_CREATE_AH;1882 1883 if (mlx5_ib_port_link_layer(ibdev, 1) == IB_LINK_LAYER_ETHERNET) {1884 mlx5_query_min_inline(dev->mdev, &resp->eth_min_inline);1885 resp->eth_min_inline++;1886 }1887 1888 if (dev->mdev->clock_info)1889 resp->clock_info_versions = BIT(MLX5_IB_CLOCK_INFO_V1);1890 1891 /*1892 * We don't want to expose information from the PCI bar that is located1893 * after 4096 bytes, so if the arch only supports larger pages, let's1894 * pretend we don't support reading the HCA's core clock. This is also1895 * forced by mmap function.1896 */1897 if (PAGE_SIZE <= 4096) {1898 resp->comp_mask |=1899 MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_CORE_CLOCK_OFFSET;1900 resp->hca_core_clock_offset =1901 offsetof(struct mlx5_init_seg,1902 internal_timer_h) % PAGE_SIZE;1903 }1904 1905 if (MLX5_CAP_GEN(dev->mdev, ece_support))1906 resp->comp_mask |= MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_ECE;1907 1908 if (rt_supported(MLX5_CAP_GEN(dev->mdev, sq_ts_format)) &&1909 rt_supported(MLX5_CAP_GEN(dev->mdev, rq_ts_format)) &&1910 rt_supported(MLX5_CAP_ROCE(dev->mdev, qp_ts_format)))1911 resp->comp_mask |=1912 MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_REAL_TIME_TS;1913 1914 resp->num_dyn_bfregs = bfregi->num_dyn_bfregs;1915 1916 if (MLX5_CAP_GEN(dev->mdev, drain_sigerr))1917 resp->comp_mask |= MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_SQD2RTS;1918 1919 resp->comp_mask |=1920 MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_MKEY_UPDATE_TAG;1921 1922 return 0;1923}1924 1925static int mlx5_ib_alloc_ucontext(struct ib_ucontext *uctx,1926 struct ib_udata *udata)1927{1928 struct ib_device *ibdev = uctx->device;1929 struct mlx5_ib_dev *dev = to_mdev(ibdev);1930 struct mlx5_ib_alloc_ucontext_req_v2 req = {};1931 struct mlx5_ib_alloc_ucontext_resp resp = {};1932 struct mlx5_ib_ucontext *context = to_mucontext(uctx);1933 struct mlx5_bfreg_info *bfregi;1934 int ver;1935 int err;1936 size_t min_req_v2 = offsetof(struct mlx5_ib_alloc_ucontext_req_v2,1937 max_cqe_version);1938 bool lib_uar_4k;1939 bool lib_uar_dyn;1940 1941 if (!dev->ib_active)1942 return -EAGAIN;1943 1944 if (udata->inlen == sizeof(struct mlx5_ib_alloc_ucontext_req))1945 ver = 0;1946 else if (udata->inlen >= min_req_v2)1947 ver = 2;1948 else1949 return -EINVAL;1950 1951 err = ib_copy_from_udata(&req, udata, min(udata->inlen, sizeof(req)));1952 if (err)1953 return err;1954 1955 if (req.flags & ~MLX5_IB_ALLOC_UCTX_DEVX)1956 return -EOPNOTSUPP;1957 1958 if (req.comp_mask || req.reserved0 || req.reserved1 || req.reserved2)1959 return -EOPNOTSUPP;1960 1961 req.total_num_bfregs = ALIGN(req.total_num_bfregs,1962 MLX5_NON_FP_BFREGS_PER_UAR);1963 if (req.num_low_latency_bfregs > req.total_num_bfregs - 1)1964 return -EINVAL;1965 1966 if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX) {1967 err = mlx5_ib_devx_create(dev, true);1968 if (err < 0)1969 goto out_ctx;1970 context->devx_uid = err;1971 }1972 1973 lib_uar_4k = req.lib_caps & MLX5_LIB_CAP_4K_UAR;1974 lib_uar_dyn = req.lib_caps & MLX5_LIB_CAP_DYN_UAR;1975 bfregi = &context->bfregi;1976 1977 if (lib_uar_dyn) {1978 bfregi->lib_uar_dyn = lib_uar_dyn;1979 goto uar_done;1980 }1981 1982 /* updates req->total_num_bfregs */1983 err = calc_total_bfregs(dev, lib_uar_4k, &req, bfregi);1984 if (err)1985 goto out_devx;1986 1987 mutex_init(&bfregi->lock);1988 bfregi->lib_uar_4k = lib_uar_4k;1989 bfregi->count = kcalloc(bfregi->total_num_bfregs, sizeof(*bfregi->count),1990 GFP_KERNEL);1991 if (!bfregi->count) {1992 err = -ENOMEM;1993 goto out_devx;1994 }1995 1996 bfregi->sys_pages = kcalloc(bfregi->num_sys_pages,1997 sizeof(*bfregi->sys_pages),1998 GFP_KERNEL);1999 if (!bfregi->sys_pages) {2000 err = -ENOMEM;2001 goto out_count;2002 }2003 2004 err = allocate_uars(dev, context);2005 if (err)2006 goto out_sys_pages;2007 2008uar_done:2009 err = mlx5_ib_alloc_transport_domain(dev, &context->tdn,2010 context->devx_uid);2011 if (err)2012 goto out_uars;2013 2014 INIT_LIST_HEAD(&context->db_page_list);2015 mutex_init(&context->db_page_mutex);2016 2017 context->cqe_version = min_t(__u8,2018 (__u8)MLX5_CAP_GEN(dev->mdev, cqe_version),2019 req.max_cqe_version);2020 2021 err = set_ucontext_resp(uctx, &resp);2022 if (err)2023 goto out_mdev;2024 2025 resp.response_length = min(udata->outlen, sizeof(resp));2026 err = ib_copy_to_udata(udata, &resp, resp.response_length);2027 if (err)2028 goto out_mdev;2029 2030 bfregi->ver = ver;2031 bfregi->num_low_latency_bfregs = req.num_low_latency_bfregs;2032 context->lib_caps = req.lib_caps;2033 print_lib_caps(dev, context->lib_caps);2034 2035 if (mlx5_ib_lag_should_assign_affinity(dev)) {2036 u32 port = mlx5_core_native_port_num(dev->mdev) - 1;2037 2038 atomic_set(&context->tx_port_affinity,2039 atomic_add_return(2040 1, &dev->port[port].roce.tx_port_affinity));2041 }2042 2043 return 0;2044 2045out_mdev:2046 mlx5_ib_dealloc_transport_domain(dev, context->tdn, context->devx_uid);2047 2048out_uars:2049 deallocate_uars(dev, context);2050 2051out_sys_pages:2052 kfree(bfregi->sys_pages);2053 2054out_count:2055 kfree(bfregi->count);2056 2057out_devx:2058 if (req.flags & MLX5_IB_ALLOC_UCTX_DEVX)2059 mlx5_ib_devx_destroy(dev, context->devx_uid);2060 2061out_ctx:2062 return err;2063}2064 2065static int mlx5_ib_query_ucontext(struct ib_ucontext *ibcontext,2066 struct uverbs_attr_bundle *attrs)2067{2068 struct mlx5_ib_alloc_ucontext_resp uctx_resp = {};2069 int ret;2070 2071 ret = set_ucontext_resp(ibcontext, &uctx_resp);2072 if (ret)2073 return ret;2074 2075 uctx_resp.response_length =2076 min_t(size_t,2077 uverbs_attr_get_len(attrs,2078 MLX5_IB_ATTR_QUERY_CONTEXT_RESP_UCTX),2079 sizeof(uctx_resp));2080 2081 ret = uverbs_copy_to_struct_or_zero(attrs,2082 MLX5_IB_ATTR_QUERY_CONTEXT_RESP_UCTX,2083 &uctx_resp,2084 sizeof(uctx_resp));2085 return ret;2086}2087 2088static void mlx5_ib_dealloc_ucontext(struct ib_ucontext *ibcontext)2089{2090 struct mlx5_ib_ucontext *context = to_mucontext(ibcontext);2091 struct mlx5_ib_dev *dev = to_mdev(ibcontext->device);2092 struct mlx5_bfreg_info *bfregi;2093 2094 bfregi = &context->bfregi;2095 mlx5_ib_dealloc_transport_domain(dev, context->tdn, context->devx_uid);2096 2097 deallocate_uars(dev, context);2098 kfree(bfregi->sys_pages);2099 kfree(bfregi->count);2100 2101 if (context->devx_uid)2102 mlx5_ib_devx_destroy(dev, context->devx_uid);2103}2104 2105static phys_addr_t uar_index2pfn(struct mlx5_ib_dev *dev,2106 int uar_idx)2107{2108 int fw_uars_per_page;2109 2110 fw_uars_per_page = MLX5_CAP_GEN(dev->mdev, uar_4k) ? MLX5_UARS_IN_PAGE : 1;2111 2112 return (dev->mdev->bar_addr >> PAGE_SHIFT) + uar_idx / fw_uars_per_page;2113}2114 2115static u64 uar_index2paddress(struct mlx5_ib_dev *dev,2116 int uar_idx)2117{2118 unsigned int fw_uars_per_page;2119 2120 fw_uars_per_page = MLX5_CAP_GEN(dev->mdev, uar_4k) ?2121 MLX5_UARS_IN_PAGE : 1;2122 2123 return (dev->mdev->bar_addr + (uar_idx / fw_uars_per_page) * PAGE_SIZE);2124}2125 2126static int get_command(unsigned long offset)2127{2128 return (offset >> MLX5_IB_MMAP_CMD_SHIFT) & MLX5_IB_MMAP_CMD_MASK;2129}2130 2131static int get_arg(unsigned long offset)2132{2133 return offset & ((1 << MLX5_IB_MMAP_CMD_SHIFT) - 1);2134}2135 2136static int get_index(unsigned long offset)2137{2138 return get_arg(offset);2139}2140 2141/* Index resides in an extra byte to enable larger values than 255 */2142static int get_extended_index(unsigned long offset)2143{2144 return get_arg(offset) | ((offset >> 16) & 0xff) << 8;2145}2146 2147 2148static void mlx5_ib_disassociate_ucontext(struct ib_ucontext *ibcontext)2149{2150}2151 2152static inline char *mmap_cmd2str(enum mlx5_ib_mmap_cmd cmd)2153{2154 switch (cmd) {2155 case MLX5_IB_MMAP_WC_PAGE:2156 return "WC";2157 case MLX5_IB_MMAP_REGULAR_PAGE:2158 return "best effort WC";2159 case MLX5_IB_MMAP_NC_PAGE:2160 return "NC";2161 case MLX5_IB_MMAP_DEVICE_MEM:2162 return "Device Memory";2163 default:2164 return "Unknown";2165 }2166}2167 2168static int mlx5_ib_mmap_clock_info_page(struct mlx5_ib_dev *dev,2169 struct vm_area_struct *vma,2170 struct mlx5_ib_ucontext *context)2171{2172 if ((vma->vm_end - vma->vm_start != PAGE_SIZE) ||2173 !(vma->vm_flags & VM_SHARED))2174 return -EINVAL;2175 2176 if (get_index(vma->vm_pgoff) != MLX5_IB_CLOCK_INFO_V1)2177 return -EOPNOTSUPP;2178 2179 if (vma->vm_flags & (VM_WRITE | VM_EXEC))2180 return -EPERM;2181 vm_flags_clear(vma, VM_MAYWRITE);2182 2183 if (!dev->mdev->clock_info)2184 return -EOPNOTSUPP;2185 2186 return vm_insert_page(vma, vma->vm_start,2187 virt_to_page(dev->mdev->clock_info));2188}2189 2190static void mlx5_ib_mmap_free(struct rdma_user_mmap_entry *entry)2191{2192 struct mlx5_user_mmap_entry *mentry = to_mmmap(entry);2193 struct mlx5_ib_dev *dev = to_mdev(entry->ucontext->device);2194 struct mlx5_var_table *var_table = &dev->var_table;2195 struct mlx5_ib_ucontext *context = to_mucontext(entry->ucontext);2196 2197 switch (mentry->mmap_flag) {2198 case MLX5_IB_MMAP_TYPE_MEMIC:2199 case MLX5_IB_MMAP_TYPE_MEMIC_OP:2200 mlx5_ib_dm_mmap_free(dev, mentry);2201 break;2202 case MLX5_IB_MMAP_TYPE_VAR:2203 mutex_lock(&var_table->bitmap_lock);2204 clear_bit(mentry->page_idx, var_table->bitmap);2205 mutex_unlock(&var_table->bitmap_lock);2206 kfree(mentry);2207 break;2208 case MLX5_IB_MMAP_TYPE_UAR_WC:2209 case MLX5_IB_MMAP_TYPE_UAR_NC:2210 mlx5_cmd_uar_dealloc(dev->mdev, mentry->page_idx,2211 context->devx_uid);2212 kfree(mentry);2213 break;2214 default:2215 WARN_ON(true);2216 }2217}2218 2219static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,2220 struct vm_area_struct *vma,2221 struct mlx5_ib_ucontext *context)2222{2223 struct mlx5_bfreg_info *bfregi = &context->bfregi;2224 int err;2225 unsigned long idx;2226 phys_addr_t pfn;2227 pgprot_t prot;2228 u32 bfreg_dyn_idx = 0;2229 u32 uar_index;2230 int dyn_uar = (cmd == MLX5_IB_MMAP_ALLOC_WC);2231 int max_valid_idx = dyn_uar ? bfregi->num_sys_pages :2232 bfregi->num_static_sys_pages;2233 2234 if (bfregi->lib_uar_dyn)2235 return -EINVAL;2236 2237 if (vma->vm_end - vma->vm_start != PAGE_SIZE)2238 return -EINVAL;2239 2240 if (dyn_uar)2241 idx = get_extended_index(vma->vm_pgoff) + bfregi->num_static_sys_pages;2242 else2243 idx = get_index(vma->vm_pgoff);2244 2245 if (idx >= max_valid_idx) {2246 mlx5_ib_warn(dev, "invalid uar index %lu, max=%d\n",2247 idx, max_valid_idx);2248 return -EINVAL;2249 }2250 2251 switch (cmd) {2252 case MLX5_IB_MMAP_WC_PAGE:2253 case MLX5_IB_MMAP_ALLOC_WC:2254 case MLX5_IB_MMAP_REGULAR_PAGE:2255 /* For MLX5_IB_MMAP_REGULAR_PAGE do the best effort to get WC */2256 prot = pgprot_writecombine(vma->vm_page_prot);2257 break;2258 case MLX5_IB_MMAP_NC_PAGE:2259 prot = pgprot_noncached(vma->vm_page_prot);2260 break;2261 default:2262 return -EINVAL;2263 }2264 2265 if (dyn_uar) {2266 int uars_per_page;2267 2268 uars_per_page = get_uars_per_sys_page(dev, bfregi->lib_uar_4k);2269 bfreg_dyn_idx = idx * (uars_per_page * MLX5_NON_FP_BFREGS_PER_UAR);2270 if (bfreg_dyn_idx >= bfregi->total_num_bfregs) {2271 mlx5_ib_warn(dev, "invalid bfreg_dyn_idx %u, max=%u\n",2272 bfreg_dyn_idx, bfregi->total_num_bfregs);2273 return -EINVAL;2274 }2275 2276 mutex_lock(&bfregi->lock);2277 /* Fail if uar already allocated, first bfreg index of each2278 * page holds its count.2279 */2280 if (bfregi->count[bfreg_dyn_idx]) {2281 mlx5_ib_warn(dev, "wrong offset, idx %lu is busy, bfregn=%u\n", idx, bfreg_dyn_idx);2282 mutex_unlock(&bfregi->lock);2283 return -EINVAL;2284 }2285 2286 bfregi->count[bfreg_dyn_idx]++;2287 mutex_unlock(&bfregi->lock);2288 2289 err = mlx5_cmd_uar_alloc(dev->mdev, &uar_index,2290 context->devx_uid);2291 if (err) {2292 mlx5_ib_warn(dev, "UAR alloc failed\n");2293 goto free_bfreg;2294 }2295 } else {2296 uar_index = bfregi->sys_pages[idx];2297 }2298 2299 pfn = uar_index2pfn(dev, uar_index);2300 mlx5_ib_dbg(dev, "uar idx 0x%lx, pfn %pa\n", idx, &pfn);2301 2302 err = rdma_user_mmap_io(&context->ibucontext, vma, pfn, PAGE_SIZE,2303 prot, NULL);2304 if (err) {2305 mlx5_ib_err(dev,2306 "rdma_user_mmap_io failed with error=%d, mmap_cmd=%s\n",2307 err, mmap_cmd2str(cmd));2308 goto err;2309 }2310 2311 if (dyn_uar)2312 bfregi->sys_pages[idx] = uar_index;2313 return 0;2314 2315err:2316 if (!dyn_uar)2317 return err;2318 2319 mlx5_cmd_uar_dealloc(dev->mdev, idx, context->devx_uid);2320 2321free_bfreg:2322 mlx5_ib_free_bfreg(dev, bfregi, bfreg_dyn_idx);2323 2324 return err;2325}2326 2327static unsigned long mlx5_vma_to_pgoff(struct vm_area_struct *vma)2328{2329 unsigned long idx;2330 u8 command;2331 2332 command = get_command(vma->vm_pgoff);2333 idx = get_extended_index(vma->vm_pgoff);2334 2335 return (command << 16 | idx);2336}2337 2338static int mlx5_ib_mmap_offset(struct mlx5_ib_dev *dev,2339 struct vm_area_struct *vma,2340 struct ib_ucontext *ucontext)2341{2342 struct mlx5_user_mmap_entry *mentry;2343 struct rdma_user_mmap_entry *entry;2344 unsigned long pgoff;2345 pgprot_t prot;2346 phys_addr_t pfn;2347 int ret;2348 2349 pgoff = mlx5_vma_to_pgoff(vma);2350 entry = rdma_user_mmap_entry_get_pgoff(ucontext, pgoff);2351 if (!entry)2352 return -EINVAL;2353 2354 mentry = to_mmmap(entry);2355 pfn = (mentry->address >> PAGE_SHIFT);2356 if (mentry->mmap_flag == MLX5_IB_MMAP_TYPE_VAR ||2357 mentry->mmap_flag == MLX5_IB_MMAP_TYPE_UAR_NC)2358 prot = pgprot_noncached(vma->vm_page_prot);2359 else2360 prot = pgprot_writecombine(vma->vm_page_prot);2361 ret = rdma_user_mmap_io(ucontext, vma, pfn,2362 entry->npages * PAGE_SIZE,2363 prot,2364 entry);2365 rdma_user_mmap_entry_put(&mentry->rdma_entry);2366 return ret;2367}2368 2369static u64 mlx5_entry_to_mmap_offset(struct mlx5_user_mmap_entry *entry)2370{2371 u64 cmd = (entry->rdma_entry.start_pgoff >> 16) & 0xFFFF;2372 u64 index = entry->rdma_entry.start_pgoff & 0xFFFF;2373 2374 return (((index >> 8) << 16) | (cmd << MLX5_IB_MMAP_CMD_SHIFT) |2375 (index & 0xFF)) << PAGE_SHIFT;2376}2377 2378static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma)2379{2380 struct mlx5_ib_ucontext *context = to_mucontext(ibcontext);2381 struct mlx5_ib_dev *dev = to_mdev(ibcontext->device);2382 unsigned long command;2383 phys_addr_t pfn;2384 2385 command = get_command(vma->vm_pgoff);2386 switch (command) {2387 case MLX5_IB_MMAP_WC_PAGE:2388 case MLX5_IB_MMAP_ALLOC_WC:2389 if (!mlx5_wc_support_get(dev->mdev))2390 return -EPERM;2391 fallthrough;2392 case MLX5_IB_MMAP_NC_PAGE:2393 case MLX5_IB_MMAP_REGULAR_PAGE:2394 return uar_mmap(dev, command, vma, context);2395 2396 case MLX5_IB_MMAP_GET_CONTIGUOUS_PAGES:2397 return -ENOSYS;2398 2399 case MLX5_IB_MMAP_CORE_CLOCK:2400 if (vma->vm_end - vma->vm_start != PAGE_SIZE)2401 return -EINVAL;2402 2403 if (vma->vm_flags & VM_WRITE)2404 return -EPERM;2405 vm_flags_clear(vma, VM_MAYWRITE);2406 2407 /* Don't expose to user-space information it shouldn't have */2408 if (PAGE_SIZE > 4096)2409 return -EOPNOTSUPP;2410 2411 pfn = (dev->mdev->iseg_base +2412 offsetof(struct mlx5_init_seg, internal_timer_h)) >>2413 PAGE_SHIFT;2414 return rdma_user_mmap_io(&context->ibucontext, vma, pfn,2415 PAGE_SIZE,2416 pgprot_noncached(vma->vm_page_prot),2417 NULL);2418 case MLX5_IB_MMAP_CLOCK_INFO:2419 return mlx5_ib_mmap_clock_info_page(dev, vma, context);2420 2421 default:2422 return mlx5_ib_mmap_offset(dev, vma, ibcontext);2423 }2424 2425 return 0;2426}2427 2428static int mlx5_ib_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)2429{2430 struct mlx5_ib_pd *pd = to_mpd(ibpd);2431 struct ib_device *ibdev = ibpd->device;2432 struct mlx5_ib_alloc_pd_resp resp;2433 int err;2434 u32 out[MLX5_ST_SZ_DW(alloc_pd_out)] = {};2435 u32 in[MLX5_ST_SZ_DW(alloc_pd_in)] = {};2436 u16 uid = 0;2437 struct mlx5_ib_ucontext *context = rdma_udata_to_drv_context(2438 udata, struct mlx5_ib_ucontext, ibucontext);2439 2440 uid = context ? context->devx_uid : 0;2441 MLX5_SET(alloc_pd_in, in, opcode, MLX5_CMD_OP_ALLOC_PD);2442 MLX5_SET(alloc_pd_in, in, uid, uid);2443 err = mlx5_cmd_exec_inout(to_mdev(ibdev)->mdev, alloc_pd, in, out);2444 if (err)2445 return err;2446 2447 pd->pdn = MLX5_GET(alloc_pd_out, out, pd);2448 pd->uid = uid;2449 if (udata) {2450 resp.pdn = pd->pdn;2451 if (ib_copy_to_udata(udata, &resp, sizeof(resp))) {2452 mlx5_cmd_dealloc_pd(to_mdev(ibdev)->mdev, pd->pdn, uid);2453 return -EFAULT;2454 }2455 }2456 2457 return 0;2458}2459 2460static int mlx5_ib_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata)2461{2462 struct mlx5_ib_dev *mdev = to_mdev(pd->device);2463 struct mlx5_ib_pd *mpd = to_mpd(pd);2464 2465 return mlx5_cmd_dealloc_pd(mdev->mdev, mpd->pdn, mpd->uid);2466}2467 2468static int mlx5_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)2469{2470 struct mlx5_ib_dev *dev = to_mdev(ibqp->device);2471 struct mlx5_ib_qp *mqp = to_mqp(ibqp);2472 int err;2473 u16 uid;2474 2475 uid = ibqp->pd ?2476 to_mpd(ibqp->pd)->uid : 0;2477 2478 if (mqp->flags & IB_QP_CREATE_SOURCE_QPN) {2479 mlx5_ib_dbg(dev, "Attaching a multi cast group to underlay QP is not supported\n");2480 return -EOPNOTSUPP;2481 }2482 2483 err = mlx5_cmd_attach_mcg(dev->mdev, gid, ibqp->qp_num, uid);2484 if (err)2485 mlx5_ib_warn(dev, "failed attaching QPN 0x%x, MGID %pI6\n",2486 ibqp->qp_num, gid->raw);2487 2488 return err;2489}2490 2491static int mlx5_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)2492{2493 struct mlx5_ib_dev *dev = to_mdev(ibqp->device);2494 int err;2495 u16 uid;2496 2497 uid = ibqp->pd ?2498 to_mpd(ibqp->pd)->uid : 0;2499 err = mlx5_cmd_detach_mcg(dev->mdev, gid, ibqp->qp_num, uid);2500 if (err)2501 mlx5_ib_warn(dev, "failed detaching QPN 0x%x, MGID %pI6\n",2502 ibqp->qp_num, gid->raw);2503 2504 return err;2505}2506 2507static int init_node_data(struct mlx5_ib_dev *dev)2508{2509 int err;2510 2511 err = mlx5_query_node_desc(dev, dev->ib_dev.node_desc);2512 if (err)2513 return err;2514 2515 dev->mdev->rev_id = dev->mdev->pdev->revision;2516 2517 return mlx5_query_node_guid(dev, &dev->ib_dev.node_guid);2518}2519 2520static ssize_t fw_pages_show(struct device *device,2521 struct device_attribute *attr, char *buf)2522{2523 struct mlx5_ib_dev *dev =2524 rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev);2525 2526 return sysfs_emit(buf, "%d\n", dev->mdev->priv.fw_pages);2527}2528static DEVICE_ATTR_RO(fw_pages);2529 2530static ssize_t reg_pages_show(struct device *device,2531 struct device_attribute *attr, char *buf)2532{2533 struct mlx5_ib_dev *dev =2534 rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev);2535 2536 return sysfs_emit(buf, "%d\n", atomic_read(&dev->mdev->priv.reg_pages));2537}2538static DEVICE_ATTR_RO(reg_pages);2539 2540static ssize_t hca_type_show(struct device *device,2541 struct device_attribute *attr, char *buf)2542{2543 struct mlx5_ib_dev *dev =2544 rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev);2545 2546 return sysfs_emit(buf, "MT%d\n", dev->mdev->pdev->device);2547}2548static DEVICE_ATTR_RO(hca_type);2549 2550static ssize_t hw_rev_show(struct device *device,2551 struct device_attribute *attr, char *buf)2552{2553 struct mlx5_ib_dev *dev =2554 rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev);2555 2556 return sysfs_emit(buf, "%x\n", dev->mdev->rev_id);2557}2558static DEVICE_ATTR_RO(hw_rev);2559 2560static ssize_t board_id_show(struct device *device,2561 struct device_attribute *attr, char *buf)2562{2563 struct mlx5_ib_dev *dev =2564 rdma_device_to_drv_device(device, struct mlx5_ib_dev, ib_dev);2565 2566 return sysfs_emit(buf, "%.*s\n", MLX5_BOARD_ID_LEN,2567 dev->mdev->board_id);2568}2569static DEVICE_ATTR_RO(board_id);2570 2571static struct attribute *mlx5_class_attributes[] = {2572 &dev_attr_hw_rev.attr,2573 &dev_attr_hca_type.attr,2574 &dev_attr_board_id.attr,2575 &dev_attr_fw_pages.attr,2576 &dev_attr_reg_pages.attr,2577 NULL,2578};2579 2580static const struct attribute_group mlx5_attr_group = {2581 .attrs = mlx5_class_attributes,2582};2583 2584static void pkey_change_handler(struct work_struct *work)2585{2586 struct mlx5_ib_port_resources *ports =2587 container_of(work, struct mlx5_ib_port_resources,2588 pkey_change_work);2589 2590 if (!ports->gsi)2591 /*2592 * We got this event before device was fully configured2593 * and MAD registration code wasn't called/finished yet.2594 */2595 return;2596 2597 mlx5_ib_gsi_pkey_change(ports->gsi);2598}2599 2600static void mlx5_ib_handle_internal_error(struct mlx5_ib_dev *ibdev)2601{2602 struct mlx5_ib_qp *mqp;2603 struct mlx5_ib_cq *send_mcq, *recv_mcq;2604 struct mlx5_core_cq *mcq;2605 struct list_head cq_armed_list;2606 unsigned long flags_qp;2607 unsigned long flags_cq;2608 unsigned long flags;2609 2610 INIT_LIST_HEAD(&cq_armed_list);2611 2612 /* Go over qp list reside on that ibdev, sync with create/destroy qp.*/2613 spin_lock_irqsave(&ibdev->reset_flow_resource_lock, flags);2614 list_for_each_entry(mqp, &ibdev->qp_list, qps_list) {2615 spin_lock_irqsave(&mqp->sq.lock, flags_qp);2616 if (mqp->sq.tail != mqp->sq.head) {2617 send_mcq = to_mcq(mqp->ibqp.send_cq);2618 spin_lock_irqsave(&send_mcq->lock, flags_cq);2619 if (send_mcq->mcq.comp &&2620 mqp->ibqp.send_cq->comp_handler) {2621 if (!send_mcq->mcq.reset_notify_added) {2622 send_mcq->mcq.reset_notify_added = 1;2623 list_add_tail(&send_mcq->mcq.reset_notify,2624 &cq_armed_list);2625 }2626 }2627 spin_unlock_irqrestore(&send_mcq->lock, flags_cq);2628 }2629 spin_unlock_irqrestore(&mqp->sq.lock, flags_qp);2630 spin_lock_irqsave(&mqp->rq.lock, flags_qp);2631 /* no handling is needed for SRQ */2632 if (!mqp->ibqp.srq) {2633 if (mqp->rq.tail != mqp->rq.head) {2634 recv_mcq = to_mcq(mqp->ibqp.recv_cq);2635 spin_lock_irqsave(&recv_mcq->lock, flags_cq);2636 if (recv_mcq->mcq.comp &&2637 mqp->ibqp.recv_cq->comp_handler) {2638 if (!recv_mcq->mcq.reset_notify_added) {2639 recv_mcq->mcq.reset_notify_added = 1;2640 list_add_tail(&recv_mcq->mcq.reset_notify,2641 &cq_armed_list);2642 }2643 }2644 spin_unlock_irqrestore(&recv_mcq->lock,2645 flags_cq);2646 }2647 }2648 spin_unlock_irqrestore(&mqp->rq.lock, flags_qp);2649 }2650 /*At that point all inflight post send were put to be executed as of we2651 * lock/unlock above locks Now need to arm all involved CQs.2652 */2653 list_for_each_entry(mcq, &cq_armed_list, reset_notify) {2654 mcq->comp(mcq, NULL);2655 }2656 spin_unlock_irqrestore(&ibdev->reset_flow_resource_lock, flags);2657}2658 2659static void delay_drop_handler(struct work_struct *work)2660{2661 int err;2662 struct mlx5_ib_delay_drop *delay_drop =2663 container_of(work, struct mlx5_ib_delay_drop,2664 delay_drop_work);2665 2666 atomic_inc(&delay_drop->events_cnt);2667 2668 mutex_lock(&delay_drop->lock);2669 err = mlx5_core_set_delay_drop(delay_drop->dev, delay_drop->timeout);2670 if (err) {2671 mlx5_ib_warn(delay_drop->dev, "Failed to set delay drop, timeout=%u\n",2672 delay_drop->timeout);2673 delay_drop->activate = false;2674 }2675 mutex_unlock(&delay_drop->lock);2676}2677 2678static void handle_general_event(struct mlx5_ib_dev *ibdev, struct mlx5_eqe *eqe,2679 struct ib_event *ibev)2680{2681 u32 port = (eqe->data.port.port >> 4) & 0xf;2682 2683 switch (eqe->sub_type) {2684 case MLX5_GENERAL_SUBTYPE_DELAY_DROP_TIMEOUT:2685 if (mlx5_ib_port_link_layer(&ibdev->ib_dev, port) ==2686 IB_LINK_LAYER_ETHERNET)2687 schedule_work(&ibdev->delay_drop.delay_drop_work);2688 break;2689 default: /* do nothing */2690 return;2691 }2692}2693 2694static int handle_port_change(struct mlx5_ib_dev *ibdev, struct mlx5_eqe *eqe,2695 struct ib_event *ibev)2696{2697 u32 port = (eqe->data.port.port >> 4) & 0xf;2698 2699 ibev->element.port_num = port;2700 2701 switch (eqe->sub_type) {2702 case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE:2703 case MLX5_PORT_CHANGE_SUBTYPE_DOWN:2704 case MLX5_PORT_CHANGE_SUBTYPE_INITIALIZED:2705 /* In RoCE, port up/down events are handled in2706 * mlx5_netdev_event().2707 */2708 if (mlx5_ib_port_link_layer(&ibdev->ib_dev, port) ==2709 IB_LINK_LAYER_ETHERNET)2710 return -EINVAL;2711 2712 ibev->event = (eqe->sub_type == MLX5_PORT_CHANGE_SUBTYPE_ACTIVE) ?2713 IB_EVENT_PORT_ACTIVE : IB_EVENT_PORT_ERR;2714 break;2715 2716 case MLX5_PORT_CHANGE_SUBTYPE_LID:2717 ibev->event = IB_EVENT_LID_CHANGE;2718 break;2719 2720 case MLX5_PORT_CHANGE_SUBTYPE_PKEY:2721 ibev->event = IB_EVENT_PKEY_CHANGE;2722 schedule_work(&ibdev->devr.ports[port - 1].pkey_change_work);2723 break;2724 2725 case MLX5_PORT_CHANGE_SUBTYPE_GUID:2726 ibev->event = IB_EVENT_GID_CHANGE;2727 break;2728 2729 case MLX5_PORT_CHANGE_SUBTYPE_CLIENT_REREG:2730 ibev->event = IB_EVENT_CLIENT_REREGISTER;2731 break;2732 default:2733 return -EINVAL;2734 }2735 2736 return 0;2737}2738 2739static void mlx5_ib_handle_event(struct work_struct *_work)2740{2741 struct mlx5_ib_event_work *work =2742 container_of(_work, struct mlx5_ib_event_work, work);2743 struct mlx5_ib_dev *ibdev;2744 struct ib_event ibev;2745 bool fatal = false;2746 2747 if (work->is_slave) {2748 ibdev = mlx5_ib_get_ibdev_from_mpi(work->mpi);2749 if (!ibdev)2750 goto out;2751 } else {2752 ibdev = work->dev;2753 }2754 2755 switch (work->event) {2756 case MLX5_DEV_EVENT_SYS_ERROR:2757 ibev.event = IB_EVENT_DEVICE_FATAL;2758 mlx5_ib_handle_internal_error(ibdev);2759 ibev.element.port_num = (u8)(unsigned long)work->param;2760 fatal = true;2761 break;2762 case MLX5_EVENT_TYPE_PORT_CHANGE:2763 if (handle_port_change(ibdev, work->param, &ibev))2764 goto out;2765 break;2766 case MLX5_EVENT_TYPE_GENERAL_EVENT:2767 handle_general_event(ibdev, work->param, &ibev);2768 fallthrough;2769 default:2770 goto out;2771 }2772 2773 ibev.device = &ibdev->ib_dev;2774 2775 if (!rdma_is_port_valid(&ibdev->ib_dev, ibev.element.port_num)) {2776 mlx5_ib_warn(ibdev, "warning: event on port %d\n", ibev.element.port_num);2777 goto out;2778 }2779 2780 if (ibdev->ib_active)2781 ib_dispatch_event(&ibev);2782 2783 if (fatal)2784 ibdev->ib_active = false;2785out:2786 kfree(work);2787}2788 2789static int mlx5_ib_event(struct notifier_block *nb,2790 unsigned long event, void *param)2791{2792 struct mlx5_ib_event_work *work;2793 2794 work = kmalloc(sizeof(*work), GFP_ATOMIC);2795 if (!work)2796 return NOTIFY_DONE;2797 2798 INIT_WORK(&work->work, mlx5_ib_handle_event);2799 work->dev = container_of(nb, struct mlx5_ib_dev, mdev_events);2800 work->is_slave = false;2801 work->param = param;2802 work->event = event;2803 2804 queue_work(mlx5_ib_event_wq, &work->work);2805 2806 return NOTIFY_OK;2807}2808 2809static int mlx5_ib_event_slave_port(struct notifier_block *nb,2810 unsigned long event, void *param)2811{2812 struct mlx5_ib_event_work *work;2813 2814 work = kmalloc(sizeof(*work), GFP_ATOMIC);2815 if (!work)2816 return NOTIFY_DONE;2817 2818 INIT_WORK(&work->work, mlx5_ib_handle_event);2819 work->mpi = container_of(nb, struct mlx5_ib_multiport_info, mdev_events);2820 work->is_slave = true;2821 work->param = param;2822 work->event = event;2823 queue_work(mlx5_ib_event_wq, &work->work);2824 2825 return NOTIFY_OK;2826}2827 2828static int mlx5_ib_get_plane_num(struct mlx5_core_dev *mdev, u8 *num_plane)2829{2830 struct mlx5_hca_vport_context vport_ctx;2831 int err;2832 2833 *num_plane = 0;2834 if (!MLX5_CAP_GEN(mdev, ib_virt))2835 return 0;2836 2837 err = mlx5_query_hca_vport_context(mdev, 0, 1, 0, &vport_ctx);2838 if (err)2839 return err;2840 2841 *num_plane = vport_ctx.num_plane;2842 return 0;2843}2844 2845static int set_has_smi_cap(struct mlx5_ib_dev *dev)2846{2847 struct mlx5_hca_vport_context vport_ctx;2848 int err;2849 int port;2850 2851 if (MLX5_CAP_GEN(dev->mdev, port_type) != MLX5_CAP_PORT_TYPE_IB)2852 return 0;2853 2854 for (port = 1; port <= dev->num_ports; port++) {2855 if (dev->num_plane) {2856 dev->port_caps[port - 1].has_smi = false;2857 continue;2858 } else if (!MLX5_CAP_GEN(dev->mdev, ib_virt) ||2859 dev->ib_dev.type == RDMA_DEVICE_TYPE_SMI) {2860 dev->port_caps[port - 1].has_smi = true;2861 continue;2862 }2863 2864 err = mlx5_query_hca_vport_context(dev->mdev, 0, port, 0,2865 &vport_ctx);2866 if (err) {2867 mlx5_ib_err(dev, "query_hca_vport_context for port=%d failed %d\n",2868 port, err);2869 return err;2870 }2871 dev->port_caps[port - 1].has_smi = vport_ctx.has_smi;2872 }2873 2874 return 0;2875}2876 2877static void get_ext_port_caps(struct mlx5_ib_dev *dev)2878{2879 unsigned int port;2880 2881 rdma_for_each_port (&dev->ib_dev, port)2882 mlx5_query_ext_port_caps(dev, port);2883}2884 2885static u8 mlx5_get_umr_fence(u8 umr_fence_cap)2886{2887 switch (umr_fence_cap) {2888 case MLX5_CAP_UMR_FENCE_NONE:2889 return MLX5_FENCE_MODE_NONE;2890 case MLX5_CAP_UMR_FENCE_SMALL:2891 return MLX5_FENCE_MODE_INITIATOR_SMALL;2892 default:2893 return MLX5_FENCE_MODE_STRONG_ORDERING;2894 }2895}2896 2897int mlx5_ib_dev_res_cq_init(struct mlx5_ib_dev *dev)2898{2899 struct mlx5_ib_resources *devr = &dev->devr;2900 struct ib_cq_init_attr cq_attr = {.cqe = 1};2901 struct ib_device *ibdev;2902 struct ib_pd *pd;2903 struct ib_cq *cq;2904 int ret = 0;2905 2906 2907 /*2908 * devr->c0 is set once, never changed until device unload.2909 * Avoid taking the mutex if initialization is already done.2910 */2911 if (devr->c0)2912 return 0;2913 2914 mutex_lock(&devr->cq_lock);2915 if (devr->c0)2916 goto unlock;2917 2918 ibdev = &dev->ib_dev;2919 pd = ib_alloc_pd(ibdev, 0);2920 if (IS_ERR(pd)) {2921 ret = PTR_ERR(pd);2922 mlx5_ib_err(dev, "Couldn't allocate PD for res init, err=%d\n", ret);2923 goto unlock;2924 }2925 2926 cq = ib_create_cq(ibdev, NULL, NULL, NULL, &cq_attr);2927 if (IS_ERR(cq)) {2928 ret = PTR_ERR(cq);2929 mlx5_ib_err(dev, "Couldn't create CQ for res init, err=%d\n", ret);2930 ib_dealloc_pd(pd);2931 goto unlock;2932 }2933 2934 devr->p0 = pd;2935 devr->c0 = cq;2936 2937unlock:2938 mutex_unlock(&devr->cq_lock);2939 return ret;2940}2941 2942int mlx5_ib_dev_res_srq_init(struct mlx5_ib_dev *dev)2943{2944 struct mlx5_ib_resources *devr = &dev->devr;2945 struct ib_srq_init_attr attr;2946 struct ib_srq *s0, *s1;2947 int ret = 0;2948 2949 /*2950 * devr->s1 is set once, never changed until device unload.2951 * Avoid taking the mutex if initialization is already done.2952 */2953 if (devr->s1)2954 return 0;2955 2956 mutex_lock(&devr->srq_lock);2957 if (devr->s1)2958 goto unlock;2959 2960 ret = mlx5_ib_dev_res_cq_init(dev);2961 if (ret)2962 goto unlock;2963 2964 memset(&attr, 0, sizeof(attr));2965 attr.attr.max_sge = 1;2966 attr.attr.max_wr = 1;2967 attr.srq_type = IB_SRQT_XRC;2968 attr.ext.cq = devr->c0;2969 2970 s0 = ib_create_srq(devr->p0, &attr);2971 if (IS_ERR(s0)) {2972 ret = PTR_ERR(s0);2973 mlx5_ib_err(dev, "Couldn't create SRQ 0 for res init, err=%d\n", ret);2974 goto unlock;2975 }2976 2977 memset(&attr, 0, sizeof(attr));2978 attr.attr.max_sge = 1;2979 attr.attr.max_wr = 1;2980 attr.srq_type = IB_SRQT_BASIC;2981 2982 s1 = ib_create_srq(devr->p0, &attr);2983 if (IS_ERR(s1)) {2984 ret = PTR_ERR(s1);2985 mlx5_ib_err(dev, "Couldn't create SRQ 1 for res init, err=%d\n", ret);2986 ib_destroy_srq(s0);2987 }2988 2989 devr->s0 = s0;2990 devr->s1 = s1;2991 2992unlock:2993 mutex_unlock(&devr->srq_lock);2994 return ret;2995}2996 2997static int mlx5_ib_dev_res_init(struct mlx5_ib_dev *dev)2998{2999 struct mlx5_ib_resources *devr = &dev->devr;3000 int port;3001 int ret;3002 3003 if (!MLX5_CAP_GEN(dev->mdev, xrc))3004 return -EOPNOTSUPP;3005 3006 ret = mlx5_cmd_xrcd_alloc(dev->mdev, &devr->xrcdn0, 0);3007 if (ret)3008 return ret;3009 3010 ret = mlx5_cmd_xrcd_alloc(dev->mdev, &devr->xrcdn1, 0);3011 if (ret) {3012 mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn0, 0);3013 return ret;3014 }3015 3016 for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)3017 INIT_WORK(&devr->ports[port].pkey_change_work,3018 pkey_change_handler);3019 3020 mutex_init(&devr->cq_lock);3021 mutex_init(&devr->srq_lock);3022 3023 return 0;3024}3025 3026static void mlx5_ib_dev_res_cleanup(struct mlx5_ib_dev *dev)3027{3028 struct mlx5_ib_resources *devr = &dev->devr;3029 int port;3030 3031 /*3032 * Make sure no change P_Key work items are still executing.3033 *3034 * At this stage, the mlx5_ib_event should be unregistered3035 * and it ensures that no new works are added.3036 */3037 for (port = 0; port < ARRAY_SIZE(devr->ports); ++port)3038 cancel_work_sync(&devr->ports[port].pkey_change_work);3039 3040 /* After s0/s1 init, they are not unset during the device lifetime. */3041 if (devr->s1) {3042 ib_destroy_srq(devr->s1);3043 ib_destroy_srq(devr->s0);3044 }3045 mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn1, 0);3046 mlx5_cmd_xrcd_dealloc(dev->mdev, devr->xrcdn0, 0);3047 /* After p0/c0 init, they are not unset during the device lifetime. */3048 if (devr->c0) {3049 ib_destroy_cq(devr->c0);3050 ib_dealloc_pd(devr->p0);3051 }3052 mutex_destroy(&devr->cq_lock);3053 mutex_destroy(&devr->srq_lock);3054}3055 3056static int3057mlx5_ib_create_data_direct_resources(struct mlx5_ib_dev *dev)3058{3059 int inlen = MLX5_ST_SZ_BYTES(create_mkey_in);3060 struct mlx5_core_dev *mdev = dev->mdev;3061 void *mkc;3062 u32 mkey;3063 u32 pdn;3064 u32 *in;3065 int err;3066 3067 err = mlx5_core_alloc_pd(mdev, &pdn);3068 if (err)3069 return err;3070 3071 in = kvzalloc(inlen, GFP_KERNEL);3072 if (!in) {3073 err = -ENOMEM;3074 goto err;3075 }3076 3077 MLX5_SET(create_mkey_in, in, data_direct, 1);3078 mkc = MLX5_ADDR_OF(create_mkey_in, in, memory_key_mkey_entry);3079 MLX5_SET(mkc, mkc, access_mode_1_0, MLX5_MKC_ACCESS_MODE_PA);3080 MLX5_SET(mkc, mkc, lw, 1);3081 MLX5_SET(mkc, mkc, lr, 1);3082 MLX5_SET(mkc, mkc, rw, 1);3083 MLX5_SET(mkc, mkc, rr, 1);3084 MLX5_SET(mkc, mkc, a, 1);3085 MLX5_SET(mkc, mkc, pd, pdn);3086 MLX5_SET(mkc, mkc, length64, 1);3087 MLX5_SET(mkc, mkc, qpn, 0xffffff);3088 err = mlx5_core_create_mkey(mdev, &mkey, in, inlen);3089 kvfree(in);3090 if (err)3091 goto err;3092 3093 dev->ddr.mkey = mkey;3094 dev->ddr.pdn = pdn;3095 return 0;3096 3097err:3098 mlx5_core_dealloc_pd(mdev, pdn);3099 return err;3100}3101 3102static void3103mlx5_ib_free_data_direct_resources(struct mlx5_ib_dev *dev)3104{3105 mlx5_core_destroy_mkey(dev->mdev, dev->ddr.mkey);3106 mlx5_core_dealloc_pd(dev->mdev, dev->ddr.pdn);3107}3108 3109static u32 get_core_cap_flags(struct ib_device *ibdev,3110 struct mlx5_hca_vport_context *rep)3111{3112 struct mlx5_ib_dev *dev = to_mdev(ibdev);3113 enum rdma_link_layer ll = mlx5_ib_port_link_layer(ibdev, 1);3114 u8 l3_type_cap = MLX5_CAP_ROCE(dev->mdev, l3_type);3115 u8 roce_version_cap = MLX5_CAP_ROCE(dev->mdev, roce_version);3116 bool raw_support = !mlx5_core_mp_enabled(dev->mdev);3117 u32 ret = 0;3118 3119 if (rep->grh_required)3120 ret |= RDMA_CORE_CAP_IB_GRH_REQUIRED;3121 3122 if (dev->num_plane)3123 return ret | RDMA_CORE_CAP_PROT_IB | RDMA_CORE_CAP_IB_MAD |3124 RDMA_CORE_CAP_IB_CM | RDMA_CORE_CAP_IB_SA |3125 RDMA_CORE_CAP_AF_IB;3126 else if (ibdev->type == RDMA_DEVICE_TYPE_SMI)3127 return ret | RDMA_CORE_CAP_IB_MAD | RDMA_CORE_CAP_IB_SMI;3128 3129 if (ll == IB_LINK_LAYER_INFINIBAND)3130 return ret | RDMA_CORE_PORT_IBA_IB;3131 3132 if (raw_support)3133 ret |= RDMA_CORE_PORT_RAW_PACKET;3134 3135 if (!(l3_type_cap & MLX5_ROCE_L3_TYPE_IPV4_CAP))3136 return ret;3137 3138 if (!(l3_type_cap & MLX5_ROCE_L3_TYPE_IPV6_CAP))3139 return ret;3140 3141 if (roce_version_cap & MLX5_ROCE_VERSION_1_CAP)3142 ret |= RDMA_CORE_PORT_IBA_ROCE;3143 3144 if (roce_version_cap & MLX5_ROCE_VERSION_2_CAP)3145 ret |= RDMA_CORE_PORT_IBA_ROCE_UDP_ENCAP;3146 3147 return ret;3148}3149 3150static int mlx5_port_immutable(struct ib_device *ibdev, u32 port_num,3151 struct ib_port_immutable *immutable)3152{3153 struct ib_port_attr attr;3154 struct mlx5_ib_dev *dev = to_mdev(ibdev);3155 enum rdma_link_layer ll = mlx5_ib_port_link_layer(ibdev, port_num);3156 struct mlx5_hca_vport_context rep = {0};3157 int err;3158 3159 err = ib_query_port(ibdev, port_num, &attr);3160 if (err)3161 return err;3162 3163 if (ll == IB_LINK_LAYER_INFINIBAND) {3164 if (ibdev->type == RDMA_DEVICE_TYPE_SMI)3165 port_num = smi_to_native_portnum(dev, port_num);3166 3167 err = mlx5_query_hca_vport_context(dev->mdev, 0, port_num, 0,3168 &rep);3169 if (err)3170 return err;3171 }3172 3173 immutable->pkey_tbl_len = attr.pkey_tbl_len;3174 immutable->gid_tbl_len = attr.gid_tbl_len;3175 immutable->core_cap_flags = get_core_cap_flags(ibdev, &rep);3176 immutable->max_mad_size = IB_MGMT_MAD_SIZE;3177 3178 return 0;3179}3180 3181static int mlx5_port_rep_immutable(struct ib_device *ibdev, u32 port_num,3182 struct ib_port_immutable *immutable)3183{3184 struct ib_port_attr attr;3185 int err;3186 3187 immutable->core_cap_flags = RDMA_CORE_PORT_RAW_PACKET;3188 3189 err = ib_query_port(ibdev, port_num, &attr);3190 if (err)3191 return err;3192 3193 immutable->pkey_tbl_len = attr.pkey_tbl_len;3194 immutable->gid_tbl_len = attr.gid_tbl_len;3195 immutable->core_cap_flags = RDMA_CORE_PORT_RAW_PACKET;3196 3197 return 0;3198}3199 3200static void get_dev_fw_str(struct ib_device *ibdev, char *str)3201{3202 struct mlx5_ib_dev *dev =3203 container_of(ibdev, struct mlx5_ib_dev, ib_dev);3204 snprintf(str, IB_FW_VERSION_NAME_MAX, "%d.%d.%04d",3205 fw_rev_maj(dev->mdev), fw_rev_min(dev->mdev),3206 fw_rev_sub(dev->mdev));3207}3208 3209static int lag_event(struct notifier_block *nb, unsigned long event, void *data)3210{3211 struct mlx5_ib_dev *dev = container_of(nb, struct mlx5_ib_dev,3212 lag_events);3213 struct mlx5_core_dev *mdev = dev->mdev;3214 struct mlx5_ib_port *port;3215 struct net_device *ndev;3216 int i, err;3217 int portnum;3218 3219 portnum = 0;3220 switch (event) {3221 case MLX5_DRIVER_EVENT_ACTIVE_BACKUP_LAG_CHANGE_LOWERSTATE:3222 ndev = data;3223 if (ndev) {3224 if (!mlx5_lag_is_roce(mdev)) {3225 // sriov lag3226 for (i = 0; i < dev->num_ports; i++) {3227 port = &dev->port[i];3228 if (port->rep && port->rep->vport ==3229 MLX5_VPORT_UPLINK) {3230 portnum = i;3231 break;3232 }3233 }3234 }3235 err = ib_device_set_netdev(&dev->ib_dev, ndev,3236 portnum + 1);3237 dev_put(ndev);3238 if (err)3239 return err;3240 /* Rescan gids after new netdev assignment */3241 rdma_roce_rescan_device(&dev->ib_dev);3242 }3243 break;3244 default:3245 return NOTIFY_DONE;3246 }3247 return NOTIFY_OK;3248}3249 3250static void mlx5e_lag_event_register(struct mlx5_ib_dev *dev)3251{3252 dev->lag_events.notifier_call = lag_event;3253 blocking_notifier_chain_register(&dev->mdev->priv.lag_nh,3254 &dev->lag_events);3255}3256 3257static void mlx5e_lag_event_unregister(struct mlx5_ib_dev *dev)3258{3259 blocking_notifier_chain_unregister(&dev->mdev->priv.lag_nh,3260 &dev->lag_events);3261}3262 3263static int mlx5_eth_lag_init(struct mlx5_ib_dev *dev)3264{3265 struct mlx5_core_dev *mdev = dev->mdev;3266 struct mlx5_flow_namespace *ns = mlx5_get_flow_namespace(mdev,3267 MLX5_FLOW_NAMESPACE_LAG);3268 struct mlx5_flow_table *ft;3269 int err;3270 3271 if (!ns || !mlx5_lag_is_active(mdev))3272 return 0;3273 3274 err = mlx5_cmd_create_vport_lag(mdev);3275 if (err)3276 return err;3277 3278 ft = mlx5_create_lag_demux_flow_table(ns, 0, 0);3279 if (IS_ERR(ft)) {3280 err = PTR_ERR(ft);3281 goto err_destroy_vport_lag;3282 }3283 3284 mlx5e_lag_event_register(dev);3285 dev->flow_db->lag_demux_ft = ft;3286 dev->lag_ports = mlx5_lag_get_num_ports(mdev);3287 dev->lag_active = true;3288 return 0;3289 3290err_destroy_vport_lag:3291 mlx5_cmd_destroy_vport_lag(mdev);3292 return err;3293}3294 3295static void mlx5_eth_lag_cleanup(struct mlx5_ib_dev *dev)3296{3297 struct mlx5_core_dev *mdev = dev->mdev;3298 3299 if (dev->lag_active) {3300 dev->lag_active = false;3301 3302 mlx5e_lag_event_unregister(dev);3303 mlx5_destroy_flow_table(dev->flow_db->lag_demux_ft);3304 dev->flow_db->lag_demux_ft = NULL;3305 3306 mlx5_cmd_destroy_vport_lag(mdev);3307 }3308}3309 3310static void mlx5_netdev_notifier_register(struct mlx5_roce *roce,3311 struct net_device *netdev)3312{3313 int err;3314 3315 if (roce->tracking_netdev)3316 return;3317 roce->tracking_netdev = netdev;3318 roce->nb.notifier_call = mlx5_netdev_event;3319 err = register_netdevice_notifier_dev_net(netdev, &roce->nb, &roce->nn);3320 WARN_ON(err);3321}3322 3323static void mlx5_netdev_notifier_unregister(struct mlx5_roce *roce)3324{3325 if (!roce->tracking_netdev)3326 return;3327 unregister_netdevice_notifier_dev_net(roce->tracking_netdev, &roce->nb,3328 &roce->nn);3329 roce->tracking_netdev = NULL;3330}3331 3332static int mlx5e_mdev_notifier_event(struct notifier_block *nb,3333 unsigned long event, void *data)3334{3335 struct mlx5_roce *roce = container_of(nb, struct mlx5_roce, mdev_nb);3336 struct net_device *netdev = data;3337 3338 switch (event) {3339 case MLX5_DRIVER_EVENT_UPLINK_NETDEV:3340 if (netdev)3341 mlx5_netdev_notifier_register(roce, netdev);3342 else3343 mlx5_netdev_notifier_unregister(roce);3344 break;3345 default:3346 return NOTIFY_DONE;3347 }3348 3349 return NOTIFY_OK;3350}3351 3352static void mlx5_mdev_netdev_track(struct mlx5_ib_dev *dev, u32 port_num)3353{3354 struct mlx5_roce *roce = &dev->port[port_num].roce;3355 3356 roce->mdev_nb.notifier_call = mlx5e_mdev_notifier_event;3357 mlx5_blocking_notifier_register(dev->mdev, &roce->mdev_nb);3358 mlx5_core_uplink_netdev_event_replay(dev->mdev);3359}3360 3361static void mlx5_mdev_netdev_untrack(struct mlx5_ib_dev *dev, u32 port_num)3362{3363 struct mlx5_roce *roce = &dev->port[port_num].roce;3364 3365 mlx5_blocking_notifier_unregister(dev->mdev, &roce->mdev_nb);3366 mlx5_netdev_notifier_unregister(roce);3367}3368 3369static int mlx5_enable_eth(struct mlx5_ib_dev *dev)3370{3371 int err;3372 3373 if (!dev->is_rep && dev->profile != &raw_eth_profile) {3374 err = mlx5_nic_vport_enable_roce(dev->mdev);3375 if (err)3376 return err;3377 }3378 3379 err = mlx5_eth_lag_init(dev);3380 if (err)3381 goto err_disable_roce;3382 3383 return 0;3384 3385err_disable_roce:3386 if (!dev->is_rep && dev->profile != &raw_eth_profile)3387 mlx5_nic_vport_disable_roce(dev->mdev);3388 3389 return err;3390}3391 3392static void mlx5_disable_eth(struct mlx5_ib_dev *dev)3393{3394 mlx5_eth_lag_cleanup(dev);3395 if (!dev->is_rep && dev->profile != &raw_eth_profile)3396 mlx5_nic_vport_disable_roce(dev->mdev);3397}3398 3399static int mlx5_ib_rn_get_params(struct ib_device *device, u32 port_num,3400 enum rdma_netdev_t type,3401 struct rdma_netdev_alloc_params *params)3402{3403 if (type != RDMA_NETDEV_IPOIB)3404 return -EOPNOTSUPP;3405 3406 return mlx5_rdma_rn_get_params(to_mdev(device)->mdev, device, params);3407}3408 3409static ssize_t delay_drop_timeout_read(struct file *filp, char __user *buf,3410 size_t count, loff_t *pos)3411{3412 struct mlx5_ib_delay_drop *delay_drop = filp->private_data;3413 char lbuf[20];3414 int len;3415 3416 len = snprintf(lbuf, sizeof(lbuf), "%u\n", delay_drop->timeout);3417 return simple_read_from_buffer(buf, count, pos, lbuf, len);3418}3419 3420static ssize_t delay_drop_timeout_write(struct file *filp, const char __user *buf,3421 size_t count, loff_t *pos)3422{3423 struct mlx5_ib_delay_drop *delay_drop = filp->private_data;3424 u32 timeout;3425 u32 var;3426 3427 if (kstrtouint_from_user(buf, count, 0, &var))3428 return -EFAULT;3429 3430 timeout = min_t(u32, roundup(var, 100), MLX5_MAX_DELAY_DROP_TIMEOUT_MS *3431 1000);3432 if (timeout != var)3433 mlx5_ib_dbg(delay_drop->dev, "Round delay drop timeout to %u usec\n",3434 timeout);3435 3436 delay_drop->timeout = timeout;3437 3438 return count;3439}3440 3441static const struct file_operations fops_delay_drop_timeout = {3442 .owner = THIS_MODULE,3443 .open = simple_open,3444 .write = delay_drop_timeout_write,3445 .read = delay_drop_timeout_read,3446};3447 3448static void mlx5_ib_unbind_slave_port(struct mlx5_ib_dev *ibdev,3449 struct mlx5_ib_multiport_info *mpi)3450{3451 u32 port_num = mlx5_core_native_port_num(mpi->mdev) - 1;3452 struct mlx5_ib_port *port = &ibdev->port[port_num];3453 int comps;3454 int err;3455 int i;3456 3457 lockdep_assert_held(&mlx5_ib_multiport_mutex);3458 3459 mlx5_core_mp_event_replay(ibdev->mdev,3460 MLX5_DRIVER_EVENT_AFFILIATION_REMOVED,3461 NULL);3462 mlx5_core_mp_event_replay(mpi->mdev,3463 MLX5_DRIVER_EVENT_AFFILIATION_REMOVED,3464 NULL);3465 3466 mlx5_ib_cleanup_cong_debugfs(ibdev, port_num);3467 3468 spin_lock(&port->mp.mpi_lock);3469 if (!mpi->ibdev) {3470 spin_unlock(&port->mp.mpi_lock);3471 return;3472 }3473 3474 mpi->ibdev = NULL;3475 3476 spin_unlock(&port->mp.mpi_lock);3477 if (mpi->mdev_events.notifier_call)3478 mlx5_notifier_unregister(mpi->mdev, &mpi->mdev_events);3479 mpi->mdev_events.notifier_call = NULL;3480 mlx5_mdev_netdev_untrack(ibdev, port_num);3481 spin_lock(&port->mp.mpi_lock);3482 3483 comps = mpi->mdev_refcnt;3484 if (comps) {3485 mpi->unaffiliate = true;3486 init_completion(&mpi->unref_comp);3487 spin_unlock(&port->mp.mpi_lock);3488 3489 for (i = 0; i < comps; i++)3490 wait_for_completion(&mpi->unref_comp);3491 3492 spin_lock(&port->mp.mpi_lock);3493 mpi->unaffiliate = false;3494 }3495 3496 port->mp.mpi = NULL;3497 3498 spin_unlock(&port->mp.mpi_lock);3499 3500 err = mlx5_nic_vport_unaffiliate_multiport(mpi->mdev);3501 3502 mlx5_ib_dbg(ibdev, "unaffiliated port %u\n", port_num + 1);3503 /* Log an error, still needed to cleanup the pointers and add3504 * it back to the list.3505 */3506 if (err)3507 mlx5_ib_err(ibdev, "Failed to unaffiliate port %u\n",3508 port_num + 1);3509 3510 ibdev->port[port_num].roce.last_port_state = IB_PORT_DOWN;3511}3512 3513static bool mlx5_ib_bind_slave_port(struct mlx5_ib_dev *ibdev,3514 struct mlx5_ib_multiport_info *mpi)3515{3516 u32 port_num = mlx5_core_native_port_num(mpi->mdev) - 1;3517 u64 key;3518 int err;3519 3520 lockdep_assert_held(&mlx5_ib_multiport_mutex);3521 3522 spin_lock(&ibdev->port[port_num].mp.mpi_lock);3523 if (ibdev->port[port_num].mp.mpi) {3524 mlx5_ib_dbg(ibdev, "port %u already affiliated.\n",3525 port_num + 1);3526 spin_unlock(&ibdev->port[port_num].mp.mpi_lock);3527 return false;3528 }3529 3530 ibdev->port[port_num].mp.mpi = mpi;3531 mpi->ibdev = ibdev;3532 mpi->mdev_events.notifier_call = NULL;3533 spin_unlock(&ibdev->port[port_num].mp.mpi_lock);3534 3535 err = mlx5_nic_vport_affiliate_multiport(ibdev->mdev, mpi->mdev);3536 if (err)3537 goto unbind;3538 3539 mlx5_mdev_netdev_track(ibdev, port_num);3540 3541 mpi->mdev_events.notifier_call = mlx5_ib_event_slave_port;3542 mlx5_notifier_register(mpi->mdev, &mpi->mdev_events);3543 3544 mlx5_ib_init_cong_debugfs(ibdev, port_num);3545 3546 key = mpi->mdev->priv.adev_idx;3547 mlx5_core_mp_event_replay(mpi->mdev,3548 MLX5_DRIVER_EVENT_AFFILIATION_DONE,3549 &key);3550 mlx5_core_mp_event_replay(ibdev->mdev,3551 MLX5_DRIVER_EVENT_AFFILIATION_DONE,3552 &key);3553 3554 return true;3555 3556unbind:3557 mlx5_ib_unbind_slave_port(ibdev, mpi);3558 return false;3559}3560 3561static int mlx5_ib_data_direct_init(struct mlx5_ib_dev *dev)3562{3563 char vuid[MLX5_ST_SZ_BYTES(array1024_auto) + 1] = {};3564 int ret;3565 3566 if (!MLX5_CAP_GEN(dev->mdev, data_direct) ||3567 !MLX5_CAP_GEN_2(dev->mdev, query_vuid))3568 return 0;3569 3570 ret = mlx5_cmd_query_vuid(dev->mdev, true, vuid);3571 if (ret)3572 return ret;3573 3574 ret = mlx5_ib_create_data_direct_resources(dev);3575 if (ret)3576 return ret;3577 3578 INIT_LIST_HEAD(&dev->data_direct_mr_list);3579 ret = mlx5_data_direct_ib_reg(dev, vuid);3580 if (ret)3581 mlx5_ib_free_data_direct_resources(dev);3582 3583 return ret;3584}3585 3586static void mlx5_ib_data_direct_cleanup(struct mlx5_ib_dev *dev)3587{3588 if (!MLX5_CAP_GEN(dev->mdev, data_direct) ||3589 !MLX5_CAP_GEN_2(dev->mdev, query_vuid))3590 return;3591 3592 mlx5_data_direct_ib_unreg(dev);3593 mlx5_ib_free_data_direct_resources(dev);3594}3595 3596static int mlx5_ib_init_multiport_master(struct mlx5_ib_dev *dev)3597{3598 u32 port_num = mlx5_core_native_port_num(dev->mdev) - 1;3599 enum rdma_link_layer ll = mlx5_ib_port_link_layer(&dev->ib_dev,3600 port_num + 1);3601 struct mlx5_ib_multiport_info *mpi;3602 int err;3603 u32 i;3604 3605 if (!mlx5_core_is_mp_master(dev->mdev) || ll != IB_LINK_LAYER_ETHERNET)3606 return 0;3607 3608 err = mlx5_query_nic_vport_system_image_guid(dev->mdev,3609 &dev->sys_image_guid);3610 if (err)3611 return err;3612 3613 err = mlx5_nic_vport_enable_roce(dev->mdev);3614 if (err)3615 return err;3616 3617 mutex_lock(&mlx5_ib_multiport_mutex);3618 for (i = 0; i < dev->num_ports; i++) {3619 bool bound = false;3620 3621 /* build a stub multiport info struct for the native port. */3622 if (i == port_num) {3623 mpi = kzalloc(sizeof(*mpi), GFP_KERNEL);3624 if (!mpi) {3625 mutex_unlock(&mlx5_ib_multiport_mutex);3626 mlx5_nic_vport_disable_roce(dev->mdev);3627 return -ENOMEM;3628 }3629 3630 mpi->is_master = true;3631 mpi->mdev = dev->mdev;3632 mpi->sys_image_guid = dev->sys_image_guid;3633 dev->port[i].mp.mpi = mpi;3634 mpi->ibdev = dev;3635 mpi = NULL;3636 continue;3637 }3638 3639 list_for_each_entry(mpi, &mlx5_ib_unaffiliated_port_list,3640 list) {3641 if (dev->sys_image_guid == mpi->sys_image_guid &&3642 (mlx5_core_native_port_num(mpi->mdev) - 1) == i) {3643 bound = mlx5_ib_bind_slave_port(dev, mpi);3644 }3645 3646 if (bound) {3647 dev_dbg(mpi->mdev->device,3648 "removing port from unaffiliated list.\n");3649 mlx5_ib_dbg(dev, "port %d bound\n", i + 1);3650 list_del(&mpi->list);3651 break;3652 }3653 }3654 if (!bound)3655 mlx5_ib_dbg(dev, "no free port found for port %d\n",3656 i + 1);3657 }3658 3659 list_add_tail(&dev->ib_dev_list, &mlx5_ib_dev_list);3660 mutex_unlock(&mlx5_ib_multiport_mutex);3661 return err;3662}3663 3664static void mlx5_ib_cleanup_multiport_master(struct mlx5_ib_dev *dev)3665{3666 u32 port_num = mlx5_core_native_port_num(dev->mdev) - 1;3667 enum rdma_link_layer ll = mlx5_ib_port_link_layer(&dev->ib_dev,3668 port_num + 1);3669 u32 i;3670 3671 if (!mlx5_core_is_mp_master(dev->mdev) || ll != IB_LINK_LAYER_ETHERNET)3672 return;3673 3674 mutex_lock(&mlx5_ib_multiport_mutex);3675 for (i = 0; i < dev->num_ports; i++) {3676 if (dev->port[i].mp.mpi) {3677 /* Destroy the native port stub */3678 if (i == port_num) {3679 kfree(dev->port[i].mp.mpi);3680 dev->port[i].mp.mpi = NULL;3681 } else {3682 mlx5_ib_dbg(dev, "unbinding port_num: %u\n",3683 i + 1);3684 list_add_tail(&dev->port[i].mp.mpi->list,3685 &mlx5_ib_unaffiliated_port_list);3686 mlx5_ib_unbind_slave_port(dev,3687 dev->port[i].mp.mpi);3688 }3689 }3690 }3691 3692 mlx5_ib_dbg(dev, "removing from devlist\n");3693 list_del(&dev->ib_dev_list);3694 mutex_unlock(&mlx5_ib_multiport_mutex);3695 3696 mlx5_nic_vport_disable_roce(dev->mdev);3697}3698 3699static int mmap_obj_cleanup(struct ib_uobject *uobject,3700 enum rdma_remove_reason why,3701 struct uverbs_attr_bundle *attrs)3702{3703 struct mlx5_user_mmap_entry *obj = uobject->object;3704 3705 rdma_user_mmap_entry_remove(&obj->rdma_entry);3706 return 0;3707}3708 3709static int mlx5_rdma_user_mmap_entry_insert(struct mlx5_ib_ucontext *c,3710 struct mlx5_user_mmap_entry *entry,3711 size_t length)3712{3713 return rdma_user_mmap_entry_insert_range(3714 &c->ibucontext, &entry->rdma_entry, length,3715 (MLX5_IB_MMAP_OFFSET_START << 16),3716 ((MLX5_IB_MMAP_OFFSET_END << 16) + (1UL << 16) - 1));3717}3718 3719static struct mlx5_user_mmap_entry *3720alloc_var_entry(struct mlx5_ib_ucontext *c)3721{3722 struct mlx5_user_mmap_entry *entry;3723 struct mlx5_var_table *var_table;3724 u32 page_idx;3725 int err;3726 3727 var_table = &to_mdev(c->ibucontext.device)->var_table;3728 entry = kzalloc(sizeof(*entry), GFP_KERNEL);3729 if (!entry)3730 return ERR_PTR(-ENOMEM);3731 3732 mutex_lock(&var_table->bitmap_lock);3733 page_idx = find_first_zero_bit(var_table->bitmap,3734 var_table->num_var_hw_entries);3735 if (page_idx >= var_table->num_var_hw_entries) {3736 err = -ENOSPC;3737 mutex_unlock(&var_table->bitmap_lock);3738 goto end;3739 }3740 3741 set_bit(page_idx, var_table->bitmap);3742 mutex_unlock(&var_table->bitmap_lock);3743 3744 entry->address = var_table->hw_start_addr +3745 (page_idx * var_table->stride_size);3746 entry->page_idx = page_idx;3747 entry->mmap_flag = MLX5_IB_MMAP_TYPE_VAR;3748 3749 err = mlx5_rdma_user_mmap_entry_insert(c, entry,3750 var_table->stride_size);3751 if (err)3752 goto err_insert;3753 3754 return entry;3755 3756err_insert:3757 mutex_lock(&var_table->bitmap_lock);3758 clear_bit(page_idx, var_table->bitmap);3759 mutex_unlock(&var_table->bitmap_lock);3760end:3761 kfree(entry);3762 return ERR_PTR(err);3763}3764 3765static int UVERBS_HANDLER(MLX5_IB_METHOD_VAR_OBJ_ALLOC)(3766 struct uverbs_attr_bundle *attrs)3767{3768 struct ib_uobject *uobj = uverbs_attr_get_uobject(3769 attrs, MLX5_IB_ATTR_VAR_OBJ_ALLOC_HANDLE);3770 struct mlx5_ib_ucontext *c;3771 struct mlx5_user_mmap_entry *entry;3772 u64 mmap_offset;3773 u32 length;3774 int err;3775 3776 c = to_mucontext(ib_uverbs_get_ucontext(attrs));3777 if (IS_ERR(c))3778 return PTR_ERR(c);3779 3780 entry = alloc_var_entry(c);3781 if (IS_ERR(entry))3782 return PTR_ERR(entry);3783 3784 mmap_offset = mlx5_entry_to_mmap_offset(entry);3785 length = entry->rdma_entry.npages * PAGE_SIZE;3786 uobj->object = entry;3787 uverbs_finalize_uobj_create(attrs, MLX5_IB_ATTR_VAR_OBJ_ALLOC_HANDLE);3788 3789 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_VAR_OBJ_ALLOC_MMAP_OFFSET,3790 &mmap_offset, sizeof(mmap_offset));3791 if (err)3792 return err;3793 3794 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_VAR_OBJ_ALLOC_PAGE_ID,3795 &entry->page_idx, sizeof(entry->page_idx));3796 if (err)3797 return err;3798 3799 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_VAR_OBJ_ALLOC_MMAP_LENGTH,3800 &length, sizeof(length));3801 return err;3802}3803 3804DECLARE_UVERBS_NAMED_METHOD(3805 MLX5_IB_METHOD_VAR_OBJ_ALLOC,3806 UVERBS_ATTR_IDR(MLX5_IB_ATTR_VAR_OBJ_ALLOC_HANDLE,3807 MLX5_IB_OBJECT_VAR,3808 UVERBS_ACCESS_NEW,3809 UA_MANDATORY),3810 UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_VAR_OBJ_ALLOC_PAGE_ID,3811 UVERBS_ATTR_TYPE(u32),3812 UA_MANDATORY),3813 UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_VAR_OBJ_ALLOC_MMAP_LENGTH,3814 UVERBS_ATTR_TYPE(u32),3815 UA_MANDATORY),3816 UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_VAR_OBJ_ALLOC_MMAP_OFFSET,3817 UVERBS_ATTR_TYPE(u64),3818 UA_MANDATORY));3819 3820DECLARE_UVERBS_NAMED_METHOD_DESTROY(3821 MLX5_IB_METHOD_VAR_OBJ_DESTROY,3822 UVERBS_ATTR_IDR(MLX5_IB_ATTR_VAR_OBJ_DESTROY_HANDLE,3823 MLX5_IB_OBJECT_VAR,3824 UVERBS_ACCESS_DESTROY,3825 UA_MANDATORY));3826 3827DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_VAR,3828 UVERBS_TYPE_ALLOC_IDR(mmap_obj_cleanup),3829 &UVERBS_METHOD(MLX5_IB_METHOD_VAR_OBJ_ALLOC),3830 &UVERBS_METHOD(MLX5_IB_METHOD_VAR_OBJ_DESTROY));3831 3832static bool var_is_supported(struct ib_device *device)3833{3834 struct mlx5_ib_dev *dev = to_mdev(device);3835 3836 return (MLX5_CAP_GEN_64(dev->mdev, general_obj_types) &3837 MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_NET_Q);3838}3839 3840static struct mlx5_user_mmap_entry *3841alloc_uar_entry(struct mlx5_ib_ucontext *c,3842 enum mlx5_ib_uapi_uar_alloc_type alloc_type)3843{3844 struct mlx5_user_mmap_entry *entry;3845 struct mlx5_ib_dev *dev;3846 u32 uar_index;3847 int err;3848 3849 entry = kzalloc(sizeof(*entry), GFP_KERNEL);3850 if (!entry)3851 return ERR_PTR(-ENOMEM);3852 3853 dev = to_mdev(c->ibucontext.device);3854 err = mlx5_cmd_uar_alloc(dev->mdev, &uar_index, c->devx_uid);3855 if (err)3856 goto end;3857 3858 entry->page_idx = uar_index;3859 entry->address = uar_index2paddress(dev, uar_index);3860 if (alloc_type == MLX5_IB_UAPI_UAR_ALLOC_TYPE_BF)3861 entry->mmap_flag = MLX5_IB_MMAP_TYPE_UAR_WC;3862 else3863 entry->mmap_flag = MLX5_IB_MMAP_TYPE_UAR_NC;3864 3865 err = mlx5_rdma_user_mmap_entry_insert(c, entry, PAGE_SIZE);3866 if (err)3867 goto err_insert;3868 3869 return entry;3870 3871err_insert:3872 mlx5_cmd_uar_dealloc(dev->mdev, uar_index, c->devx_uid);3873end:3874 kfree(entry);3875 return ERR_PTR(err);3876}3877 3878static int UVERBS_HANDLER(MLX5_IB_METHOD_UAR_OBJ_ALLOC)(3879 struct uverbs_attr_bundle *attrs)3880{3881 struct ib_uobject *uobj = uverbs_attr_get_uobject(3882 attrs, MLX5_IB_ATTR_UAR_OBJ_ALLOC_HANDLE);3883 enum mlx5_ib_uapi_uar_alloc_type alloc_type;3884 struct mlx5_ib_ucontext *c;3885 struct mlx5_user_mmap_entry *entry;3886 u64 mmap_offset;3887 u32 length;3888 int err;3889 3890 c = to_mucontext(ib_uverbs_get_ucontext(attrs));3891 if (IS_ERR(c))3892 return PTR_ERR(c);3893 3894 err = uverbs_get_const(&alloc_type, attrs,3895 MLX5_IB_ATTR_UAR_OBJ_ALLOC_TYPE);3896 if (err)3897 return err;3898 3899 if (alloc_type != MLX5_IB_UAPI_UAR_ALLOC_TYPE_BF &&3900 alloc_type != MLX5_IB_UAPI_UAR_ALLOC_TYPE_NC)3901 return -EOPNOTSUPP;3902 3903 if (!mlx5_wc_support_get(to_mdev(c->ibucontext.device)->mdev) &&3904 alloc_type == MLX5_IB_UAPI_UAR_ALLOC_TYPE_BF)3905 return -EOPNOTSUPP;3906 3907 entry = alloc_uar_entry(c, alloc_type);3908 if (IS_ERR(entry))3909 return PTR_ERR(entry);3910 3911 mmap_offset = mlx5_entry_to_mmap_offset(entry);3912 length = entry->rdma_entry.npages * PAGE_SIZE;3913 uobj->object = entry;3914 uverbs_finalize_uobj_create(attrs, MLX5_IB_ATTR_UAR_OBJ_ALLOC_HANDLE);3915 3916 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_UAR_OBJ_ALLOC_MMAP_OFFSET,3917 &mmap_offset, sizeof(mmap_offset));3918 if (err)3919 return err;3920 3921 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_UAR_OBJ_ALLOC_PAGE_ID,3922 &entry->page_idx, sizeof(entry->page_idx));3923 if (err)3924 return err;3925 3926 err = uverbs_copy_to(attrs, MLX5_IB_ATTR_UAR_OBJ_ALLOC_MMAP_LENGTH,3927 &length, sizeof(length));3928 return err;3929}3930 3931DECLARE_UVERBS_NAMED_METHOD(3932 MLX5_IB_METHOD_UAR_OBJ_ALLOC,3933 UVERBS_ATTR_IDR(MLX5_IB_ATTR_UAR_OBJ_ALLOC_HANDLE,3934 MLX5_IB_OBJECT_UAR,3935 UVERBS_ACCESS_NEW,3936 UA_MANDATORY),3937 UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_UAR_OBJ_ALLOC_TYPE,3938 enum mlx5_ib_uapi_uar_alloc_type,3939 UA_MANDATORY),3940 UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_UAR_OBJ_ALLOC_PAGE_ID,3941 UVERBS_ATTR_TYPE(u32),3942 UA_MANDATORY),3943 UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_UAR_OBJ_ALLOC_MMAP_LENGTH,3944 UVERBS_ATTR_TYPE(u32),3945 UA_MANDATORY),3946 UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_UAR_OBJ_ALLOC_MMAP_OFFSET,3947 UVERBS_ATTR_TYPE(u64),3948 UA_MANDATORY));3949 3950DECLARE_UVERBS_NAMED_METHOD_DESTROY(3951 MLX5_IB_METHOD_UAR_OBJ_DESTROY,3952 UVERBS_ATTR_IDR(MLX5_IB_ATTR_UAR_OBJ_DESTROY_HANDLE,3953 MLX5_IB_OBJECT_UAR,3954 UVERBS_ACCESS_DESTROY,3955 UA_MANDATORY));3956 3957DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_UAR,3958 UVERBS_TYPE_ALLOC_IDR(mmap_obj_cleanup),3959 &UVERBS_METHOD(MLX5_IB_METHOD_UAR_OBJ_ALLOC),3960 &UVERBS_METHOD(MLX5_IB_METHOD_UAR_OBJ_DESTROY));3961 3962ADD_UVERBS_ATTRIBUTES_SIMPLE(3963 mlx5_ib_query_context,3964 UVERBS_OBJECT_DEVICE,3965 UVERBS_METHOD_QUERY_CONTEXT,3966 UVERBS_ATTR_PTR_OUT(3967 MLX5_IB_ATTR_QUERY_CONTEXT_RESP_UCTX,3968 UVERBS_ATTR_STRUCT(struct mlx5_ib_alloc_ucontext_resp,3969 dump_fill_mkey),3970 UA_MANDATORY));3971 3972ADD_UVERBS_ATTRIBUTES_SIMPLE(3973 mlx5_ib_reg_dmabuf_mr,3974 UVERBS_OBJECT_MR,3975 UVERBS_METHOD_REG_DMABUF_MR,3976 UVERBS_ATTR_FLAGS_IN(MLX5_IB_ATTR_REG_DMABUF_MR_ACCESS_FLAGS,3977 enum mlx5_ib_uapi_reg_dmabuf_flags,3978 UA_OPTIONAL));3979 3980static const struct uapi_definition mlx5_ib_defs[] = {3981 UAPI_DEF_CHAIN(mlx5_ib_devx_defs),3982 UAPI_DEF_CHAIN(mlx5_ib_flow_defs),3983 UAPI_DEF_CHAIN(mlx5_ib_qos_defs),3984 UAPI_DEF_CHAIN(mlx5_ib_std_types_defs),3985 UAPI_DEF_CHAIN(mlx5_ib_dm_defs),3986 UAPI_DEF_CHAIN(mlx5_ib_create_cq_defs),3987 3988 UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_DEVICE, &mlx5_ib_query_context),3989 UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_MR, &mlx5_ib_reg_dmabuf_mr),3990 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(MLX5_IB_OBJECT_VAR,3991 UAPI_DEF_IS_OBJ_SUPPORTED(var_is_supported)),3992 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(MLX5_IB_OBJECT_UAR),3993 {}3994};3995 3996static void mlx5_ib_stage_init_cleanup(struct mlx5_ib_dev *dev)3997{3998 mlx5_ib_data_direct_cleanup(dev);3999 mlx5_ib_cleanup_multiport_master(dev);4000 WARN_ON(!xa_empty(&dev->odp_mkeys));4001 mutex_destroy(&dev->cap_mask_mutex);4002 WARN_ON(!xa_empty(&dev->sig_mrs));4003 WARN_ON(!bitmap_empty(dev->dm.memic_alloc_pages, MLX5_MAX_MEMIC_PAGES));4004 mlx5r_macsec_dealloc_gids(dev);4005}4006 4007static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev)4008{4009 struct mlx5_core_dev *mdev = dev->mdev;4010 int err, i;4011 4012 dev->ib_dev.node_type = RDMA_NODE_IB_CA;4013 dev->ib_dev.local_dma_lkey = 0 /* not supported for now */;4014 dev->ib_dev.dev.parent = mdev->device;4015 dev->ib_dev.lag_flags = RDMA_LAG_FLAGS_HASH_ALL_SLAVES;4016 4017 for (i = 0; i < dev->num_ports; i++) {4018 spin_lock_init(&dev->port[i].mp.mpi_lock);4019 dev->port[i].roce.dev = dev;4020 dev->port[i].roce.native_port_num = i + 1;4021 dev->port[i].roce.last_port_state = IB_PORT_DOWN;4022 }4023 4024 err = mlx5r_cmd_query_special_mkeys(dev);4025 if (err)4026 return err;4027 4028 err = mlx5r_macsec_init_gids_and_devlist(dev);4029 if (err)4030 return err;4031 4032 err = mlx5_ib_init_multiport_master(dev);4033 if (err)4034 goto err;4035 4036 err = set_has_smi_cap(dev);4037 if (err)4038 goto err_mp;4039 4040 err = mlx5_query_max_pkeys(&dev->ib_dev, &dev->pkey_table_len);4041 if (err)4042 goto err_mp;4043 4044 if (mlx5_use_mad_ifc(dev))4045 get_ext_port_caps(dev);4046 4047 dev->ib_dev.num_comp_vectors = mlx5_comp_vectors_max(mdev);4048 4049 mutex_init(&dev->cap_mask_mutex);4050 mutex_init(&dev->data_direct_lock);4051 INIT_LIST_HEAD(&dev->qp_list);4052 spin_lock_init(&dev->reset_flow_resource_lock);4053 xa_init(&dev->odp_mkeys);4054 xa_init(&dev->sig_mrs);4055 atomic_set(&dev->mkey_var, 0);4056 4057 spin_lock_init(&dev->dm.lock);4058 dev->dm.dev = mdev;4059 err = mlx5_ib_data_direct_init(dev);4060 if (err)4061 goto err_mp;4062 4063 return 0;4064err_mp:4065 mlx5_ib_cleanup_multiport_master(dev);4066err:4067 mlx5r_macsec_dealloc_gids(dev);4068 return err;4069}4070 4071static struct ib_device *mlx5_ib_add_sub_dev(struct ib_device *parent,4072 enum rdma_nl_dev_type type,4073 const char *name);4074static void mlx5_ib_del_sub_dev(struct ib_device *sub_dev);4075 4076static const struct ib_device_ops mlx5_ib_dev_ops = {4077 .owner = THIS_MODULE,4078 .driver_id = RDMA_DRIVER_MLX5,4079 .uverbs_abi_ver = MLX5_IB_UVERBS_ABI_VERSION,4080 4081 .add_gid = mlx5_ib_add_gid,4082 .add_sub_dev = mlx5_ib_add_sub_dev,4083 .alloc_mr = mlx5_ib_alloc_mr,4084 .alloc_mr_integrity = mlx5_ib_alloc_mr_integrity,4085 .alloc_pd = mlx5_ib_alloc_pd,4086 .alloc_ucontext = mlx5_ib_alloc_ucontext,4087 .attach_mcast = mlx5_ib_mcg_attach,4088 .check_mr_status = mlx5_ib_check_mr_status,4089 .create_ah = mlx5_ib_create_ah,4090 .create_cq = mlx5_ib_create_cq,4091 .create_qp = mlx5_ib_create_qp,4092 .create_srq = mlx5_ib_create_srq,4093 .create_user_ah = mlx5_ib_create_ah,4094 .dealloc_pd = mlx5_ib_dealloc_pd,4095 .dealloc_ucontext = mlx5_ib_dealloc_ucontext,4096 .del_gid = mlx5_ib_del_gid,4097 .del_sub_dev = mlx5_ib_del_sub_dev,4098 .dereg_mr = mlx5_ib_dereg_mr,4099 .destroy_ah = mlx5_ib_destroy_ah,4100 .destroy_cq = mlx5_ib_destroy_cq,4101 .destroy_qp = mlx5_ib_destroy_qp,4102 .destroy_srq = mlx5_ib_destroy_srq,4103 .detach_mcast = mlx5_ib_mcg_detach,4104 .disassociate_ucontext = mlx5_ib_disassociate_ucontext,4105 .drain_rq = mlx5_ib_drain_rq,4106 .drain_sq = mlx5_ib_drain_sq,4107 .device_group = &mlx5_attr_group,4108 .get_dev_fw_str = get_dev_fw_str,4109 .get_dma_mr = mlx5_ib_get_dma_mr,4110 .get_link_layer = mlx5_ib_port_link_layer,4111 .map_mr_sg = mlx5_ib_map_mr_sg,4112 .map_mr_sg_pi = mlx5_ib_map_mr_sg_pi,4113 .mmap = mlx5_ib_mmap,4114 .mmap_free = mlx5_ib_mmap_free,4115 .modify_cq = mlx5_ib_modify_cq,4116 .modify_device = mlx5_ib_modify_device,4117 .modify_port = mlx5_ib_modify_port,4118 .modify_qp = mlx5_ib_modify_qp,4119 .modify_srq = mlx5_ib_modify_srq,4120 .poll_cq = mlx5_ib_poll_cq,4121 .post_recv = mlx5_ib_post_recv_nodrain,4122 .post_send = mlx5_ib_post_send_nodrain,4123 .post_srq_recv = mlx5_ib_post_srq_recv,4124 .process_mad = mlx5_ib_process_mad,4125 .query_ah = mlx5_ib_query_ah,4126 .query_device = mlx5_ib_query_device,4127 .query_gid = mlx5_ib_query_gid,4128 .query_pkey = mlx5_ib_query_pkey,4129 .query_qp = mlx5_ib_query_qp,4130 .query_srq = mlx5_ib_query_srq,4131 .query_ucontext = mlx5_ib_query_ucontext,4132 .reg_user_mr = mlx5_ib_reg_user_mr,4133 .reg_user_mr_dmabuf = mlx5_ib_reg_user_mr_dmabuf,4134 .req_notify_cq = mlx5_ib_arm_cq,4135 .rereg_user_mr = mlx5_ib_rereg_user_mr,4136 .resize_cq = mlx5_ib_resize_cq,4137 4138 INIT_RDMA_OBJ_SIZE(ib_ah, mlx5_ib_ah, ibah),4139 INIT_RDMA_OBJ_SIZE(ib_counters, mlx5_ib_mcounters, ibcntrs),4140 INIT_RDMA_OBJ_SIZE(ib_cq, mlx5_ib_cq, ibcq),4141 INIT_RDMA_OBJ_SIZE(ib_pd, mlx5_ib_pd, ibpd),4142 INIT_RDMA_OBJ_SIZE(ib_qp, mlx5_ib_qp, ibqp),4143 INIT_RDMA_OBJ_SIZE(ib_srq, mlx5_ib_srq, ibsrq),4144 INIT_RDMA_OBJ_SIZE(ib_ucontext, mlx5_ib_ucontext, ibucontext),4145};4146 4147static const struct ib_device_ops mlx5_ib_dev_ipoib_enhanced_ops = {4148 .rdma_netdev_get_params = mlx5_ib_rn_get_params,4149};4150 4151static const struct ib_device_ops mlx5_ib_dev_sriov_ops = {4152 .get_vf_config = mlx5_ib_get_vf_config,4153 .get_vf_guid = mlx5_ib_get_vf_guid,4154 .get_vf_stats = mlx5_ib_get_vf_stats,4155 .set_vf_guid = mlx5_ib_set_vf_guid,4156 .set_vf_link_state = mlx5_ib_set_vf_link_state,4157};4158 4159static const struct ib_device_ops mlx5_ib_dev_mw_ops = {4160 .alloc_mw = mlx5_ib_alloc_mw,4161 .dealloc_mw = mlx5_ib_dealloc_mw,4162 4163 INIT_RDMA_OBJ_SIZE(ib_mw, mlx5_ib_mw, ibmw),4164};4165 4166static const struct ib_device_ops mlx5_ib_dev_xrc_ops = {4167 .alloc_xrcd = mlx5_ib_alloc_xrcd,4168 .dealloc_xrcd = mlx5_ib_dealloc_xrcd,4169 4170 INIT_RDMA_OBJ_SIZE(ib_xrcd, mlx5_ib_xrcd, ibxrcd),4171};4172 4173static int mlx5_ib_init_var_table(struct mlx5_ib_dev *dev)4174{4175 struct mlx5_core_dev *mdev = dev->mdev;4176 struct mlx5_var_table *var_table = &dev->var_table;4177 u8 log_doorbell_bar_size;4178 u8 log_doorbell_stride;4179 u64 bar_size;4180 4181 log_doorbell_bar_size = MLX5_CAP_DEV_VDPA_EMULATION(mdev,4182 log_doorbell_bar_size);4183 log_doorbell_stride = MLX5_CAP_DEV_VDPA_EMULATION(mdev,4184 log_doorbell_stride);4185 var_table->hw_start_addr = dev->mdev->bar_addr +4186 MLX5_CAP64_DEV_VDPA_EMULATION(mdev,4187 doorbell_bar_offset);4188 bar_size = (1ULL << log_doorbell_bar_size) * 4096;4189 var_table->stride_size = 1ULL << log_doorbell_stride;4190 var_table->num_var_hw_entries = div_u64(bar_size,4191 var_table->stride_size);4192 mutex_init(&var_table->bitmap_lock);4193 var_table->bitmap = bitmap_zalloc(var_table->num_var_hw_entries,4194 GFP_KERNEL);4195 return (var_table->bitmap) ? 0 : -ENOMEM;4196}4197 4198static void mlx5_ib_stage_caps_cleanup(struct mlx5_ib_dev *dev)4199{4200 bitmap_free(dev->var_table.bitmap);4201}4202 4203static int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev)4204{4205 struct mlx5_core_dev *mdev = dev->mdev;4206 int err;4207 4208 if (MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads) &&4209 IS_ENABLED(CONFIG_MLX5_CORE_IPOIB))4210 ib_set_device_ops(&dev->ib_dev,4211 &mlx5_ib_dev_ipoib_enhanced_ops);4212 4213 if (mlx5_core_is_pf(mdev))4214 ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_sriov_ops);4215 4216 dev->umr_fence = mlx5_get_umr_fence(MLX5_CAP_GEN(mdev, umr_fence));4217 4218 if (MLX5_CAP_GEN(mdev, imaicl))4219 ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_mw_ops);4220 4221 if (MLX5_CAP_GEN(mdev, xrc))4222 ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_xrc_ops);4223 4224 if (MLX5_CAP_DEV_MEM(mdev, memic) ||4225 MLX5_CAP_GEN_64(dev->mdev, general_obj_types) &4226 MLX5_GENERAL_OBJ_TYPES_CAP_SW_ICM)4227 ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_dm_ops);4228 4229 ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_ops);4230 4231 if (IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS))4232 dev->ib_dev.driver_def = mlx5_ib_defs;4233 4234 err = init_node_data(dev);4235 if (err)4236 return err;4237 4238 if ((MLX5_CAP_GEN(dev->mdev, port_type) == MLX5_CAP_PORT_TYPE_ETH) &&4239 (MLX5_CAP_GEN(dev->mdev, disable_local_lb_uc) ||4240 MLX5_CAP_GEN(dev->mdev, disable_local_lb_mc)))4241 mutex_init(&dev->lb.mutex);4242 4243 if (MLX5_CAP_GEN_64(dev->mdev, general_obj_types) &4244 MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_NET_Q) {4245 err = mlx5_ib_init_var_table(dev);4246 if (err)4247 return err;4248 }4249 4250 dev->ib_dev.use_cq_dim = true;4251 4252 return 0;4253}4254 4255static const struct ib_device_ops mlx5_ib_dev_port_ops = {4256 .get_port_immutable = mlx5_port_immutable,4257 .query_port = mlx5_ib_query_port,4258};4259 4260static int mlx5_ib_stage_non_default_cb(struct mlx5_ib_dev *dev)4261{4262 ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_port_ops);4263 return 0;4264}4265 4266static const struct ib_device_ops mlx5_ib_dev_port_rep_ops = {4267 .get_port_immutable = mlx5_port_rep_immutable,4268 .query_port = mlx5_ib_rep_query_port,4269 .query_pkey = mlx5_ib_rep_query_pkey,4270};4271 4272static int mlx5_ib_stage_raw_eth_non_default_cb(struct mlx5_ib_dev *dev)4273{4274 ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_port_rep_ops);4275 return 0;4276}4277 4278static const struct ib_device_ops mlx5_ib_dev_common_roce_ops = {4279 .create_rwq_ind_table = mlx5_ib_create_rwq_ind_table,4280 .create_wq = mlx5_ib_create_wq,4281 .destroy_rwq_ind_table = mlx5_ib_destroy_rwq_ind_table,4282 .destroy_wq = mlx5_ib_destroy_wq,4283 .modify_wq = mlx5_ib_modify_wq,4284 4285 INIT_RDMA_OBJ_SIZE(ib_rwq_ind_table, mlx5_ib_rwq_ind_table,4286 ib_rwq_ind_tbl),4287};4288 4289static int mlx5_ib_roce_init(struct mlx5_ib_dev *dev)4290{4291 struct mlx5_core_dev *mdev = dev->mdev;4292 enum rdma_link_layer ll;4293 int port_type_cap;4294 u32 port_num = 0;4295 int err;4296 4297 port_type_cap = MLX5_CAP_GEN(mdev, port_type);4298 ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);4299 4300 if (ll == IB_LINK_LAYER_ETHERNET) {4301 ib_set_device_ops(&dev->ib_dev, &mlx5_ib_dev_common_roce_ops);4302 4303 port_num = mlx5_core_native_port_num(dev->mdev) - 1;4304 4305 /* Register only for native ports */4306 mlx5_mdev_netdev_track(dev, port_num);4307 4308 err = mlx5_enable_eth(dev);4309 if (err)4310 goto cleanup;4311 }4312 4313 return 0;4314cleanup:4315 mlx5_mdev_netdev_untrack(dev, port_num);4316 return err;4317}4318 4319static void mlx5_ib_roce_cleanup(struct mlx5_ib_dev *dev)4320{4321 struct mlx5_core_dev *mdev = dev->mdev;4322 enum rdma_link_layer ll;4323 int port_type_cap;4324 u32 port_num;4325 4326 port_type_cap = MLX5_CAP_GEN(mdev, port_type);4327 ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);4328 4329 if (ll == IB_LINK_LAYER_ETHERNET) {4330 mlx5_disable_eth(dev);4331 4332 port_num = mlx5_core_native_port_num(dev->mdev) - 1;4333 mlx5_mdev_netdev_untrack(dev, port_num);4334 }4335}4336 4337static int mlx5_ib_stage_cong_debugfs_init(struct mlx5_ib_dev *dev)4338{4339 mlx5_ib_init_cong_debugfs(dev,4340 mlx5_core_native_port_num(dev->mdev) - 1);4341 return 0;4342}4343 4344static void mlx5_ib_stage_cong_debugfs_cleanup(struct mlx5_ib_dev *dev)4345{4346 mlx5_ib_cleanup_cong_debugfs(dev,4347 mlx5_core_native_port_num(dev->mdev) - 1);4348}4349 4350static int mlx5_ib_stage_uar_init(struct mlx5_ib_dev *dev)4351{4352 dev->mdev->priv.uar = mlx5_get_uars_page(dev->mdev);4353 return PTR_ERR_OR_ZERO(dev->mdev->priv.uar);4354}4355 4356static void mlx5_ib_stage_uar_cleanup(struct mlx5_ib_dev *dev)4357{4358 mlx5_put_uars_page(dev->mdev, dev->mdev->priv.uar);4359}4360 4361static int mlx5_ib_stage_bfrag_init(struct mlx5_ib_dev *dev)4362{4363 int err;4364 4365 err = mlx5_alloc_bfreg(dev->mdev, &dev->bfreg, false, false);4366 if (err)4367 return err;4368 4369 err = mlx5_alloc_bfreg(dev->mdev, &dev->fp_bfreg, false, true);4370 if (err)4371 mlx5_free_bfreg(dev->mdev, &dev->bfreg);4372 4373 return err;4374}4375 4376static void mlx5_ib_stage_bfrag_cleanup(struct mlx5_ib_dev *dev)4377{4378 mlx5_free_bfreg(dev->mdev, &dev->fp_bfreg);4379 mlx5_free_bfreg(dev->mdev, &dev->bfreg);4380}4381 4382static int mlx5_ib_stage_ib_reg_init(struct mlx5_ib_dev *dev)4383{4384 const char *name;4385 4386 if (dev->sub_dev_name) {4387 name = dev->sub_dev_name;4388 ib_mark_name_assigned_by_user(&dev->ib_dev);4389 } else if (!mlx5_lag_is_active(dev->mdev))4390 name = "mlx5_%d";4391 else4392 name = "mlx5_bond_%d";4393 return ib_register_device(&dev->ib_dev, name, &dev->mdev->pdev->dev);4394}4395 4396static void mlx5_ib_stage_pre_ib_reg_umr_cleanup(struct mlx5_ib_dev *dev)4397{4398 mlx5_mkey_cache_cleanup(dev);4399 mlx5r_umr_resource_cleanup(dev);4400 mlx5r_umr_cleanup(dev);4401}4402 4403static void mlx5_ib_stage_ib_reg_cleanup(struct mlx5_ib_dev *dev)4404{4405 ib_unregister_device(&dev->ib_dev);4406}4407 4408static int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev)4409{4410 int ret;4411 4412 ret = mlx5r_umr_init(dev);4413 if (ret)4414 return ret;4415 4416 ret = mlx5_mkey_cache_init(dev);4417 if (ret)4418 mlx5_ib_warn(dev, "mr cache init failed %d\n", ret);4419 return ret;4420}4421 4422static int mlx5_ib_stage_delay_drop_init(struct mlx5_ib_dev *dev)4423{4424 struct dentry *root;4425 4426 if (!(dev->ib_dev.attrs.raw_packet_caps & IB_RAW_PACKET_CAP_DELAY_DROP))4427 return 0;4428 4429 mutex_init(&dev->delay_drop.lock);4430 dev->delay_drop.dev = dev;4431 dev->delay_drop.activate = false;4432 dev->delay_drop.timeout = MLX5_MAX_DELAY_DROP_TIMEOUT_MS * 1000;4433 INIT_WORK(&dev->delay_drop.delay_drop_work, delay_drop_handler);4434 atomic_set(&dev->delay_drop.rqs_cnt, 0);4435 atomic_set(&dev->delay_drop.events_cnt, 0);4436 4437 if (!mlx5_debugfs_root)4438 return 0;4439 4440 root = debugfs_create_dir("delay_drop", mlx5_debugfs_get_dev_root(dev->mdev));4441 dev->delay_drop.dir_debugfs = root;4442 4443 debugfs_create_atomic_t("num_timeout_events", 0400, root,4444 &dev->delay_drop.events_cnt);4445 debugfs_create_atomic_t("num_rqs", 0400, root,4446 &dev->delay_drop.rqs_cnt);4447 debugfs_create_file("timeout", 0600, root, &dev->delay_drop,4448 &fops_delay_drop_timeout);4449 return 0;4450}4451 4452static void mlx5_ib_stage_delay_drop_cleanup(struct mlx5_ib_dev *dev)4453{4454 if (!(dev->ib_dev.attrs.raw_packet_caps & IB_RAW_PACKET_CAP_DELAY_DROP))4455 return;4456 4457 cancel_work_sync(&dev->delay_drop.delay_drop_work);4458 if (!dev->delay_drop.dir_debugfs)4459 return;4460 4461 debugfs_remove_recursive(dev->delay_drop.dir_debugfs);4462 dev->delay_drop.dir_debugfs = NULL;4463}4464 4465static int mlx5_ib_stage_dev_notifier_init(struct mlx5_ib_dev *dev)4466{4467 dev->mdev_events.notifier_call = mlx5_ib_event;4468 mlx5_notifier_register(dev->mdev, &dev->mdev_events);4469 4470 mlx5r_macsec_event_register(dev);4471 4472 return 0;4473}4474 4475static void mlx5_ib_stage_dev_notifier_cleanup(struct mlx5_ib_dev *dev)4476{4477 mlx5r_macsec_event_unregister(dev);4478 mlx5_notifier_unregister(dev->mdev, &dev->mdev_events);4479}4480 4481void mlx5_ib_data_direct_bind(struct mlx5_ib_dev *ibdev,4482 struct mlx5_data_direct_dev *dev)4483{4484 mutex_lock(&ibdev->data_direct_lock);4485 ibdev->data_direct_dev = dev;4486 mutex_unlock(&ibdev->data_direct_lock);4487}4488 4489void mlx5_ib_data_direct_unbind(struct mlx5_ib_dev *ibdev)4490{4491 mutex_lock(&ibdev->data_direct_lock);4492 mlx5_ib_revoke_data_direct_mrs(ibdev);4493 ibdev->data_direct_dev = NULL;4494 mutex_unlock(&ibdev->data_direct_lock);4495}4496 4497void __mlx5_ib_remove(struct mlx5_ib_dev *dev,4498 const struct mlx5_ib_profile *profile,4499 int stage)4500{4501 dev->ib_active = false;4502 4503 /* Number of stages to cleanup */4504 while (stage) {4505 stage--;4506 if (profile->stage[stage].cleanup)4507 profile->stage[stage].cleanup(dev);4508 }4509 4510 kfree(dev->port);4511 ib_dealloc_device(&dev->ib_dev);4512}4513 4514int __mlx5_ib_add(struct mlx5_ib_dev *dev,4515 const struct mlx5_ib_profile *profile)4516{4517 int err;4518 int i;4519 4520 dev->profile = profile;4521 4522 for (i = 0; i < MLX5_IB_STAGE_MAX; i++) {4523 if (profile->stage[i].init) {4524 err = profile->stage[i].init(dev);4525 if (err)4526 goto err_out;4527 }4528 }4529 4530 dev->ib_active = true;4531 return 0;4532 4533err_out:4534 /* Clean up stages which were initialized */4535 while (i) {4536 i--;4537 if (profile->stage[i].cleanup)4538 profile->stage[i].cleanup(dev);4539 }4540 return -ENOMEM;4541}4542 4543static const struct mlx5_ib_profile pf_profile = {4544 STAGE_CREATE(MLX5_IB_STAGE_INIT,4545 mlx5_ib_stage_init_init,4546 mlx5_ib_stage_init_cleanup),4547 STAGE_CREATE(MLX5_IB_STAGE_FS,4548 mlx5_ib_fs_init,4549 mlx5_ib_fs_cleanup),4550 STAGE_CREATE(MLX5_IB_STAGE_CAPS,4551 mlx5_ib_stage_caps_init,4552 mlx5_ib_stage_caps_cleanup),4553 STAGE_CREATE(MLX5_IB_STAGE_NON_DEFAULT_CB,4554 mlx5_ib_stage_non_default_cb,4555 NULL),4556 STAGE_CREATE(MLX5_IB_STAGE_ROCE,4557 mlx5_ib_roce_init,4558 mlx5_ib_roce_cleanup),4559 STAGE_CREATE(MLX5_IB_STAGE_QP,4560 mlx5_init_qp_table,4561 mlx5_cleanup_qp_table),4562 STAGE_CREATE(MLX5_IB_STAGE_SRQ,4563 mlx5_init_srq_table,4564 mlx5_cleanup_srq_table),4565 STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,4566 mlx5_ib_dev_res_init,4567 mlx5_ib_dev_res_cleanup),4568 STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER,4569 mlx5_ib_stage_dev_notifier_init,4570 mlx5_ib_stage_dev_notifier_cleanup),4571 STAGE_CREATE(MLX5_IB_STAGE_ODP,4572 mlx5_ib_odp_init_one,4573 mlx5_ib_odp_cleanup_one),4574 STAGE_CREATE(MLX5_IB_STAGE_COUNTERS,4575 mlx5_ib_counters_init,4576 mlx5_ib_counters_cleanup),4577 STAGE_CREATE(MLX5_IB_STAGE_CONG_DEBUGFS,4578 mlx5_ib_stage_cong_debugfs_init,4579 mlx5_ib_stage_cong_debugfs_cleanup),4580 STAGE_CREATE(MLX5_IB_STAGE_UAR,4581 mlx5_ib_stage_uar_init,4582 mlx5_ib_stage_uar_cleanup),4583 STAGE_CREATE(MLX5_IB_STAGE_BFREG,4584 mlx5_ib_stage_bfrag_init,4585 mlx5_ib_stage_bfrag_cleanup),4586 STAGE_CREATE(MLX5_IB_STAGE_PRE_IB_REG_UMR,4587 NULL,4588 mlx5_ib_stage_pre_ib_reg_umr_cleanup),4589 STAGE_CREATE(MLX5_IB_STAGE_WHITELIST_UID,4590 mlx5_ib_devx_init,4591 mlx5_ib_devx_cleanup),4592 STAGE_CREATE(MLX5_IB_STAGE_IB_REG,4593 mlx5_ib_stage_ib_reg_init,4594 mlx5_ib_stage_ib_reg_cleanup),4595 STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR,4596 mlx5_ib_stage_post_ib_reg_umr_init,4597 NULL),4598 STAGE_CREATE(MLX5_IB_STAGE_DELAY_DROP,4599 mlx5_ib_stage_delay_drop_init,4600 mlx5_ib_stage_delay_drop_cleanup),4601 STAGE_CREATE(MLX5_IB_STAGE_RESTRACK,4602 mlx5_ib_restrack_init,4603 NULL),4604};4605 4606const struct mlx5_ib_profile raw_eth_profile = {4607 STAGE_CREATE(MLX5_IB_STAGE_INIT,4608 mlx5_ib_stage_init_init,4609 mlx5_ib_stage_init_cleanup),4610 STAGE_CREATE(MLX5_IB_STAGE_FS,4611 mlx5_ib_fs_init,4612 mlx5_ib_fs_cleanup),4613 STAGE_CREATE(MLX5_IB_STAGE_CAPS,4614 mlx5_ib_stage_caps_init,4615 mlx5_ib_stage_caps_cleanup),4616 STAGE_CREATE(MLX5_IB_STAGE_NON_DEFAULT_CB,4617 mlx5_ib_stage_raw_eth_non_default_cb,4618 NULL),4619 STAGE_CREATE(MLX5_IB_STAGE_ROCE,4620 mlx5_ib_roce_init,4621 mlx5_ib_roce_cleanup),4622 STAGE_CREATE(MLX5_IB_STAGE_QP,4623 mlx5_init_qp_table,4624 mlx5_cleanup_qp_table),4625 STAGE_CREATE(MLX5_IB_STAGE_SRQ,4626 mlx5_init_srq_table,4627 mlx5_cleanup_srq_table),4628 STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,4629 mlx5_ib_dev_res_init,4630 mlx5_ib_dev_res_cleanup),4631 STAGE_CREATE(MLX5_IB_STAGE_DEVICE_NOTIFIER,4632 mlx5_ib_stage_dev_notifier_init,4633 mlx5_ib_stage_dev_notifier_cleanup),4634 STAGE_CREATE(MLX5_IB_STAGE_COUNTERS,4635 mlx5_ib_counters_init,4636 mlx5_ib_counters_cleanup),4637 STAGE_CREATE(MLX5_IB_STAGE_CONG_DEBUGFS,4638 mlx5_ib_stage_cong_debugfs_init,4639 mlx5_ib_stage_cong_debugfs_cleanup),4640 STAGE_CREATE(MLX5_IB_STAGE_UAR,4641 mlx5_ib_stage_uar_init,4642 mlx5_ib_stage_uar_cleanup),4643 STAGE_CREATE(MLX5_IB_STAGE_BFREG,4644 mlx5_ib_stage_bfrag_init,4645 mlx5_ib_stage_bfrag_cleanup),4646 STAGE_CREATE(MLX5_IB_STAGE_PRE_IB_REG_UMR,4647 NULL,4648 mlx5_ib_stage_pre_ib_reg_umr_cleanup),4649 STAGE_CREATE(MLX5_IB_STAGE_WHITELIST_UID,4650 mlx5_ib_devx_init,4651 mlx5_ib_devx_cleanup),4652 STAGE_CREATE(MLX5_IB_STAGE_IB_REG,4653 mlx5_ib_stage_ib_reg_init,4654 mlx5_ib_stage_ib_reg_cleanup),4655 STAGE_CREATE(MLX5_IB_STAGE_POST_IB_REG_UMR,4656 mlx5_ib_stage_post_ib_reg_umr_init,4657 NULL),4658 STAGE_CREATE(MLX5_IB_STAGE_DELAY_DROP,4659 mlx5_ib_stage_delay_drop_init,4660 mlx5_ib_stage_delay_drop_cleanup),4661 STAGE_CREATE(MLX5_IB_STAGE_RESTRACK,4662 mlx5_ib_restrack_init,4663 NULL),4664};4665 4666static const struct mlx5_ib_profile plane_profile = {4667 STAGE_CREATE(MLX5_IB_STAGE_INIT,4668 mlx5_ib_stage_init_init,4669 mlx5_ib_stage_init_cleanup),4670 STAGE_CREATE(MLX5_IB_STAGE_CAPS,4671 mlx5_ib_stage_caps_init,4672 mlx5_ib_stage_caps_cleanup),4673 STAGE_CREATE(MLX5_IB_STAGE_NON_DEFAULT_CB,4674 mlx5_ib_stage_non_default_cb,4675 NULL),4676 STAGE_CREATE(MLX5_IB_STAGE_QP,4677 mlx5_init_qp_table,4678 mlx5_cleanup_qp_table),4679 STAGE_CREATE(MLX5_IB_STAGE_SRQ,4680 mlx5_init_srq_table,4681 mlx5_cleanup_srq_table),4682 STAGE_CREATE(MLX5_IB_STAGE_DEVICE_RESOURCES,4683 mlx5_ib_dev_res_init,4684 mlx5_ib_dev_res_cleanup),4685 STAGE_CREATE(MLX5_IB_STAGE_BFREG,4686 mlx5_ib_stage_bfrag_init,4687 mlx5_ib_stage_bfrag_cleanup),4688 STAGE_CREATE(MLX5_IB_STAGE_IB_REG,4689 mlx5_ib_stage_ib_reg_init,4690 mlx5_ib_stage_ib_reg_cleanup),4691};4692 4693static struct ib_device *mlx5_ib_add_sub_dev(struct ib_device *parent,4694 enum rdma_nl_dev_type type,4695 const char *name)4696{4697 struct mlx5_ib_dev *mparent = to_mdev(parent), *mplane;4698 enum rdma_link_layer ll;4699 int ret;4700 4701 if (mparent->smi_dev)4702 return ERR_PTR(-EEXIST);4703 4704 ll = mlx5_port_type_cap_to_rdma_ll(MLX5_CAP_GEN(mparent->mdev,4705 port_type));4706 if (type != RDMA_DEVICE_TYPE_SMI || !mparent->num_plane ||4707 ll != IB_LINK_LAYER_INFINIBAND ||4708 !MLX5_CAP_GEN_2(mparent->mdev, multiplane_qp_ud))4709 return ERR_PTR(-EOPNOTSUPP);4710 4711 mplane = ib_alloc_device(mlx5_ib_dev, ib_dev);4712 if (!mplane)4713 return ERR_PTR(-ENOMEM);4714 4715 mplane->port = kcalloc(mparent->num_plane * mparent->num_ports,4716 sizeof(*mplane->port), GFP_KERNEL);4717 if (!mplane->port) {4718 ret = -ENOMEM;4719 goto fail_kcalloc;4720 }4721 4722 mplane->ib_dev.type = type;4723 mplane->mdev = mparent->mdev;4724 mplane->num_ports = mparent->num_plane;4725 mplane->sub_dev_name = name;4726 mplane->ib_dev.phys_port_cnt = mplane->num_ports;4727 4728 ret = __mlx5_ib_add(mplane, &plane_profile);4729 if (ret)4730 goto fail_ib_add;4731 4732 mparent->smi_dev = mplane;4733 return &mplane->ib_dev;4734 4735fail_ib_add:4736 kfree(mplane->port);4737fail_kcalloc:4738 ib_dealloc_device(&mplane->ib_dev);4739 return ERR_PTR(ret);4740}4741 4742static void mlx5_ib_del_sub_dev(struct ib_device *sub_dev)4743{4744 struct mlx5_ib_dev *mdev = to_mdev(sub_dev);4745 4746 to_mdev(sub_dev->parent)->smi_dev = NULL;4747 __mlx5_ib_remove(mdev, mdev->profile, MLX5_IB_STAGE_MAX);4748}4749 4750static int mlx5r_mp_probe(struct auxiliary_device *adev,4751 const struct auxiliary_device_id *id)4752{4753 struct mlx5_adev *idev = container_of(adev, struct mlx5_adev, adev);4754 struct mlx5_core_dev *mdev = idev->mdev;4755 struct mlx5_ib_multiport_info *mpi;4756 struct mlx5_ib_dev *dev;4757 bool bound = false;4758 int err;4759 4760 mpi = kzalloc(sizeof(*mpi), GFP_KERNEL);4761 if (!mpi)4762 return -ENOMEM;4763 4764 mpi->mdev = mdev;4765 err = mlx5_query_nic_vport_system_image_guid(mdev,4766 &mpi->sys_image_guid);4767 if (err) {4768 kfree(mpi);4769 return err;4770 }4771 4772 mutex_lock(&mlx5_ib_multiport_mutex);4773 list_for_each_entry(dev, &mlx5_ib_dev_list, ib_dev_list) {4774 if (dev->sys_image_guid == mpi->sys_image_guid)4775 bound = mlx5_ib_bind_slave_port(dev, mpi);4776 4777 if (bound) {4778 rdma_roce_rescan_device(&dev->ib_dev);4779 mpi->ibdev->ib_active = true;4780 break;4781 }4782 }4783 4784 if (!bound) {4785 list_add_tail(&mpi->list, &mlx5_ib_unaffiliated_port_list);4786 dev_dbg(mdev->device,4787 "no suitable IB device found to bind to, added to unaffiliated list.\n");4788 }4789 mutex_unlock(&mlx5_ib_multiport_mutex);4790 4791 auxiliary_set_drvdata(adev, mpi);4792 return 0;4793}4794 4795static void mlx5r_mp_remove(struct auxiliary_device *adev)4796{4797 struct mlx5_ib_multiport_info *mpi;4798 4799 mpi = auxiliary_get_drvdata(adev);4800 mutex_lock(&mlx5_ib_multiport_mutex);4801 if (mpi->ibdev)4802 mlx5_ib_unbind_slave_port(mpi->ibdev, mpi);4803 else4804 list_del(&mpi->list);4805 mutex_unlock(&mlx5_ib_multiport_mutex);4806 kfree(mpi);4807}4808 4809static int mlx5r_probe(struct auxiliary_device *adev,4810 const struct auxiliary_device_id *id)4811{4812 struct mlx5_adev *idev = container_of(adev, struct mlx5_adev, adev);4813 struct mlx5_core_dev *mdev = idev->mdev;4814 const struct mlx5_ib_profile *profile;4815 int port_type_cap, num_ports, ret;4816 enum rdma_link_layer ll;4817 struct mlx5_ib_dev *dev;4818 4819 port_type_cap = MLX5_CAP_GEN(mdev, port_type);4820 ll = mlx5_port_type_cap_to_rdma_ll(port_type_cap);4821 4822 num_ports = max(MLX5_CAP_GEN(mdev, num_ports),4823 MLX5_CAP_GEN(mdev, num_vhca_ports));4824 dev = ib_alloc_device(mlx5_ib_dev, ib_dev);4825 if (!dev)4826 return -ENOMEM;4827 4828 if (ll == IB_LINK_LAYER_INFINIBAND) {4829 ret = mlx5_ib_get_plane_num(mdev, &dev->num_plane);4830 if (ret)4831 goto fail;4832 }4833 4834 dev->port = kcalloc(num_ports, sizeof(*dev->port),4835 GFP_KERNEL);4836 if (!dev->port) {4837 ret = -ENOMEM;4838 goto fail;4839 }4840 4841 dev->mdev = mdev;4842 dev->num_ports = num_ports;4843 dev->ib_dev.phys_port_cnt = num_ports;4844 4845 if (ll == IB_LINK_LAYER_ETHERNET && !mlx5_get_roce_state(mdev))4846 profile = &raw_eth_profile;4847 else4848 profile = &pf_profile;4849 4850 ret = __mlx5_ib_add(dev, profile);4851 if (ret)4852 goto fail_ib_add;4853 4854 auxiliary_set_drvdata(adev, dev);4855 return 0;4856 4857fail_ib_add:4858 kfree(dev->port);4859fail:4860 ib_dealloc_device(&dev->ib_dev);4861 return ret;4862}4863 4864static void mlx5r_remove(struct auxiliary_device *adev)4865{4866 struct mlx5_ib_dev *dev;4867 4868 dev = auxiliary_get_drvdata(adev);4869 __mlx5_ib_remove(dev, dev->profile, MLX5_IB_STAGE_MAX);4870}4871 4872static const struct auxiliary_device_id mlx5r_mp_id_table[] = {4873 { .name = MLX5_ADEV_NAME ".multiport", },4874 {},4875};4876 4877static const struct auxiliary_device_id mlx5r_id_table[] = {4878 { .name = MLX5_ADEV_NAME ".rdma", },4879 {},4880};4881 4882MODULE_DEVICE_TABLE(auxiliary, mlx5r_mp_id_table);4883MODULE_DEVICE_TABLE(auxiliary, mlx5r_id_table);4884 4885static struct auxiliary_driver mlx5r_mp_driver = {4886 .name = "multiport",4887 .probe = mlx5r_mp_probe,4888 .remove = mlx5r_mp_remove,4889 .id_table = mlx5r_mp_id_table,4890};4891 4892static struct auxiliary_driver mlx5r_driver = {4893 .name = "rdma",4894 .probe = mlx5r_probe,4895 .remove = mlx5r_remove,4896 .id_table = mlx5r_id_table,4897};4898 4899static int __init mlx5_ib_init(void)4900{4901 int ret;4902 4903 xlt_emergency_page = (void *)__get_free_page(GFP_KERNEL);4904 if (!xlt_emergency_page)4905 return -ENOMEM;4906 4907 mlx5_ib_event_wq = alloc_ordered_workqueue("mlx5_ib_event_wq", 0);4908 if (!mlx5_ib_event_wq) {4909 free_page((unsigned long)xlt_emergency_page);4910 return -ENOMEM;4911 }4912 4913 ret = mlx5_ib_qp_event_init();4914 if (ret)4915 goto qp_event_err;4916 4917 mlx5_ib_odp_init();4918 ret = mlx5r_rep_init();4919 if (ret)4920 goto rep_err;4921 ret = mlx5_data_direct_driver_register();4922 if (ret)4923 goto dd_err;4924 ret = auxiliary_driver_register(&mlx5r_mp_driver);4925 if (ret)4926 goto mp_err;4927 ret = auxiliary_driver_register(&mlx5r_driver);4928 if (ret)4929 goto drv_err;4930 4931 return 0;4932 4933drv_err:4934 auxiliary_driver_unregister(&mlx5r_mp_driver);4935mp_err:4936 mlx5_data_direct_driver_unregister();4937dd_err:4938 mlx5r_rep_cleanup();4939rep_err:4940 mlx5_ib_qp_event_cleanup();4941qp_event_err:4942 destroy_workqueue(mlx5_ib_event_wq);4943 free_page((unsigned long)xlt_emergency_page);4944 return ret;4945}4946 4947static void __exit mlx5_ib_cleanup(void)4948{4949 mlx5_data_direct_driver_unregister();4950 auxiliary_driver_unregister(&mlx5r_driver);4951 auxiliary_driver_unregister(&mlx5r_mp_driver);4952 mlx5r_rep_cleanup();4953 4954 mlx5_ib_qp_event_cleanup();4955 destroy_workqueue(mlx5_ib_event_wq);4956 free_page((unsigned long)xlt_emergency_page);4957}4958 4959module_init(mlx5_ib_init);4960module_exit(mlx5_ib_cleanup);4961