1219820Sjeff/* 2219820Sjeff * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved. 3219820Sjeff * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved. 4219820Sjeff * 5219820Sjeff * This software is available to you under a choice of one of two 6219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 7219820Sjeff * General Public License (GPL) Version 2, available from the file 8219820Sjeff * COPYING in the main directory of this source tree, or the 9219820Sjeff * OpenIB.org BSD license below: 10219820Sjeff * 11219820Sjeff * Redistribution and use in source and binary forms, with or 12219820Sjeff * without modification, are permitted provided that the following 13219820Sjeff * conditions are met: 14219820Sjeff * 15219820Sjeff * - Redistributions of source code must retain the above 16219820Sjeff * copyright notice, this list of conditions and the following 17219820Sjeff * disclaimer. 18219820Sjeff * 19219820Sjeff * - Redistributions in binary form must reproduce the above 20219820Sjeff * copyright notice, this list of conditions and the following 21219820Sjeff * disclaimer in the documentation and/or other materials 22219820Sjeff * provided with the distribution. 23219820Sjeff * 24219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31219820Sjeff * SOFTWARE. 32219820Sjeff */ 33219820Sjeff 34219820Sjeff#include <linux/module.h> 35219820Sjeff#include <linux/init.h> 36219820Sjeff#include <linux/errno.h> 37219820Sjeff#include <linux/netdevice.h> 38219820Sjeff#include <linux/inetdevice.h> 39219820Sjeff#include <linux/rtnetlink.h> 40219820Sjeff#include <linux/if_vlan.h> 41219820Sjeff 42219820Sjeff#include <rdma/ib_smi.h> 43219820Sjeff#include <rdma/ib_user_verbs.h> 44219820Sjeff#include <rdma/ib_addr.h> 45219820Sjeff 46219820Sjeff#include <linux/mlx4/driver.h> 47219820Sjeff#include <linux/mlx4/cmd.h> 48219820Sjeff 49219820Sjeff#include "mlx4_ib.h" 50219820Sjeff#include "user.h" 51219820Sjeff#include "wc.h" 52219820Sjeff 53219820Sjeff#define DRV_NAME MLX4_IB_DRV_NAME 54219820Sjeff#define DRV_VERSION "1.0-ofed1.5.2" 55219820Sjeff#define DRV_RELDATE "August 4, 2010" 56219820Sjeff 57219820SjeffMODULE_AUTHOR("Roland Dreier"); 58219820SjeffMODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver"); 59219820SjeffMODULE_LICENSE("Dual BSD/GPL"); 60219820SjeffMODULE_VERSION(DRV_VERSION); 61219820Sjeff 62219820Sjeff#ifdef CONFIG_MLX4_DEBUG 63219820Sjeff 64219820Sjeffint mlx4_ib_debug_level = 0; 65219820Sjeffmodule_param_named(debug_level, mlx4_ib_debug_level, int, 0644); 66219820SjeffMODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0"); 67219820Sjeff 68219820Sjeff#endif /* CONFIG_MLX4_DEBUG */ 69219820Sjeff 70219820Sjeffstatic const char mlx4_ib_version[] = 71219820Sjeff DRV_NAME ": Mellanox ConnectX InfiniBand driver v" 72219820Sjeff DRV_VERSION " (" DRV_RELDATE ")\n"; 73219820Sjeff 74219820Sjeffstatic void *get_ibdev(struct mlx4_dev *dev, void *ctx, u8 port) 75219820Sjeff{ 76219820Sjeff struct mlx4_ib_dev *mlxibdev = ctx; 77219820Sjeff return &mlxibdev->ib_dev; 78219820Sjeff} 79219820Sjeff 80219820Sjeffstruct update_gid_work { 81219820Sjeff struct work_struct work; 82219820Sjeff union ib_gid gids[128]; 83219820Sjeff int port; 84219820Sjeff struct mlx4_ib_dev *dev; 85219820Sjeff}; 86219820Sjeff 87219820Sjeffstatic struct workqueue_struct *wq; 88219820Sjeff 89219820Sjeffstatic void init_query_mad(struct ib_smp *mad) 90219820Sjeff{ 91219820Sjeff mad->base_version = 1; 92219820Sjeff mad->mgmt_class = IB_MGMT_CLASS_SUBN_LID_ROUTED; 93219820Sjeff mad->class_version = 1; 94219820Sjeff mad->method = IB_MGMT_METHOD_GET; 95219820Sjeff} 96219820Sjeff 97219820Sjeffstatic union ib_gid zgid; 98219820Sjeff 99219820Sjeffstatic int mlx4_ib_query_device(struct ib_device *ibdev, 100219820Sjeff struct ib_device_attr *props) 101219820Sjeff{ 102219820Sjeff struct mlx4_ib_dev *dev = to_mdev(ibdev); 103219820Sjeff struct ib_smp *in_mad = NULL; 104219820Sjeff struct ib_smp *out_mad = NULL; 105219820Sjeff int err = -ENOMEM; 106219820Sjeff 107219820Sjeff in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); 108219820Sjeff out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); 109219820Sjeff if (!in_mad || !out_mad) 110219820Sjeff goto out; 111219820Sjeff 112219820Sjeff init_query_mad(in_mad); 113219820Sjeff in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; 114219820Sjeff 115219820Sjeff err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, 1, NULL, NULL, in_mad, out_mad); 116219820Sjeff if (err) 117219820Sjeff goto out; 118219820Sjeff 119219820Sjeff memset(props, 0, sizeof *props); 120219820Sjeff 121219820Sjeff props->fw_ver = dev->dev->caps.fw_ver; 122219820Sjeff props->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT | 123219820Sjeff IB_DEVICE_PORT_ACTIVE_EVENT | 124219820Sjeff IB_DEVICE_SYS_IMAGE_GUID | 125219820Sjeff IB_DEVICE_RC_RNR_NAK_GEN | 126219820Sjeff IB_DEVICE_BLOCK_MULTICAST_LOOPBACK; 127219820Sjeff if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR) 128219820Sjeff props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR; 129219820Sjeff if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_QKEY_CNTR) 130219820Sjeff props->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR; 131219820Sjeff if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_APM) 132219820Sjeff props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG; 133219820Sjeff if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UD_AV_PORT) 134219820Sjeff props->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE; 135219820Sjeff if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM) 136219820Sjeff props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM; 137219820Sjeff if (dev->dev->caps.max_gso_sz && dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BLH) 138219820Sjeff props->device_cap_flags |= IB_DEVICE_UD_TSO; 139219820Sjeff if (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_RESERVED_LKEY) 140219820Sjeff props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY; 141219820Sjeff if ((dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_LOCAL_INV) && 142219820Sjeff (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_REMOTE_INV) && 143219820Sjeff (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_FAST_REG_WR)) 144219820Sjeff props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS; 145219820Sjeff if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) 146219820Sjeff props->device_cap_flags |= IB_DEVICE_XRC; 147219820Sjeff if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_RAW_ETY) 148219820Sjeff props->max_raw_ethy_qp = dev->ib_dev.phys_port_cnt; 149219820Sjeff 150219820Sjeff props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) & 151219820Sjeff 0xffffff; 152219820Sjeff props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); 153219820Sjeff props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); 154219820Sjeff memcpy(&props->sys_image_guid, out_mad->data + 4, 8); 155219820Sjeff 156219820Sjeff props->max_mr_size = ~0ull; 157219820Sjeff props->page_size_cap = dev->dev->caps.page_size_cap; 158219820Sjeff props->max_qp = dev->dev->caps.num_qps - dev->dev->caps.reserved_qps; 159219820Sjeff props->max_qp_wr = dev->dev->caps.max_wqes - MLX4_IB_SQ_MAX_SPARE; 160219820Sjeff props->max_sge = min(dev->dev->caps.max_sq_sg, 161219820Sjeff dev->dev->caps.max_rq_sg); 162219820Sjeff props->max_cq = dev->dev->caps.num_cqs - dev->dev->caps.reserved_cqs; 163219820Sjeff props->max_cqe = dev->dev->caps.max_cqes; 164219820Sjeff props->max_mr = dev->dev->caps.num_mpts - dev->dev->caps.reserved_mrws; 165219820Sjeff props->max_pd = dev->dev->caps.num_pds - dev->dev->caps.reserved_pds; 166219820Sjeff props->max_qp_rd_atom = dev->dev->caps.max_qp_dest_rdma; 167219820Sjeff props->max_qp_init_rd_atom = dev->dev->caps.max_qp_init_rdma; 168219820Sjeff props->max_res_rd_atom = props->max_qp_rd_atom * props->max_qp; 169219820Sjeff props->max_srq = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs; 170219820Sjeff props->max_srq_wr = dev->dev->caps.max_srq_wqes - 1; 171219820Sjeff props->max_srq_sge = dev->dev->caps.max_srq_sge; 172219820Sjeff props->max_fast_reg_page_list_len = MAX_FAST_REG_PAGES; 173219820Sjeff props->local_ca_ack_delay = dev->dev->caps.local_ca_ack_delay; 174219820Sjeff props->atomic_cap = dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_ATOMIC ? 175219820Sjeff IB_ATOMIC_HCA : IB_ATOMIC_NONE; 176219820Sjeff props->masked_atomic_cap = IB_ATOMIC_HCA; 177219820Sjeff props->max_pkeys = dev->dev->caps.pkey_table_len[1]; 178219820Sjeff props->max_mcast_grp = dev->dev->caps.num_mgms + dev->dev->caps.num_amgms; 179219820Sjeff props->max_mcast_qp_attach = dev->dev->caps.num_qp_per_mgm; 180219820Sjeff props->max_total_mcast_qp_attach = props->max_mcast_qp_attach * 181219820Sjeff props->max_mcast_grp; 182219820Sjeff props->max_map_per_fmr = (1 << (32 - ilog2(dev->dev->caps.num_mpts))) - 1; 183219820Sjeff 184219820Sjeffout: 185219820Sjeff kfree(in_mad); 186219820Sjeff kfree(out_mad); 187219820Sjeff 188219820Sjeff return err; 189219820Sjeff} 190219820Sjeff 191219820Sjeffstatic enum rdma_link_layer 192219820Sjeffmlx4_ib_port_link_layer(struct ib_device *device, u8 port_num) 193219820Sjeff{ 194219820Sjeff struct mlx4_dev *dev = to_mdev(device)->dev; 195219820Sjeff 196219820Sjeff return dev->caps.port_mask[port_num] == MLX4_PORT_TYPE_IB ? 197219820Sjeff IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET; 198219820Sjeff} 199219820Sjeff 200219820Sjeffstatic void ib_link_query_port(struct ib_device *ibdev, u8 port, 201219820Sjeff struct ib_port_attr *props, 202219820Sjeff struct ib_smp *out_mad) 203219820Sjeff{ 204219820Sjeff props->lid = be16_to_cpup((__be16 *) (out_mad->data + 16)); 205219820Sjeff props->lmc = out_mad->data[34] & 0x7; 206219820Sjeff props->sm_lid = be16_to_cpup((__be16 *) (out_mad->data + 18)); 207219820Sjeff props->sm_sl = out_mad->data[36] & 0xf; 208219820Sjeff props->state = out_mad->data[32] & 0xf; 209219820Sjeff props->phys_state = out_mad->data[33] >> 4; 210219820Sjeff props->port_cap_flags = be32_to_cpup((__be32 *) (out_mad->data + 20)); 211219820Sjeff props->gid_tbl_len = to_mdev(ibdev)->dev->caps.gid_table_len[port]; 212219820Sjeff props->max_msg_sz = to_mdev(ibdev)->dev->caps.max_msg_sz; 213219820Sjeff props->pkey_tbl_len = to_mdev(ibdev)->dev->caps.pkey_table_len[port]; 214219820Sjeff props->bad_pkey_cntr = be16_to_cpup((__be16 *) (out_mad->data + 46)); 215219820Sjeff props->qkey_viol_cntr = be16_to_cpup((__be16 *) (out_mad->data + 48)); 216219820Sjeff props->active_width = out_mad->data[31] & 0xf; 217219820Sjeff props->active_speed = out_mad->data[35] >> 4; 218219820Sjeff props->max_mtu = out_mad->data[41] & 0xf; 219219820Sjeff props->active_mtu = out_mad->data[36] >> 4; 220219820Sjeff props->subnet_timeout = out_mad->data[51] & 0x1f; 221219820Sjeff props->max_vl_num = out_mad->data[37] >> 4; 222219820Sjeff props->init_type_reply = out_mad->data[41] >> 4; 223219820Sjeff props->link_layer = IB_LINK_LAYER_INFINIBAND; 224219820Sjeff} 225219820Sjeff 226219820Sjeff#ifdef notyet 227219820Sjeffstatic int eth_to_ib_width(int w) 228219820Sjeff{ 229219820Sjeff switch (w) { 230219820Sjeff case 4: 231219820Sjeff return IB_WIDTH_4X; 232219820Sjeff case 8: 233219820Sjeff case 16: 234219820Sjeff return IB_WIDTH_8X; 235219820Sjeff case 32: 236219820Sjeff return IB_WIDTH_12X; 237219820Sjeff default: 238219820Sjeff return IB_WIDTH_1X; 239219820Sjeff } 240219820Sjeff} 241219820Sjeff 242219820Sjeffstatic int eth_to_ib_speed(int s) 243219820Sjeff{ 244219820Sjeff switch (s) { 245219820Sjeff case 256: 246219820Sjeff return 1; 247219820Sjeff case 512: 248219820Sjeff return 2; 249219820Sjeff case 1024: 250219820Sjeff return 4; 251219820Sjeff default: 252219820Sjeff return 1; 253219820Sjeff } 254219820Sjeff} 255219820Sjeff#endif 256219820Sjeff 257219820Sjeffstatic u8 state_to_phys_state(enum ib_port_state state) 258219820Sjeff{ 259219820Sjeff return state == IB_PORT_ACTIVE ? 5 : 3; 260219820Sjeff} 261219820Sjeff 262219820Sjeffstatic int eth_link_query_port(struct ib_device *ibdev, u8 port, 263219820Sjeff struct ib_port_attr *props, 264219820Sjeff struct ib_smp *out_mad) 265219820Sjeff{ 266219820Sjeff struct mlx4_ib_iboe *iboe = &to_mdev(ibdev)->iboe; 267219820Sjeff struct net_device *ndev; 268219820Sjeff enum ib_mtu tmp; 269219820Sjeff 270219820Sjeff props->active_width = IB_WIDTH_4X; 271219820Sjeff props->active_speed = 1; 272219820Sjeff props->port_cap_flags = IB_PORT_CM_SUP; 273219820Sjeff props->gid_tbl_len = to_mdev(ibdev)->dev->caps.gid_table_len[port]; 274219820Sjeff props->max_msg_sz = to_mdev(ibdev)->dev->caps.max_msg_sz; 275219820Sjeff props->pkey_tbl_len = 1; 276219820Sjeff props->bad_pkey_cntr = be16_to_cpup((__be16 *) (out_mad->data + 46)); 277219820Sjeff props->qkey_viol_cntr = be16_to_cpup((__be16 *) (out_mad->data + 48)); 278219820Sjeff props->max_mtu = IB_MTU_2048; 279219820Sjeff props->subnet_timeout = 0; 280219820Sjeff props->max_vl_num = out_mad->data[37] >> 4; 281219820Sjeff props->init_type_reply = 0; 282219820Sjeff props->link_layer = IB_LINK_LAYER_ETHERNET; 283219820Sjeff props->state = IB_PORT_DOWN; 284219820Sjeff props->phys_state = state_to_phys_state(props->state); 285219820Sjeff props->active_mtu = IB_MTU_256; 286219820Sjeff spin_lock(&iboe->lock); 287219820Sjeff ndev = iboe->netdevs[port - 1]; 288219820Sjeff if (!ndev) 289219820Sjeff goto out; 290219820Sjeff 291219820Sjeff#ifdef __linux__ 292219820Sjeff tmp = iboe_get_mtu(ndev->mtu); 293219820Sjeff#else 294219820Sjeff tmp = iboe_get_mtu(ndev->if_mtu); 295219820Sjeff#endif 296219820Sjeff props->active_mtu = tmp ? min(props->max_mtu, tmp) : IB_MTU_256; 297219820Sjeff props->state = netif_carrier_ok(ndev) && netif_oper_up(ndev) ? 298219820Sjeff IB_PORT_ACTIVE : IB_PORT_DOWN; 299219820Sjeff props->phys_state = state_to_phys_state(props->state); 300219820Sjeff 301219820Sjeffout: 302219820Sjeff spin_unlock(&iboe->lock); 303219820Sjeff return 0; 304219820Sjeff} 305219820Sjeff 306219820Sjeffstatic int mlx4_ib_query_port(struct ib_device *ibdev, u8 port, 307219820Sjeff struct ib_port_attr *props) 308219820Sjeff{ 309219820Sjeff struct ib_smp *in_mad = NULL; 310219820Sjeff struct ib_smp *out_mad = NULL; 311219820Sjeff int err = -ENOMEM; 312219820Sjeff 313219820Sjeff in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); 314219820Sjeff out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); 315219820Sjeff if (!in_mad || !out_mad) 316219820Sjeff goto out; 317219820Sjeff 318219820Sjeff memset(props, 0, sizeof *props); 319219820Sjeff 320219820Sjeff init_query_mad(in_mad); 321219820Sjeff in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; 322219820Sjeff in_mad->attr_mod = cpu_to_be32(port); 323219820Sjeff 324219820Sjeff err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); 325219820Sjeff if (err) 326219820Sjeff goto out; 327219820Sjeff 328219820Sjeff mlx4_ib_port_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND ? 329219820Sjeff ib_link_query_port(ibdev, port, props, out_mad) : 330219820Sjeff eth_link_query_port(ibdev, port, props, out_mad); 331219820Sjeff 332219820Sjeffout: 333219820Sjeff kfree(in_mad); 334219820Sjeff kfree(out_mad); 335219820Sjeff 336219820Sjeff return err; 337219820Sjeff} 338219820Sjeff 339219820Sjeffstatic int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index, 340219820Sjeff union ib_gid *gid) 341219820Sjeff{ 342219820Sjeff struct ib_smp *in_mad = NULL; 343219820Sjeff struct ib_smp *out_mad = NULL; 344219820Sjeff int err = -ENOMEM; 345219820Sjeff 346219820Sjeff in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); 347219820Sjeff out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); 348219820Sjeff if (!in_mad || !out_mad) 349219820Sjeff goto out; 350219820Sjeff 351219820Sjeff init_query_mad(in_mad); 352219820Sjeff in_mad->attr_id = IB_SMP_ATTR_PORT_INFO; 353219820Sjeff in_mad->attr_mod = cpu_to_be32(port); 354219820Sjeff 355219820Sjeff err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); 356219820Sjeff if (err) 357219820Sjeff goto out; 358219820Sjeff 359219820Sjeff memcpy(gid->raw, out_mad->data + 8, 8); 360219820Sjeff 361219820Sjeff init_query_mad(in_mad); 362219820Sjeff in_mad->attr_id = IB_SMP_ATTR_GUID_INFO; 363219820Sjeff in_mad->attr_mod = cpu_to_be32(index / 8); 364219820Sjeff 365219820Sjeff err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); 366219820Sjeff if (err) 367219820Sjeff goto out; 368219820Sjeff 369219820Sjeff memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8); 370219820Sjeff 371219820Sjeffout: 372219820Sjeff kfree(in_mad); 373219820Sjeff kfree(out_mad); 374219820Sjeff return err; 375219820Sjeff} 376219820Sjeff 377219820Sjeffstatic int iboe_query_gid(struct ib_device *ibdev, u8 port, int index, 378219820Sjeff union ib_gid *gid) 379219820Sjeff{ 380219820Sjeff struct mlx4_ib_dev *dev = to_mdev(ibdev); 381219820Sjeff 382219820Sjeff *gid = dev->iboe.gid_table[port - 1][index]; 383219820Sjeff 384219820Sjeff return 0; 385219820Sjeff} 386219820Sjeff 387219820Sjeffstatic int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index, 388219820Sjeff union ib_gid *gid) 389219820Sjeff{ 390219820Sjeff if (rdma_port_get_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND) 391219820Sjeff return __mlx4_ib_query_gid(ibdev, port, index, gid); 392219820Sjeff else 393219820Sjeff return iboe_query_gid(ibdev, port, index, gid); 394219820Sjeff} 395219820Sjeff 396219820Sjeffstatic int mlx4_ib_query_pkey(struct ib_device *ibdev, u8 port, u16 index, 397219820Sjeff u16 *pkey) 398219820Sjeff{ 399219820Sjeff struct ib_smp *in_mad = NULL; 400219820Sjeff struct ib_smp *out_mad = NULL; 401219820Sjeff int err = -ENOMEM; 402219820Sjeff 403219820Sjeff in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); 404219820Sjeff out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); 405219820Sjeff if (!in_mad || !out_mad) 406219820Sjeff goto out; 407219820Sjeff 408219820Sjeff init_query_mad(in_mad); 409219820Sjeff in_mad->attr_id = IB_SMP_ATTR_PKEY_TABLE; 410219820Sjeff in_mad->attr_mod = cpu_to_be32(index / 32); 411219820Sjeff 412219820Sjeff err = mlx4_MAD_IFC(to_mdev(ibdev), 1, 1, port, NULL, NULL, in_mad, out_mad); 413219820Sjeff if (err) 414219820Sjeff goto out; 415219820Sjeff 416219820Sjeff *pkey = be16_to_cpu(((__be16 *) out_mad->data)[index % 32]); 417219820Sjeff 418219820Sjeffout: 419219820Sjeff kfree(in_mad); 420219820Sjeff kfree(out_mad); 421219820Sjeff return err; 422219820Sjeff} 423219820Sjeff 424219820Sjeffstatic int mlx4_ib_modify_device(struct ib_device *ibdev, int mask, 425219820Sjeff struct ib_device_modify *props) 426219820Sjeff{ 427219820Sjeff struct mlx4_cmd_mailbox *mailbox; 428219820Sjeff int err; 429219820Sjeff 430219820Sjeff if (mask & ~IB_DEVICE_MODIFY_NODE_DESC) 431219820Sjeff return -EOPNOTSUPP; 432219820Sjeff 433219820Sjeff if (!(mask & IB_DEVICE_MODIFY_NODE_DESC)) 434219820Sjeff return 0; 435219820Sjeff 436219820Sjeff spin_lock(&to_mdev(ibdev)->sm_lock); 437219820Sjeff memcpy(ibdev->node_desc, props->node_desc, 64); 438219820Sjeff spin_unlock(&to_mdev(ibdev)->sm_lock); 439219820Sjeff 440219820Sjeff /* if possible, pass node desc to FW, so it can generate 441219820Sjeff * a 144 trap. If cmd fails, just ignore. 442219820Sjeff */ 443219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(to_mdev(ibdev)->dev); 444219820Sjeff if (IS_ERR(mailbox)) 445219820Sjeff return 0; 446219820Sjeff 447219820Sjeff memset(mailbox->buf, 0, 256); 448219820Sjeff memcpy(mailbox->buf, props->node_desc, 64); 449219820Sjeff err = mlx4_cmd(to_mdev(ibdev)->dev, mailbox->dma, 1, 0, 450219820Sjeff MLX4_CMD_SET_NODE, MLX4_CMD_TIME_CLASS_A); 451219820Sjeff if (err) 452219820Sjeff mlx4_ib_dbg("SET_NODE command failed (%d)", err); 453219820Sjeff 454219820Sjeff mlx4_free_cmd_mailbox(to_mdev(ibdev)->dev, mailbox); 455219820Sjeff 456219820Sjeff return 0; 457219820Sjeff} 458219820Sjeff 459219820Sjeffstatic int mlx4_SET_PORT(struct mlx4_ib_dev *dev, u8 port, int reset_qkey_viols, 460219820Sjeff u32 cap_mask) 461219820Sjeff{ 462219820Sjeff struct mlx4_cmd_mailbox *mailbox; 463219820Sjeff int err; 464219820Sjeff u8 is_eth = dev->dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH; 465219820Sjeff 466219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(dev->dev); 467219820Sjeff if (IS_ERR(mailbox)) 468219820Sjeff return PTR_ERR(mailbox); 469219820Sjeff 470219820Sjeff memset(mailbox->buf, 0, 256); 471219820Sjeff 472219820Sjeff if (dev->dev->flags & MLX4_FLAG_OLD_PORT_CMDS) { 473219820Sjeff *(u8 *) mailbox->buf = !!reset_qkey_viols << 6; 474219820Sjeff ((__be32 *) mailbox->buf)[2] = cpu_to_be32(cap_mask); 475219820Sjeff } else { 476219820Sjeff ((u8 *) mailbox->buf)[3] = !!reset_qkey_viols; 477219820Sjeff ((__be32 *) mailbox->buf)[1] = cpu_to_be32(cap_mask); 478219820Sjeff } 479219820Sjeff 480219820Sjeff err = mlx4_cmd(dev->dev, mailbox->dma, port, is_eth, MLX4_CMD_SET_PORT, 481219820Sjeff MLX4_CMD_TIME_CLASS_B); 482219820Sjeff 483219820Sjeff mlx4_free_cmd_mailbox(dev->dev, mailbox); 484219820Sjeff return err; 485219820Sjeff} 486219820Sjeff 487219820Sjeffstatic int mlx4_ib_modify_port(struct ib_device *ibdev, u8 port, int mask, 488219820Sjeff struct ib_port_modify *props) 489219820Sjeff{ 490219820Sjeff struct ib_port_attr attr; 491219820Sjeff u32 cap_mask; 492219820Sjeff int err; 493219820Sjeff 494219820Sjeff mutex_lock(&to_mdev(ibdev)->cap_mask_mutex); 495219820Sjeff 496219820Sjeff err = mlx4_ib_query_port(ibdev, port, &attr); 497219820Sjeff if (err) 498219820Sjeff goto out; 499219820Sjeff 500219820Sjeff cap_mask = (attr.port_cap_flags | props->set_port_cap_mask) & 501219820Sjeff ~props->clr_port_cap_mask; 502219820Sjeff 503219820Sjeff err = mlx4_SET_PORT(to_mdev(ibdev), port, 504219820Sjeff !!(mask & IB_PORT_RESET_QKEY_CNTR), 505219820Sjeff cap_mask); 506219820Sjeff 507219820Sjeffout: 508219820Sjeff mutex_unlock(&to_mdev(ibdev)->cap_mask_mutex); 509219820Sjeff return err; 510219820Sjeff} 511219820Sjeff 512219820Sjeffstatic struct ib_ucontext *mlx4_ib_alloc_ucontext(struct ib_device *ibdev, 513219820Sjeff struct ib_udata *udata) 514219820Sjeff{ 515219820Sjeff struct mlx4_ib_dev *dev = to_mdev(ibdev); 516219820Sjeff struct mlx4_ib_ucontext *context; 517219820Sjeff struct mlx4_ib_alloc_ucontext_resp resp; 518219820Sjeff int err; 519219820Sjeff 520219820Sjeff if (!dev->ib_active) 521219820Sjeff return ERR_PTR(-EAGAIN); 522219820Sjeff 523219820Sjeff resp.qp_tab_size = dev->dev->caps.num_qps; 524219820Sjeff 525219820Sjeff if (mlx4_wc_enabled()) { 526219820Sjeff resp.bf_reg_size = dev->dev->caps.bf_reg_size; 527219820Sjeff resp.bf_regs_per_page = dev->dev->caps.bf_regs_per_page; 528219820Sjeff } else { 529219820Sjeff resp.bf_reg_size = 0; 530219820Sjeff resp.bf_regs_per_page = 0; 531219820Sjeff } 532219820Sjeff 533219820Sjeff context = kzalloc(sizeof *context, GFP_KERNEL); 534219820Sjeff if (!context) 535219820Sjeff return ERR_PTR(-ENOMEM); 536219820Sjeff 537219820Sjeff err = mlx4_uar_alloc(to_mdev(ibdev)->dev, &context->uar); 538219820Sjeff if (err) { 539219820Sjeff kfree(context); 540219820Sjeff return ERR_PTR(err); 541219820Sjeff } 542219820Sjeff 543219820Sjeff INIT_LIST_HEAD(&context->db_page_list); 544219820Sjeff mutex_init(&context->db_page_mutex); 545219820Sjeff 546219820Sjeff err = ib_copy_to_udata(udata, &resp, sizeof resp); 547219820Sjeff if (err) { 548219820Sjeff mlx4_uar_free(to_mdev(ibdev)->dev, &context->uar); 549219820Sjeff kfree(context); 550219820Sjeff return ERR_PTR(-EFAULT); 551219820Sjeff } 552219820Sjeff 553219820Sjeff return &context->ibucontext; 554219820Sjeff} 555219820Sjeff 556219820Sjeffstatic int mlx4_ib_dealloc_ucontext(struct ib_ucontext *ibcontext) 557219820Sjeff{ 558219820Sjeff struct mlx4_ib_ucontext *context = to_mucontext(ibcontext); 559219820Sjeff 560219820Sjeff mlx4_uar_free(to_mdev(ibcontext->device)->dev, &context->uar); 561219820Sjeff kfree(context); 562219820Sjeff 563219820Sjeff return 0; 564219820Sjeff} 565219820Sjeff 566219820Sjeffstatic int mlx4_ib_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) 567219820Sjeff{ 568219820Sjeff struct mlx4_ib_dev *dev = to_mdev(context->device); 569219820Sjeff 570219820Sjeff if (vma->vm_end - vma->vm_start != PAGE_SIZE) 571219820Sjeff return -EINVAL; 572219820Sjeff 573219820Sjeff if (vma->vm_pgoff == 0) { 574219820Sjeff vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 575219820Sjeff 576219820Sjeff if (io_remap_pfn_range(vma, vma->vm_start, 577219820Sjeff to_mucontext(context)->uar.pfn, 578219820Sjeff PAGE_SIZE, vma->vm_page_prot)) 579219820Sjeff return -EAGAIN; 580219820Sjeff } else if (vma->vm_pgoff == 1 && dev->dev->caps.bf_reg_size != 0) { 581219820Sjeff vma->vm_page_prot = pgprot_wc(vma->vm_page_prot); 582219820Sjeff 583219820Sjeff if (io_remap_pfn_range(vma, vma->vm_start, 584219820Sjeff to_mucontext(context)->uar.pfn + 585219820Sjeff dev->dev->caps.num_uars, 586219820Sjeff PAGE_SIZE, vma->vm_page_prot)) 587219820Sjeff return -EAGAIN; 588219820Sjeff } else 589219820Sjeff return -EINVAL; 590219820Sjeff 591219820Sjeff return 0; 592219820Sjeff} 593219820Sjeff 594219820Sjeffstatic struct ib_pd *mlx4_ib_alloc_pd(struct ib_device *ibdev, 595219820Sjeff struct ib_ucontext *context, 596219820Sjeff struct ib_udata *udata) 597219820Sjeff{ 598219820Sjeff struct mlx4_ib_pd *pd; 599219820Sjeff int err; 600219820Sjeff 601219820Sjeff pd = kzalloc(sizeof *pd, GFP_KERNEL); 602219820Sjeff if (!pd) 603219820Sjeff return ERR_PTR(-ENOMEM); 604219820Sjeff 605219820Sjeff err = mlx4_pd_alloc(to_mdev(ibdev)->dev, &pd->pdn); 606219820Sjeff if (err) { 607219820Sjeff kfree(pd); 608219820Sjeff return ERR_PTR(err); 609219820Sjeff } 610219820Sjeff 611219820Sjeff if (context) 612219820Sjeff if (ib_copy_to_udata(udata, &pd->pdn, sizeof (__u32))) { 613219820Sjeff mlx4_pd_free(to_mdev(ibdev)->dev, pd->pdn); 614219820Sjeff kfree(pd); 615219820Sjeff return ERR_PTR(-EFAULT); 616219820Sjeff } 617219820Sjeff 618219820Sjeff return &pd->ibpd; 619219820Sjeff} 620219820Sjeff 621219820Sjeffstatic int mlx4_ib_dealloc_pd(struct ib_pd *pd) 622219820Sjeff{ 623219820Sjeff mlx4_pd_free(to_mdev(pd->device)->dev, to_mpd(pd)->pdn); 624219820Sjeff kfree(pd); 625219820Sjeff 626219820Sjeff return 0; 627219820Sjeff} 628219820Sjeff 629219820Sjeffstatic int add_gid_entry(struct ib_qp *ibqp, union ib_gid *gid) 630219820Sjeff{ 631219820Sjeff struct mlx4_ib_qp *mqp = to_mqp(ibqp); 632219820Sjeff struct mlx4_ib_dev *mdev = to_mdev(ibqp->device); 633219820Sjeff struct gid_entry *ge; 634219820Sjeff 635219820Sjeff ge = kzalloc(sizeof *ge, GFP_KERNEL); 636219820Sjeff if (!ge) 637219820Sjeff return -ENOMEM; 638219820Sjeff 639219820Sjeff ge->gid = *gid; 640219820Sjeff if (mlx4_ib_add_mc(mdev, mqp, gid)) { 641219820Sjeff ge->port = mqp->port; 642219820Sjeff ge->added = 1; 643219820Sjeff } 644219820Sjeff 645219820Sjeff mutex_lock(&mqp->mutex); 646219820Sjeff list_add_tail(&ge->list, &mqp->gid_list); 647219820Sjeff mutex_unlock(&mqp->mutex); 648219820Sjeff 649219820Sjeff return 0; 650219820Sjeff} 651219820Sjeff 652219820Sjeffint mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp, 653219820Sjeff union ib_gid *gid) 654219820Sjeff{ 655219820Sjeff u8 mac[6]; 656219820Sjeff struct net_device *ndev; 657219820Sjeff int ret = 0; 658219820Sjeff 659219820Sjeff if (!mqp->port) 660219820Sjeff return 0; 661219820Sjeff spin_lock(&mdev->iboe.lock); 662219820Sjeff ndev = mdev->iboe.netdevs[mqp->port - 1]; 663219820Sjeff if (ndev) 664219820Sjeff dev_hold(ndev); 665219820Sjeff spin_unlock(&mdev->iboe.lock); 666219820Sjeff if (ndev) { 667219820Sjeff rdma_get_mcast_mac((struct in6_addr *)gid, mac); 668219820Sjeff rtnl_lock(); 669219820Sjeff dev_mc_add(mdev->iboe.netdevs[mqp->port - 1], mac, 6, 0); 670219820Sjeff ret = 1; 671219820Sjeff rtnl_unlock(); 672219820Sjeff dev_put(ndev); 673219820Sjeff } 674219820Sjeff 675219820Sjeff return ret; 676219820Sjeff} 677219820Sjeff 678219820Sjeffstatic int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) 679219820Sjeff{ 680219820Sjeff int err; 681219820Sjeff struct mlx4_ib_dev *mdev = to_mdev(ibqp->device); 682219820Sjeff struct mlx4_ib_qp *mqp = to_mqp(ibqp); 683219820Sjeff 684219820Sjeff err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw, !!(mqp->flags & 685219820Sjeff MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK), 686219820Sjeff (ibqp->qp_type == IB_QPT_RAW_ETH) ? 687219820Sjeff MLX4_MCAST_PROT_EN : MLX4_MCAST_PROT_IB); 688219820Sjeff if (err) 689219820Sjeff return err; 690219820Sjeff 691219820Sjeff err = add_gid_entry(ibqp, gid); 692219820Sjeff if (err) 693219820Sjeff goto err_add; 694219820Sjeff 695219820Sjeff return 0; 696219820Sjeff 697219820Sjefferr_add: 698219820Sjeff mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, 699219820Sjeff (ibqp->qp_type == IB_QPT_RAW_ETH) ? 700219820Sjeff MLX4_MCAST_PROT_EN : MLX4_MCAST_PROT_IB); 701219820Sjeff return err; 702219820Sjeff} 703219820Sjeff 704219820Sjeffstatic struct gid_entry *find_gid_entry(struct mlx4_ib_qp *qp, u8 *raw) 705219820Sjeff{ 706219820Sjeff struct gid_entry *ge; 707219820Sjeff struct gid_entry *tmp; 708219820Sjeff struct gid_entry *ret = NULL; 709219820Sjeff 710219820Sjeff list_for_each_entry_safe(ge, tmp, &qp->gid_list, list) { 711219820Sjeff if (!memcmp(raw, ge->gid.raw, 16)) { 712219820Sjeff ret = ge; 713219820Sjeff break; 714219820Sjeff } 715219820Sjeff } 716219820Sjeff 717219820Sjeff return ret; 718219820Sjeff} 719219820Sjeff 720219820Sjeffstatic int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) 721219820Sjeff{ 722219820Sjeff int err; 723219820Sjeff struct mlx4_ib_dev *mdev = to_mdev(ibqp->device); 724219820Sjeff struct mlx4_ib_qp *mqp = to_mqp(ibqp); 725219820Sjeff u8 mac[6]; 726219820Sjeff struct net_device *ndev; 727219820Sjeff struct gid_entry *ge; 728219820Sjeff 729219820Sjeff err = mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, 730219820Sjeff (ibqp->qp_type == IB_QPT_RAW_ETH) ? 731219820Sjeff MLX4_MCAST_PROT_EN : MLX4_MCAST_PROT_IB); 732219820Sjeff if (err) 733219820Sjeff return err; 734219820Sjeff 735219820Sjeff mutex_lock(&mqp->mutex); 736219820Sjeff ge = find_gid_entry(mqp, gid->raw); 737219820Sjeff if (ge) { 738219820Sjeff spin_lock(&mdev->iboe.lock); 739219820Sjeff ndev = ge->added ? mdev->iboe.netdevs[ge->port - 1] : NULL; 740219820Sjeff if (ndev) 741219820Sjeff dev_hold(ndev); 742219820Sjeff spin_unlock(&mdev->iboe.lock); 743219820Sjeff rdma_get_mcast_mac((struct in6_addr *)gid, mac); 744219820Sjeff if (ndev) { 745219820Sjeff rtnl_lock(); 746219820Sjeff dev_mc_delete(mdev->iboe.netdevs[ge->port - 1], mac, 6, 0); 747219820Sjeff rtnl_unlock(); 748219820Sjeff dev_put(ndev); 749219820Sjeff } 750219820Sjeff list_del(&ge->list); 751219820Sjeff kfree(ge); 752219820Sjeff } else 753219820Sjeff printk(KERN_WARNING "could not find mgid entry\n"); 754219820Sjeff 755219820Sjeff mutex_unlock(&mqp->mutex); 756219820Sjeff 757219820Sjeff return 0; 758219820Sjeff} 759219820Sjeff 760219820Sjeffstatic void mlx4_dummy_comp_handler(struct ib_cq *cq, void *cq_context) 761219820Sjeff{ 762219820Sjeff} 763219820Sjeff 764219820Sjeffstatic struct ib_xrcd *mlx4_ib_alloc_xrcd(struct ib_device *ibdev, 765219820Sjeff struct ib_ucontext *context, 766219820Sjeff struct ib_udata *udata) 767219820Sjeff{ 768219820Sjeff struct mlx4_ib_xrcd *xrcd; 769219820Sjeff struct mlx4_ib_dev *mdev = to_mdev(ibdev); 770219820Sjeff struct ib_pd *pd; 771219820Sjeff struct ib_cq *cq; 772219820Sjeff int err; 773219820Sjeff 774219820Sjeff if (!(mdev->dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC)) 775219820Sjeff return ERR_PTR(-ENOSYS); 776219820Sjeff 777219820Sjeff xrcd = kmalloc(sizeof *xrcd, GFP_KERNEL); 778219820Sjeff if (!xrcd) 779219820Sjeff return ERR_PTR(-ENOMEM); 780219820Sjeff 781219820Sjeff err = mlx4_xrcd_alloc(mdev->dev, &xrcd->xrcdn); 782219820Sjeff if (err) 783219820Sjeff goto err_xrcd; 784219820Sjeff 785219820Sjeff pd = mlx4_ib_alloc_pd(ibdev, NULL, NULL); 786219820Sjeff if (IS_ERR(pd)) { 787219820Sjeff err = PTR_ERR(pd); 788219820Sjeff goto err_pd; 789219820Sjeff } 790219820Sjeff pd->device = ibdev; 791219820Sjeff 792219820Sjeff cq = mlx4_ib_create_cq(ibdev, 1, 0, NULL, NULL); 793219820Sjeff if (IS_ERR(cq)) { 794219820Sjeff err = PTR_ERR(cq); 795219820Sjeff goto err_cq; 796219820Sjeff } 797219820Sjeff cq->device = ibdev; 798219820Sjeff cq->comp_handler = mlx4_dummy_comp_handler; 799219820Sjeff 800219820Sjeff if (context) 801219820Sjeff if (ib_copy_to_udata(udata, &xrcd->xrcdn, sizeof(__u32))) { 802219820Sjeff err = -EFAULT; 803219820Sjeff goto err_copy; 804219820Sjeff } 805219820Sjeff 806219820Sjeff xrcd->cq = cq; 807219820Sjeff xrcd->pd = pd; 808219820Sjeff return &xrcd->ibxrcd; 809219820Sjeff 810219820Sjefferr_copy: 811219820Sjeff mlx4_ib_destroy_cq(cq); 812219820Sjefferr_cq: 813219820Sjeff mlx4_ib_dealloc_pd(pd); 814219820Sjefferr_pd: 815219820Sjeff mlx4_xrcd_free(mdev->dev, xrcd->xrcdn); 816219820Sjefferr_xrcd: 817219820Sjeff kfree(xrcd); 818219820Sjeff return ERR_PTR(err); 819219820Sjeff} 820219820Sjeff 821219820Sjeffstatic int mlx4_ib_dealloc_xrcd(struct ib_xrcd *xrcd) 822219820Sjeff{ 823219820Sjeff struct mlx4_ib_xrcd *mxrcd = to_mxrcd(xrcd); 824219820Sjeff 825219820Sjeff mlx4_ib_destroy_cq(mxrcd->cq); 826219820Sjeff mlx4_ib_dealloc_pd(mxrcd->pd); 827219820Sjeff mlx4_xrcd_free(to_mdev(xrcd->device)->dev, to_mxrcd(xrcd)->xrcdn); 828219820Sjeff kfree(xrcd); 829219820Sjeff 830219820Sjeff return 0; 831219820Sjeff} 832219820Sjeff 833219820Sjeff 834219820Sjeffstatic int init_node_data(struct mlx4_ib_dev *dev) 835219820Sjeff{ 836219820Sjeff struct ib_smp *in_mad = NULL; 837219820Sjeff struct ib_smp *out_mad = NULL; 838219820Sjeff int err = -ENOMEM; 839219820Sjeff 840219820Sjeff in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); 841219820Sjeff out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); 842219820Sjeff if (!in_mad || !out_mad) 843219820Sjeff goto out; 844219820Sjeff 845219820Sjeff init_query_mad(in_mad); 846219820Sjeff in_mad->attr_id = IB_SMP_ATTR_NODE_DESC; 847219820Sjeff 848219820Sjeff err = mlx4_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); 849219820Sjeff if (err) 850219820Sjeff goto out; 851219820Sjeff 852219820Sjeff memcpy(dev->ib_dev.node_desc, out_mad->data, 64); 853219820Sjeff 854219820Sjeff in_mad->attr_id = IB_SMP_ATTR_NODE_INFO; 855219820Sjeff 856219820Sjeff err = mlx4_MAD_IFC(dev, 1, 1, 1, NULL, NULL, in_mad, out_mad); 857219820Sjeff if (err) 858219820Sjeff goto out; 859219820Sjeff 860219820Sjeff dev->dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32)); 861219820Sjeff memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8); 862219820Sjeff 863219820Sjeffout: 864219820Sjeff kfree(in_mad); 865219820Sjeff kfree(out_mad); 866219820Sjeff return err; 867219820Sjeff} 868219820Sjeff 869219820Sjeffstatic ssize_t show_hca(struct device *device, struct device_attribute *attr, 870219820Sjeff char *buf) 871219820Sjeff{ 872219820Sjeff struct mlx4_ib_dev *dev = 873219820Sjeff container_of(device, struct mlx4_ib_dev, ib_dev.dev); 874219820Sjeff return sprintf(buf, "MT%d\n", dev->dev->pdev->device); 875219820Sjeff} 876219820Sjeff 877219820Sjeffstatic ssize_t show_fw_ver(struct device *device, struct device_attribute *attr, 878219820Sjeff char *buf) 879219820Sjeff{ 880219820Sjeff struct mlx4_ib_dev *dev = 881219820Sjeff container_of(device, struct mlx4_ib_dev, ib_dev.dev); 882219820Sjeff return sprintf(buf, "%d.%d.%d\n", (int) (dev->dev->caps.fw_ver >> 32), 883219820Sjeff (int) (dev->dev->caps.fw_ver >> 16) & 0xffff, 884219820Sjeff (int) dev->dev->caps.fw_ver & 0xffff); 885219820Sjeff} 886219820Sjeff 887219820Sjeffstatic ssize_t show_rev(struct device *device, struct device_attribute *attr, 888219820Sjeff char *buf) 889219820Sjeff{ 890219820Sjeff struct mlx4_ib_dev *dev = 891219820Sjeff container_of(device, struct mlx4_ib_dev, ib_dev.dev); 892219820Sjeff return sprintf(buf, "%x\n", dev->dev->rev_id); 893219820Sjeff} 894219820Sjeff 895219820Sjeffstatic ssize_t show_board(struct device *device, struct device_attribute *attr, 896219820Sjeff char *buf) 897219820Sjeff{ 898219820Sjeff struct mlx4_ib_dev *dev = 899219820Sjeff container_of(device, struct mlx4_ib_dev, ib_dev.dev); 900219820Sjeff return sprintf(buf, "%.*s\n", MLX4_BOARD_ID_LEN, 901219820Sjeff dev->dev->board_id); 902219820Sjeff} 903219820Sjeff 904219820Sjeffstatic DEVICE_ATTR(hw_rev, S_IRUGO, show_rev, NULL); 905219820Sjeffstatic DEVICE_ATTR(fw_ver, S_IRUGO, show_fw_ver, NULL); 906219820Sjeffstatic DEVICE_ATTR(hca_type, S_IRUGO, show_hca, NULL); 907219820Sjeffstatic DEVICE_ATTR(board_id, S_IRUGO, show_board, NULL); 908219820Sjeff 909219820Sjeffstatic struct device_attribute *mlx4_class_attributes[] = { 910219820Sjeff &dev_attr_hw_rev, 911219820Sjeff &dev_attr_fw_ver, 912219820Sjeff &dev_attr_hca_type, 913219820Sjeff &dev_attr_board_id 914219820Sjeff}; 915219820Sjeff 916219820Sjeff/* 917219820Sjeff * create show function and a device_attribute struct pointing to 918219820Sjeff * the function for _name 919219820Sjeff */ 920219820Sjeff#define DEVICE_DIAG_RPRT_ATTR(_name, _offset, _op_mod) \ 921219820Sjeffstatic ssize_t show_rprt_##_name(struct device *dev, \ 922219820Sjeff struct device_attribute *attr, \ 923219820Sjeff char *buf){ \ 924219820Sjeff return show_diag_rprt(dev, buf, _offset, _op_mod); \ 925219820Sjeff} \ 926219820Sjeffstatic DEVICE_ATTR(_name, S_IRUGO, show_rprt_##_name, NULL); 927219820Sjeff 928219820Sjeff#define MLX4_DIAG_RPRT_CLEAR_DIAGS 3 929219820Sjeff 930219820Sjeffstatic size_t show_diag_rprt(struct device *device, char *buf, 931219820Sjeff u32 offset, u8 op_modifier) 932219820Sjeff{ 933219820Sjeff size_t ret; 934219820Sjeff u32 counter_offset = offset; 935219820Sjeff u32 diag_counter = 0; 936219820Sjeff struct mlx4_ib_dev *dev = container_of(device, struct mlx4_ib_dev, 937219820Sjeff ib_dev.dev); 938219820Sjeff 939219820Sjeff ret = mlx4_query_diag_counters(dev->dev, 1, op_modifier, 940219820Sjeff &counter_offset, &diag_counter); 941219820Sjeff if (ret) 942219820Sjeff return ret; 943219820Sjeff 944219820Sjeff return sprintf(buf,"%d\n", diag_counter); 945219820Sjeff} 946219820Sjeff 947219820Sjeffstatic ssize_t clear_diag_counters(struct device *device, 948219820Sjeff struct device_attribute *attr, 949219820Sjeff const char *buf, size_t length) 950219820Sjeff{ 951219820Sjeff size_t ret; 952219820Sjeff struct mlx4_ib_dev *dev = container_of(device, struct mlx4_ib_dev, 953219820Sjeff ib_dev.dev); 954219820Sjeff 955219820Sjeff ret = mlx4_query_diag_counters(dev->dev, 0, MLX4_DIAG_RPRT_CLEAR_DIAGS, 956219820Sjeff NULL, NULL); 957219820Sjeff if (ret) 958219820Sjeff return ret; 959219820Sjeff 960219820Sjeff return length; 961219820Sjeff} 962219820Sjeff 963219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_lle , 0x00, 2); 964219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_lle , 0x04, 2); 965219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_lqpoe , 0x08, 2); 966219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_lqpoe , 0x0C, 2); 967219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_leeoe , 0x10, 2); 968219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_leeoe , 0x14, 2); 969219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_lpe , 0x18, 2); 970219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_lpe , 0x1C, 2); 971219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_wrfe , 0x20, 2); 972219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_wrfe , 0x24, 2); 973219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_mwbe , 0x2C, 2); 974219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_bre , 0x34, 2); 975219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_lae , 0x38, 2); 976219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_rire , 0x44, 2); 977219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_rire , 0x48, 2); 978219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_rae , 0x4C, 2); 979219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_rae , 0x50, 2); 980219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_roe , 0x54, 2); 981219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_tree , 0x5C, 2); 982219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_rree , 0x64, 2); 983219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_rnr , 0x68, 2); 984219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_rnr , 0x6C, 2); 985219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_rabrte , 0x7C, 2); 986219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_ieecne , 0x84, 2); 987219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_ieecse , 0x8C, 2); 988219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_oos , 0x100, 2); 989219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_oos , 0x104, 2); 990219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_mce , 0x108, 2); 991219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_rsync , 0x110, 2); 992219820SjeffDEVICE_DIAG_RPRT_ATTR(sq_num_rsync , 0x114, 2); 993219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_udsdprd , 0x118, 2); 994219820SjeffDEVICE_DIAG_RPRT_ATTR(rq_num_ucsdprd , 0x120, 2); 995219820SjeffDEVICE_DIAG_RPRT_ATTR(num_cqovf , 0x1A0, 2); 996219820SjeffDEVICE_DIAG_RPRT_ATTR(num_eqovf , 0x1A4, 2); 997219820SjeffDEVICE_DIAG_RPRT_ATTR(num_baddb , 0x1A8, 2); 998219820Sjeff 999219820Sjeffstatic DEVICE_ATTR(clear_diag, S_IWUGO, NULL, clear_diag_counters); 1000219820Sjeff 1001219820Sjeffstatic struct attribute *diag_rprt_attrs[] = { 1002219820Sjeff &dev_attr_rq_num_lle.attr, 1003219820Sjeff &dev_attr_sq_num_lle.attr, 1004219820Sjeff &dev_attr_rq_num_lqpoe.attr, 1005219820Sjeff &dev_attr_sq_num_lqpoe.attr, 1006219820Sjeff &dev_attr_rq_num_leeoe.attr, 1007219820Sjeff &dev_attr_sq_num_leeoe.attr, 1008219820Sjeff &dev_attr_rq_num_lpe.attr, 1009219820Sjeff &dev_attr_sq_num_lpe.attr, 1010219820Sjeff &dev_attr_rq_num_wrfe.attr, 1011219820Sjeff &dev_attr_sq_num_wrfe.attr, 1012219820Sjeff &dev_attr_sq_num_mwbe.attr, 1013219820Sjeff &dev_attr_sq_num_bre.attr, 1014219820Sjeff &dev_attr_rq_num_lae.attr, 1015219820Sjeff &dev_attr_sq_num_rire.attr, 1016219820Sjeff &dev_attr_rq_num_rire.attr, 1017219820Sjeff &dev_attr_sq_num_rae.attr, 1018219820Sjeff &dev_attr_rq_num_rae.attr, 1019219820Sjeff &dev_attr_sq_num_roe.attr, 1020219820Sjeff &dev_attr_sq_num_tree.attr, 1021219820Sjeff &dev_attr_sq_num_rree.attr, 1022219820Sjeff &dev_attr_rq_num_rnr.attr, 1023219820Sjeff &dev_attr_sq_num_rnr.attr, 1024219820Sjeff &dev_attr_sq_num_rabrte.attr, 1025219820Sjeff &dev_attr_sq_num_ieecne.attr, 1026219820Sjeff &dev_attr_sq_num_ieecse.attr, 1027219820Sjeff &dev_attr_rq_num_oos.attr, 1028219820Sjeff &dev_attr_sq_num_oos.attr, 1029219820Sjeff &dev_attr_rq_num_mce.attr, 1030219820Sjeff &dev_attr_rq_num_rsync.attr, 1031219820Sjeff &dev_attr_sq_num_rsync.attr, 1032219820Sjeff &dev_attr_rq_num_udsdprd.attr, 1033219820Sjeff &dev_attr_rq_num_ucsdprd.attr, 1034219820Sjeff &dev_attr_num_cqovf.attr, 1035219820Sjeff &dev_attr_num_eqovf.attr, 1036219820Sjeff &dev_attr_num_baddb.attr, 1037219820Sjeff &dev_attr_clear_diag.attr, 1038219820Sjeff NULL 1039219820Sjeff}; 1040219820Sjeff 1041219820Sjeffstruct attribute_group diag_counters_group = { 1042219820Sjeff .name = "diag_counters", 1043219820Sjeff .attrs = diag_rprt_attrs 1044219820Sjeff}; 1045219820Sjeff 1046219820Sjeffstatic void mlx4_addrconf_ifid_eui48(u8 *eui, u16 vlan_id, struct net_device *dev) 1047219820Sjeff{ 1048219820Sjeff#ifdef __linux__ 1049219820Sjeff memcpy(eui, dev->dev_addr, 3); 1050219820Sjeff memcpy(eui + 5, dev->dev_addr + 3, 3); 1051219820Sjeff#else 1052219820Sjeff memcpy(eui, IF_LLADDR(dev), 3); 1053219820Sjeff memcpy(eui + 5, IF_LLADDR(dev) + 3, 3); 1054219820Sjeff#endif 1055219820Sjeff if (vlan_id < 0x1000) { 1056219820Sjeff eui[3] = vlan_id >> 8; 1057219820Sjeff eui[4] = vlan_id & 0xff; 1058219820Sjeff } else { 1059219820Sjeff eui[3] = 0xff; 1060219820Sjeff eui[4] = 0xfe; 1061219820Sjeff } 1062219820Sjeff eui[0] ^= 2; 1063219820Sjeff} 1064219820Sjeff 1065219820Sjeffstatic void update_gids_task(struct work_struct *work) 1066219820Sjeff{ 1067219820Sjeff struct update_gid_work *gw = container_of(work, struct update_gid_work, work); 1068219820Sjeff struct mlx4_cmd_mailbox *mailbox; 1069219820Sjeff union ib_gid *gids; 1070219820Sjeff int err; 1071219820Sjeff struct mlx4_dev *dev = gw->dev->dev; 1072219820Sjeff struct ib_event event; 1073219820Sjeff 1074219820Sjeff mailbox = mlx4_alloc_cmd_mailbox(dev); 1075219820Sjeff if (IS_ERR(mailbox)) { 1076219820Sjeff printk(KERN_WARNING "update gid table failed %ld\n", PTR_ERR(mailbox)); 1077219820Sjeff return; 1078219820Sjeff } 1079219820Sjeff 1080219820Sjeff gids = mailbox->buf; 1081219820Sjeff memcpy(gids, gw->gids, sizeof gw->gids); 1082219820Sjeff 1083219820Sjeff err = mlx4_cmd(dev, mailbox->dma, MLX4_SET_PORT_GID_TABLE << 8 | gw->port, 1084219820Sjeff 1, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B); 1085219820Sjeff if (err) 1086219820Sjeff printk(KERN_WARNING "set port command failed\n"); 1087219820Sjeff else { 1088219820Sjeff memcpy(gw->dev->iboe.gid_table[gw->port - 1], gw->gids, sizeof gw->gids); 1089219820Sjeff event.device = &gw->dev->ib_dev; 1090219820Sjeff event.element.port_num = gw->port; 1091219820Sjeff event.event = IB_EVENT_GID_CHANGE; 1092219820Sjeff ib_dispatch_event(&event); 1093219820Sjeff } 1094219820Sjeff 1095219820Sjeff mlx4_free_cmd_mailbox(dev, mailbox); 1096219820Sjeff kfree(gw); 1097219820Sjeff} 1098219820Sjeff 1099219820Sjeffenum { 1100219820Sjeff MLX4_MAX_EFF_VLANS = 128 - MLX4_VLAN_REGULAR, 1101219820Sjeff}; 1102219820Sjeff 1103219820Sjeffstatic int update_ipv6_gids(struct mlx4_ib_dev *dev, int port, int clear) 1104219820Sjeff{ 1105219820Sjeff struct net_device *ndev = dev->iboe.netdevs[port - 1]; 1106219820Sjeff struct update_gid_work *work; 1107219820Sjeff struct net_device *tmp; 1108219820Sjeff int i; 1109219820Sjeff u8 *hits; 1110219820Sjeff int ret; 1111219820Sjeff union ib_gid gid; 1112219820Sjeff int tofree; 1113219820Sjeff int found; 1114219820Sjeff int need_update = 0; 1115219820Sjeff u16 vid; 1116219820Sjeff 1117219820Sjeff work = kzalloc(sizeof *work, GFP_ATOMIC); 1118219820Sjeff if (!work) 1119219820Sjeff return -ENOMEM; 1120219820Sjeff 1121219820Sjeff hits = kzalloc(MLX4_MAX_EFF_VLANS + 1, GFP_ATOMIC); 1122219820Sjeff if (!hits) { 1123219820Sjeff ret = -ENOMEM; 1124219820Sjeff goto out; 1125219820Sjeff } 1126219820Sjeff 1127219820Sjeff#ifdef __linux__ 1128219820Sjeff read_lock(&dev_base_lock); 1129219820Sjeff for_each_netdev(&init_net, tmp) { 1130219820Sjeff#else 1131219820Sjeff IFNET_RLOCK(); 1132219820Sjeff TAILQ_FOREACH(tmp, &V_ifnet, if_link) { 1133219820Sjeff#endif 1134219820Sjeff if (ndev && (tmp == ndev || rdma_vlan_dev_real_dev(tmp) == ndev)) { 1135219820Sjeff gid.global.subnet_prefix = cpu_to_be64(0xfe80000000000000LL); 1136219820Sjeff vid = rdma_vlan_dev_vlan_id(tmp); 1137219820Sjeff mlx4_addrconf_ifid_eui48(&gid.raw[8], vid, ndev); 1138219820Sjeff found = 0; 1139219820Sjeff tofree = -1; 1140219820Sjeff for (i = 0; i < MLX4_MAX_EFF_VLANS + 1; ++i) { 1141219820Sjeff if (tofree < 0 && 1142219820Sjeff !memcmp(&dev->iboe.gid_table[port - 1][i], &zgid, sizeof zgid)) 1143219820Sjeff tofree = i; 1144219820Sjeff if (!memcmp(&dev->iboe.gid_table[port - 1][i], &gid, sizeof gid)) { 1145219820Sjeff hits[i] = 1; 1146219820Sjeff found = 1; 1147219820Sjeff break; 1148219820Sjeff } 1149219820Sjeff } 1150219820Sjeff 1151219820Sjeff if (!found) { 1152219820Sjeff if (tmp == ndev && (memcmp(&dev->iboe.gid_table[port - 1][0], &gid, sizeof gid) || !memcmp(&dev->iboe.gid_table[port - 1][0], &zgid, sizeof gid))) { 1153219820Sjeff dev->iboe.gid_table[port - 1][0] = gid; 1154219820Sjeff ++need_update; 1155219820Sjeff hits[0] = 1; 1156219820Sjeff } else if (tofree >= 0) { 1157219820Sjeff dev->iboe.gid_table[port - 1][tofree] = gid; 1158219820Sjeff hits[tofree] = 1; 1159219820Sjeff ++need_update; 1160219820Sjeff } 1161219820Sjeff } 1162219820Sjeff } 1163219820Sjeff#ifdef __linux__ 1164219820Sjeff } 1165219820Sjeff read_unlock(&dev_base_lock); 1166219820Sjeff#else 1167219820Sjeff } 1168219820Sjeff IFNET_RUNLOCK(); 1169219820Sjeff#endif 1170219820Sjeff 1171219820Sjeff for (i = 0; i < MLX4_MAX_EFF_VLANS + 1; ++i) 1172219820Sjeff if (!hits[i]) { 1173219820Sjeff if (memcmp(&dev->iboe.gid_table[port - 1][i], &zgid, sizeof zgid)) 1174219820Sjeff ++need_update; 1175219820Sjeff dev->iboe.gid_table[port - 1][i] = zgid; 1176219820Sjeff } 1177219820Sjeff 1178219820Sjeff 1179219820Sjeff if (need_update) { 1180219820Sjeff memcpy(work->gids, dev->iboe.gid_table[port - 1], sizeof work->gids); 1181219820Sjeff INIT_WORK(&work->work, update_gids_task); 1182219820Sjeff work->port = port; 1183219820Sjeff work->dev = dev; 1184219820Sjeff queue_work(wq, &work->work); 1185219820Sjeff } else 1186219820Sjeff kfree(work); 1187219820Sjeff 1188219820Sjeff kfree(hits); 1189219820Sjeff return 0; 1190219820Sjeff 1191219820Sjeffout: 1192219820Sjeff kfree(work); 1193219820Sjeff return ret; 1194219820Sjeff} 1195219820Sjeff 1196219820Sjeffstatic void handle_en_event(struct mlx4_ib_dev *dev, int port, unsigned long event) 1197219820Sjeff{ 1198219820Sjeff switch (event) { 1199219820Sjeff case NETDEV_UP: 1200219820Sjeff#ifdef __linux__ 1201219820Sjeff case NETDEV_CHANGEADDR: 1202219820Sjeff#endif 1203219820Sjeff update_ipv6_gids(dev, port, 0); 1204219820Sjeff break; 1205219820Sjeff 1206219820Sjeff case NETDEV_DOWN: 1207219820Sjeff update_ipv6_gids(dev, port, 1); 1208219820Sjeff dev->iboe.netdevs[port - 1] = NULL; 1209219820Sjeff } 1210219820Sjeff} 1211219820Sjeff 1212219820Sjeffstatic void netdev_added(struct mlx4_ib_dev *dev, int port) 1213219820Sjeff{ 1214219820Sjeff update_ipv6_gids(dev, port, 0); 1215219820Sjeff} 1216219820Sjeff 1217219820Sjeffstatic void netdev_removed(struct mlx4_ib_dev *dev, int port) 1218219820Sjeff{ 1219219820Sjeff update_ipv6_gids(dev, port, 1); 1220219820Sjeff} 1221219820Sjeff 1222219820Sjeffstatic int mlx4_ib_netdev_event(struct notifier_block *this, unsigned long event, 1223219820Sjeff void *ptr) 1224219820Sjeff{ 1225219820Sjeff struct net_device *dev = ptr; 1226219820Sjeff struct mlx4_ib_dev *ibdev; 1227219820Sjeff struct net_device *oldnd; 1228219820Sjeff struct mlx4_ib_iboe *iboe; 1229219820Sjeff int port; 1230219820Sjeff 1231219820Sjeff#ifdef __linux__ 1232219820Sjeff if (!net_eq(dev_net(dev), &init_net)) 1233219820Sjeff return NOTIFY_DONE; 1234219820Sjeff#endif 1235219820Sjeff 1236219820Sjeff ibdev = container_of(this, struct mlx4_ib_dev, iboe.nb); 1237219820Sjeff iboe = &ibdev->iboe; 1238219820Sjeff 1239219820Sjeff spin_lock(&iboe->lock); 1240219820Sjeff mlx4_foreach_ib_transport_port(port, ibdev->dev) { 1241219820Sjeff oldnd = iboe->netdevs[port - 1]; 1242219820Sjeff iboe->netdevs[port - 1] = mlx4_get_prot_dev(ibdev->dev, MLX4_PROT_EN, port); 1243219820Sjeff if (oldnd != iboe->netdevs[port - 1]) { 1244219820Sjeff if (iboe->netdevs[port - 1]) 1245219820Sjeff netdev_added(ibdev, port); 1246219820Sjeff else 1247219820Sjeff netdev_removed(ibdev, port); 1248219820Sjeff } 1249219820Sjeff } 1250219820Sjeff 1251219820Sjeff if (dev == iboe->netdevs[0] || 1252219820Sjeff (iboe->netdevs[0] && rdma_vlan_dev_real_dev(dev) == iboe->netdevs[0])) 1253219820Sjeff handle_en_event(ibdev, 1, event); 1254219820Sjeff else if (dev == iboe->netdevs[1] 1255219820Sjeff || (iboe->netdevs[1] && rdma_vlan_dev_real_dev(dev) == iboe->netdevs[1])) 1256219820Sjeff handle_en_event(ibdev, 2, event); 1257219820Sjeff 1258219820Sjeff spin_unlock(&iboe->lock); 1259219820Sjeff 1260219820Sjeff return NOTIFY_DONE; 1261219820Sjeff} 1262219820Sjeff 1263219820Sjeffstatic void *mlx4_ib_add(struct mlx4_dev *dev) 1264219820Sjeff{ 1265219820Sjeff static int mlx4_ib_version_printed; 1266219820Sjeff struct mlx4_ib_dev *ibdev; 1267219820Sjeff int num_ports = 0; 1268219820Sjeff int i; 1269219820Sjeff int err; 1270219820Sjeff struct mlx4_ib_iboe *iboe; 1271219820Sjeff int k; 1272219820Sjeff 1273219820Sjeff if (!mlx4_ib_version_printed) { 1274219820Sjeff printk(KERN_INFO "%s", mlx4_ib_version); 1275219820Sjeff ++mlx4_ib_version_printed; 1276219820Sjeff } 1277219820Sjeff 1278219820Sjeff mlx4_foreach_ib_transport_port(i, dev) 1279219820Sjeff num_ports++; 1280219820Sjeff 1281219820Sjeff /* No point in registering a device with no ports... */ 1282219820Sjeff if (num_ports == 0) 1283219820Sjeff return NULL; 1284219820Sjeff 1285219820Sjeff ibdev = (struct mlx4_ib_dev *) ib_alloc_device(sizeof *ibdev); 1286219820Sjeff if (!ibdev) { 1287219820Sjeff dev_err(&dev->pdev->dev, "Device struct alloc failed\n"); 1288219820Sjeff return NULL; 1289219820Sjeff } 1290219820Sjeff 1291219820Sjeff iboe = &ibdev->iboe; 1292219820Sjeff 1293219820Sjeff if (mlx4_pd_alloc(dev, &ibdev->priv_pdn)) 1294219820Sjeff goto err_dealloc; 1295219820Sjeff 1296219820Sjeff if (mlx4_uar_alloc(dev, &ibdev->priv_uar)) 1297219820Sjeff goto err_pd; 1298219820Sjeff 1299219820Sjeff ibdev->priv_uar.map = ioremap(ibdev->priv_uar.pfn << PAGE_SHIFT, PAGE_SIZE); 1300219820Sjeff if (!ibdev->priv_uar.map) 1301219820Sjeff goto err_uar; 1302219820Sjeff MLX4_INIT_DOORBELL_LOCK(&ibdev->uar_lock); 1303219820Sjeff 1304219820Sjeff ibdev->dev = dev; 1305219820Sjeff 1306219820Sjeff strlcpy(ibdev->ib_dev.name, "mlx4_%d", IB_DEVICE_NAME_MAX); 1307219820Sjeff ibdev->ib_dev.owner = THIS_MODULE; 1308219820Sjeff ibdev->ib_dev.node_type = RDMA_NODE_IB_CA; 1309219820Sjeff ibdev->ib_dev.local_dma_lkey = dev->caps.reserved_lkey; 1310219820Sjeff ibdev->num_ports = num_ports; 1311219820Sjeff ibdev->ib_dev.phys_port_cnt = ibdev->num_ports; 1312219820Sjeff ibdev->ib_dev.num_comp_vectors = dev->caps.num_comp_vectors; 1313219820Sjeff ibdev->ib_dev.dma_device = &dev->pdev->dev; 1314219820Sjeff 1315219820Sjeff ibdev->ib_dev.uverbs_abi_ver = MLX4_IB_UVERBS_ABI_VERSION; 1316219820Sjeff ibdev->ib_dev.uverbs_cmd_mask = 1317219820Sjeff (1ull << IB_USER_VERBS_CMD_GET_CONTEXT) | 1318219820Sjeff (1ull << IB_USER_VERBS_CMD_QUERY_DEVICE) | 1319219820Sjeff (1ull << IB_USER_VERBS_CMD_QUERY_PORT) | 1320219820Sjeff (1ull << IB_USER_VERBS_CMD_ALLOC_PD) | 1321219820Sjeff (1ull << IB_USER_VERBS_CMD_DEALLOC_PD) | 1322219820Sjeff (1ull << IB_USER_VERBS_CMD_REG_MR) | 1323219820Sjeff (1ull << IB_USER_VERBS_CMD_DEREG_MR) | 1324219820Sjeff (1ull << IB_USER_VERBS_CMD_CREATE_COMP_CHANNEL) | 1325219820Sjeff (1ull << IB_USER_VERBS_CMD_CREATE_CQ) | 1326219820Sjeff (1ull << IB_USER_VERBS_CMD_RESIZE_CQ) | 1327219820Sjeff (1ull << IB_USER_VERBS_CMD_DESTROY_CQ) | 1328219820Sjeff (1ull << IB_USER_VERBS_CMD_CREATE_QP) | 1329219820Sjeff (1ull << IB_USER_VERBS_CMD_MODIFY_QP) | 1330219820Sjeff (1ull << IB_USER_VERBS_CMD_QUERY_QP) | 1331219820Sjeff (1ull << IB_USER_VERBS_CMD_DESTROY_QP) | 1332219820Sjeff (1ull << IB_USER_VERBS_CMD_ATTACH_MCAST) | 1333219820Sjeff (1ull << IB_USER_VERBS_CMD_DETACH_MCAST) | 1334219820Sjeff (1ull << IB_USER_VERBS_CMD_CREATE_SRQ) | 1335219820Sjeff (1ull << IB_USER_VERBS_CMD_MODIFY_SRQ) | 1336219820Sjeff (1ull << IB_USER_VERBS_CMD_QUERY_SRQ) | 1337219820Sjeff (1ull << IB_USER_VERBS_CMD_DESTROY_SRQ); 1338219820Sjeff 1339219820Sjeff ibdev->ib_dev.query_device = mlx4_ib_query_device; 1340219820Sjeff ibdev->ib_dev.query_port = mlx4_ib_query_port; 1341219820Sjeff ibdev->ib_dev.get_link_layer = mlx4_ib_port_link_layer; 1342219820Sjeff ibdev->ib_dev.query_gid = mlx4_ib_query_gid; 1343219820Sjeff ibdev->ib_dev.query_pkey = mlx4_ib_query_pkey; 1344219820Sjeff ibdev->ib_dev.modify_device = mlx4_ib_modify_device; 1345219820Sjeff ibdev->ib_dev.modify_port = mlx4_ib_modify_port; 1346219820Sjeff ibdev->ib_dev.alloc_ucontext = mlx4_ib_alloc_ucontext; 1347219820Sjeff ibdev->ib_dev.dealloc_ucontext = mlx4_ib_dealloc_ucontext; 1348219820Sjeff ibdev->ib_dev.mmap = mlx4_ib_mmap; 1349219820Sjeff ibdev->ib_dev.alloc_pd = mlx4_ib_alloc_pd; 1350219820Sjeff ibdev->ib_dev.dealloc_pd = mlx4_ib_dealloc_pd; 1351219820Sjeff ibdev->ib_dev.create_ah = mlx4_ib_create_ah; 1352219820Sjeff ibdev->ib_dev.query_ah = mlx4_ib_query_ah; 1353219820Sjeff ibdev->ib_dev.destroy_ah = mlx4_ib_destroy_ah; 1354219820Sjeff ibdev->ib_dev.create_srq = mlx4_ib_create_srq; 1355219820Sjeff ibdev->ib_dev.modify_srq = mlx4_ib_modify_srq; 1356219820Sjeff ibdev->ib_dev.query_srq = mlx4_ib_query_srq; 1357219820Sjeff ibdev->ib_dev.destroy_srq = mlx4_ib_destroy_srq; 1358219820Sjeff ibdev->ib_dev.post_srq_recv = mlx4_ib_post_srq_recv; 1359219820Sjeff ibdev->ib_dev.create_qp = mlx4_ib_create_qp; 1360219820Sjeff ibdev->ib_dev.modify_qp = mlx4_ib_modify_qp; 1361219820Sjeff ibdev->ib_dev.query_qp = mlx4_ib_query_qp; 1362219820Sjeff ibdev->ib_dev.destroy_qp = mlx4_ib_destroy_qp; 1363219820Sjeff ibdev->ib_dev.post_send = mlx4_ib_post_send; 1364219820Sjeff ibdev->ib_dev.post_recv = mlx4_ib_post_recv; 1365219820Sjeff ibdev->ib_dev.create_cq = mlx4_ib_create_cq; 1366219820Sjeff ibdev->ib_dev.modify_cq = mlx4_ib_modify_cq; 1367219820Sjeff ibdev->ib_dev.resize_cq = mlx4_ib_resize_cq; 1368219820Sjeff ibdev->ib_dev.destroy_cq = mlx4_ib_destroy_cq; 1369219820Sjeff ibdev->ib_dev.poll_cq = mlx4_ib_poll_cq; 1370219820Sjeff ibdev->ib_dev.req_notify_cq = mlx4_ib_arm_cq; 1371219820Sjeff ibdev->ib_dev.get_dma_mr = mlx4_ib_get_dma_mr; 1372219820Sjeff ibdev->ib_dev.reg_user_mr = mlx4_ib_reg_user_mr; 1373219820Sjeff ibdev->ib_dev.dereg_mr = mlx4_ib_dereg_mr; 1374219820Sjeff ibdev->ib_dev.alloc_fast_reg_mr = mlx4_ib_alloc_fast_reg_mr; 1375219820Sjeff ibdev->ib_dev.alloc_fast_reg_page_list = mlx4_ib_alloc_fast_reg_page_list; 1376219820Sjeff ibdev->ib_dev.free_fast_reg_page_list = mlx4_ib_free_fast_reg_page_list; 1377219820Sjeff ibdev->ib_dev.attach_mcast = mlx4_ib_mcg_attach; 1378219820Sjeff ibdev->ib_dev.detach_mcast = mlx4_ib_mcg_detach; 1379219820Sjeff ibdev->ib_dev.process_mad = mlx4_ib_process_mad; 1380219820Sjeff 1381219820Sjeff ibdev->ib_dev.alloc_fmr = mlx4_ib_fmr_alloc; 1382219820Sjeff ibdev->ib_dev.map_phys_fmr = mlx4_ib_map_phys_fmr; 1383219820Sjeff ibdev->ib_dev.unmap_fmr = mlx4_ib_unmap_fmr; 1384219820Sjeff ibdev->ib_dev.dealloc_fmr = mlx4_ib_fmr_dealloc; 1385219820Sjeff if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) { 1386219820Sjeff ibdev->ib_dev.create_xrc_srq = mlx4_ib_create_xrc_srq; 1387219820Sjeff ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd; 1388219820Sjeff ibdev->ib_dev.dealloc_xrcd = mlx4_ib_dealloc_xrcd; 1389219820Sjeff ibdev->ib_dev.create_xrc_rcv_qp = mlx4_ib_create_xrc_rcv_qp; 1390219820Sjeff ibdev->ib_dev.modify_xrc_rcv_qp = mlx4_ib_modify_xrc_rcv_qp; 1391219820Sjeff ibdev->ib_dev.query_xrc_rcv_qp = mlx4_ib_query_xrc_rcv_qp; 1392219820Sjeff ibdev->ib_dev.reg_xrc_rcv_qp = mlx4_ib_reg_xrc_rcv_qp; 1393219820Sjeff ibdev->ib_dev.unreg_xrc_rcv_qp = mlx4_ib_unreg_xrc_rcv_qp; 1394219820Sjeff ibdev->ib_dev.uverbs_cmd_mask |= 1395219820Sjeff (1ull << IB_USER_VERBS_CMD_CREATE_XRC_SRQ) | 1396219820Sjeff (1ull << IB_USER_VERBS_CMD_OPEN_XRC_DOMAIN) | 1397219820Sjeff (1ull << IB_USER_VERBS_CMD_CLOSE_XRC_DOMAIN) | 1398219820Sjeff (1ull << IB_USER_VERBS_CMD_CREATE_XRC_RCV_QP) | 1399219820Sjeff (1ull << IB_USER_VERBS_CMD_MODIFY_XRC_RCV_QP) | 1400219820Sjeff (1ull << IB_USER_VERBS_CMD_QUERY_XRC_RCV_QP) | 1401219820Sjeff (1ull << IB_USER_VERBS_CMD_REG_XRC_RCV_QP) | 1402219820Sjeff (1ull << IB_USER_VERBS_CMD_UNREG_XRC_RCV_QP); 1403219820Sjeff } 1404219820Sjeff 1405219820Sjeff 1406219820Sjeff spin_lock_init(&iboe->lock); 1407219820Sjeff if (init_node_data(ibdev)) 1408219820Sjeff goto err_map; 1409219820Sjeff 1410219820Sjeff for (k = 0; k < ibdev->num_ports; ++k) { 1411219820Sjeff err = mlx4_counter_alloc(ibdev->dev, &ibdev->counters[k]); 1412219820Sjeff if (err) 1413219820Sjeff ibdev->counters[k] = -1; 1414219820Sjeff else 1415219820Sjeff mlx4_set_iboe_counter(dev, ibdev->counters[k], k + 1); 1416219820Sjeff } 1417219820Sjeff 1418219820Sjeff spin_lock_init(&ibdev->sm_lock); 1419219820Sjeff mutex_init(&ibdev->cap_mask_mutex); 1420219820Sjeff mutex_init(&ibdev->xrc_reg_mutex); 1421219820Sjeff 1422219820Sjeff if (ib_register_device(&ibdev->ib_dev)) 1423219820Sjeff goto err_counter; 1424219820Sjeff 1425219820Sjeff if (mlx4_ib_mad_init(ibdev)) 1426219820Sjeff goto err_reg; 1427219820Sjeff if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE && !iboe->nb.notifier_call) { 1428219820Sjeff iboe->nb.notifier_call = mlx4_ib_netdev_event; 1429219820Sjeff err = register_netdevice_notifier(&iboe->nb); 1430219820Sjeff if (err) 1431219820Sjeff goto err_reg; 1432219820Sjeff } 1433219820Sjeff for (i = 0; i < ARRAY_SIZE(mlx4_class_attributes); ++i) { 1434219820Sjeff if (device_create_file(&ibdev->ib_dev.dev, 1435219820Sjeff mlx4_class_attributes[i])) 1436219820Sjeff goto err_notif; 1437219820Sjeff } 1438219820Sjeff 1439219820Sjeff if(sysfs_create_group(&ibdev->ib_dev.dev.kobj, &diag_counters_group)) 1440219820Sjeff goto err_notif; 1441219820Sjeff 1442219820Sjeff ibdev->ib_active = 1; 1443219820Sjeff 1444219820Sjeff return ibdev; 1445219820Sjeff 1446219820Sjefferr_notif: 1447219820Sjeff if (unregister_netdevice_notifier(&ibdev->iboe.nb)) 1448219820Sjeff printk(KERN_WARNING "failure unregistering notifier\n"); 1449219820Sjeff flush_workqueue(wq); 1450219820Sjeff 1451219820Sjefferr_reg: 1452219820Sjeff ib_unregister_device(&ibdev->ib_dev); 1453219820Sjeff 1454219820Sjefferr_counter: 1455219820Sjeff for (; k; --k) 1456219820Sjeff mlx4_counter_free(ibdev->dev, ibdev->counters[k - 1]); 1457219820Sjeff 1458219820Sjefferr_map: 1459219820Sjeff iounmap(ibdev->priv_uar.map); 1460219820Sjeff 1461219820Sjefferr_uar: 1462219820Sjeff mlx4_uar_free(dev, &ibdev->priv_uar); 1463219820Sjeff 1464219820Sjefferr_pd: 1465219820Sjeff mlx4_pd_free(dev, ibdev->priv_pdn); 1466219820Sjeff 1467219820Sjefferr_dealloc: 1468219820Sjeff ib_dealloc_device(&ibdev->ib_dev); 1469219820Sjeff 1470219820Sjeff return NULL; 1471219820Sjeff} 1472219820Sjeff 1473219820Sjeffstatic void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) 1474219820Sjeff{ 1475219820Sjeff struct mlx4_ib_dev *ibdev = ibdev_ptr; 1476219820Sjeff int p; 1477219820Sjeff int k; 1478219820Sjeff 1479219820Sjeff sysfs_remove_group(&ibdev->ib_dev.dev.kobj, &diag_counters_group); 1480219820Sjeff 1481219820Sjeff mlx4_ib_mad_cleanup(ibdev); 1482219820Sjeff ib_unregister_device(&ibdev->ib_dev); 1483219820Sjeff for (k = 0; k < ibdev->num_ports; ++k) 1484219820Sjeff mlx4_counter_free(ibdev->dev, ibdev->counters[k]); 1485219820Sjeff 1486219820Sjeff if (ibdev->iboe.nb.notifier_call) { 1487219820Sjeff unregister_netdevice_notifier(&ibdev->iboe.nb); 1488219820Sjeff flush_workqueue(wq); 1489219820Sjeff ibdev->iboe.nb.notifier_call = NULL; 1490219820Sjeff } 1491219820Sjeff iounmap(ibdev->priv_uar.map); 1492219820Sjeff 1493219820Sjeff mlx4_foreach_port(p, dev, MLX4_PORT_TYPE_IB) 1494219820Sjeff mlx4_CLOSE_PORT(dev, p); 1495219820Sjeff 1496219820Sjeff mlx4_uar_free(dev, &ibdev->priv_uar); 1497219820Sjeff mlx4_pd_free(dev, ibdev->priv_pdn); 1498219820Sjeff ib_dealloc_device(&ibdev->ib_dev); 1499219820Sjeff} 1500219820Sjeff 1501219820Sjeffstatic void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr, 1502219820Sjeff enum mlx4_dev_event event, int port) 1503219820Sjeff{ 1504219820Sjeff struct ib_event ibev; 1505219820Sjeff struct mlx4_ib_dev *ibdev = to_mdev((struct ib_device *) ibdev_ptr); 1506219820Sjeff 1507219820Sjeff if (port > ibdev->num_ports) 1508219820Sjeff return; 1509219820Sjeff 1510219820Sjeff switch (event) { 1511219820Sjeff case MLX4_DEV_EVENT_PORT_UP: 1512219820Sjeff ibev.event = IB_EVENT_PORT_ACTIVE; 1513219820Sjeff break; 1514219820Sjeff 1515219820Sjeff case MLX4_DEV_EVENT_PORT_DOWN: 1516219820Sjeff ibev.event = IB_EVENT_PORT_ERR; 1517219820Sjeff break; 1518219820Sjeff 1519219820Sjeff case MLX4_DEV_EVENT_CATASTROPHIC_ERROR: 1520219820Sjeff ibdev->ib_active = 0; 1521219820Sjeff ibev.event = IB_EVENT_DEVICE_FATAL; 1522219820Sjeff break; 1523219820Sjeff 1524219820Sjeff default: 1525219820Sjeff return; 1526219820Sjeff } 1527219820Sjeff 1528219820Sjeff ibev.device = ibdev_ptr; 1529219820Sjeff ibev.element.port_num = port; 1530219820Sjeff 1531219820Sjeff ib_dispatch_event(&ibev); 1532219820Sjeff} 1533219820Sjeff 1534219820Sjeffstatic struct mlx4_interface mlx4_ib_interface = { 1535219820Sjeff .add = mlx4_ib_add, 1536219820Sjeff .remove = mlx4_ib_remove, 1537219820Sjeff .event = mlx4_ib_event, 1538219820Sjeff .get_prot_dev = get_ibdev, 1539219820Sjeff .protocol = MLX4_PROT_IB, 1540219820Sjeff}; 1541219820Sjeff 1542219820Sjeffstatic int __init mlx4_ib_init(void) 1543219820Sjeff{ 1544219820Sjeff int err; 1545219820Sjeff 1546219820Sjeff wq = create_singlethread_workqueue("mlx4_ib"); 1547219820Sjeff if (!wq) 1548219820Sjeff return -ENOMEM; 1549219820Sjeff 1550219820Sjeff err = mlx4_register_interface(&mlx4_ib_interface); 1551219820Sjeff if (err) { 1552219820Sjeff destroy_workqueue(wq); 1553219820Sjeff return err; 1554219820Sjeff } 1555219820Sjeff 1556219820Sjeff return 0; 1557219820Sjeff} 1558219820Sjeff 1559219820Sjeffstatic void __exit mlx4_ib_cleanup(void) 1560219820Sjeff{ 1561219820Sjeff mlx4_unregister_interface(&mlx4_ib_interface); 1562219820Sjeff destroy_workqueue(wq); 1563219820Sjeff} 1564219820Sjeff 1565219820Sjeffmodule_init_order(mlx4_ib_init, SI_ORDER_MIDDLE); 1566219820Sjeffmodule_exit(mlx4_ib_cleanup); 1567219820Sjeff 1568219820Sjeff#undef MODULE_VERSION 1569219820Sjeff#include <sys/module.h> 1570219820Sjeffstatic int 1571219820Sjeffmlx4ib_evhand(module_t mod, int event, void *arg) 1572219820Sjeff{ 1573219820Sjeff return (0); 1574219820Sjeff} 1575219820Sjeffstatic moduledata_t mlx4ib_mod = { 1576219820Sjeff .name = "mlx4ib", 1577219820Sjeff .evhand = mlx4ib_evhand, 1578219820Sjeff}; 1579219820SjeffDECLARE_MODULE(mlx4ib, mlx4ib_mod, SI_SUB_SMP, SI_ORDER_ANY); 1580219820SjeffMODULE_DEPEND(mlx4ib, mlx4, 1, 1, 1); 1581