mlx4: Activate SR-IOV mode for IB
[pandora-kernel.git] / drivers / infiniband / hw / mlx4 / main.c
index 45a6cc0..e849347 100644 (file)
@@ -59,6 +59,10 @@ MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_VERSION(DRV_VERSION);
 
+int mlx4_ib_sm_guid_assign = 1;
+module_param_named(sm_guid_assign, mlx4_ib_sm_guid_assign, int, 0444);
+MODULE_PARM_DESC(sm_guid_assign, "Enable SM alias_GUID assignment if sm_guid_assign > 0 (Default: 1)");
+
 static const char mlx4_ib_version[] =
        DRV_NAME ": Mellanox ConnectX InfiniBand driver v"
        DRV_VERSION " (" DRV_RELDATE ")\n";
@@ -134,7 +138,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
 
        props->vendor_id           = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
                0xffffff;
-       props->vendor_part_id      = be16_to_cpup((__be16 *) (out_mad->data + 30));
+       props->vendor_part_id      = dev->dev->pdev->device;
        props->hw_ver              = be32_to_cpup((__be32 *) (out_mad->data + 32));
        memcpy(&props->sys_image_guid, out_mad->data +  4, 8);
 
@@ -349,12 +353,15 @@ static int mlx4_ib_query_port(struct ib_device *ibdev, u8 port,
        return __mlx4_ib_query_port(ibdev, port, props, 0);
 }
 
-static int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
-                              union ib_gid *gid)
+int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
+                       union ib_gid *gid, int netw_view)
 {
        struct ib_smp *in_mad  = NULL;
        struct ib_smp *out_mad = NULL;
        int err = -ENOMEM;
+       struct mlx4_ib_dev *dev = to_mdev(ibdev);
+       int clear = 0;
+       int mad_ifc_flags = MLX4_MAD_IFC_IGNORE_KEYS;
 
        in_mad  = kzalloc(sizeof *in_mad, GFP_KERNEL);
        out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL);
@@ -365,18 +372,29 @@ static int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
        in_mad->attr_id  = IB_SMP_ATTR_PORT_INFO;
        in_mad->attr_mod = cpu_to_be32(port);
 
-       err = mlx4_MAD_IFC(to_mdev(ibdev), MLX4_MAD_IFC_IGNORE_KEYS, port,
-                          NULL, NULL, in_mad, out_mad);
+       if (mlx4_is_mfunc(dev->dev) && netw_view)
+               mad_ifc_flags |= MLX4_MAD_IFC_NET_VIEW;
+
+       err = mlx4_MAD_IFC(dev, mad_ifc_flags, port, NULL, NULL, in_mad, out_mad);
        if (err)
                goto out;
 
        memcpy(gid->raw, out_mad->data + 8, 8);
 
+       if (mlx4_is_mfunc(dev->dev) && !netw_view) {
+               if (index) {
+                       /* For any index > 0, return the null guid */
+                       err = 0;
+                       clear = 1;
+                       goto out;
+               }
+       }
+
        init_query_mad(in_mad);
        in_mad->attr_id  = IB_SMP_ATTR_GUID_INFO;
        in_mad->attr_mod = cpu_to_be32(index / 8);
 
-       err = mlx4_MAD_IFC(to_mdev(ibdev), MLX4_MAD_IFC_IGNORE_KEYS, port,
+       err = mlx4_MAD_IFC(dev, mad_ifc_flags, port,
                           NULL, NULL, in_mad, out_mad);
        if (err)
                goto out;
@@ -384,6 +402,8 @@ static int __mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
        memcpy(gid->raw + 8, out_mad->data + (index % 8) * 8, 8);
 
 out:
+       if (clear)
+               memset(gid->raw + 8, 0, 8);
        kfree(in_mad);
        kfree(out_mad);
        return err;
@@ -403,7 +423,7 @@ static int mlx4_ib_query_gid(struct ib_device *ibdev, u8 port, int index,
                             union ib_gid *gid)
 {
        if (rdma_port_get_link_layer(ibdev, port) == IB_LINK_LAYER_INFINIBAND)
-               return __mlx4_ib_query_gid(ibdev, port, index, gid);
+               return __mlx4_ib_query_gid(ibdev, port, index, gid, 0);
        else
                return iboe_query_gid(ibdev, port, index, gid);
 }
@@ -458,6 +478,9 @@ static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask,
        if (!(mask & IB_DEVICE_MODIFY_NODE_DESC))
                return 0;
 
+       if (mlx4_is_slave(to_mdev(ibdev)->dev))
+               return -EOPNOTSUPP;
+
        spin_lock_irqsave(&to_mdev(ibdev)->sm_lock, flags);
        memcpy(ibdev->node_desc, props->node_desc, 64);
        spin_unlock_irqrestore(&to_mdev(ibdev)->sm_lock, flags);
@@ -473,7 +496,7 @@ static int mlx4_ib_modify_device(struct ib_device *ibdev, int mask,
        memset(mailbox->buf, 0, 256);
        memcpy(mailbox->buf, props->node_desc, 64);
        mlx4_cmd(to_mdev(ibdev)->dev, mailbox->dma, 1, 0,
-                MLX4_CMD_SET_NODE, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_WRAPPED);
+                MLX4_CMD_SET_NODE, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
 
        mlx4_free_cmd_mailbox(to_mdev(ibdev)->dev, mailbox);
 
@@ -901,6 +924,7 @@ static int init_node_data(struct mlx4_ib_dev *dev)
        if (err)
                goto out;
 
+       dev->dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32));
        memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
 
 out:
@@ -989,7 +1013,7 @@ static void update_gids_task(struct work_struct *work)
 
        err = mlx4_cmd(dev, mailbox->dma, MLX4_SET_PORT_GID_TABLE << 8 | gw->port,
                       1, MLX4_CMD_SET_PORT, MLX4_CMD_TIME_CLASS_B,
-                      MLX4_CMD_NATIVE);
+                      MLX4_CMD_WRAPPED);
        if (err)
                pr_warn("set port command failed\n");
        else {
@@ -1269,11 +1293,15 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
 
        pr_info_once("%s", mlx4_ib_version);
 
-       if (mlx4_is_mfunc(dev)) {
-               pr_warn("IB not yet supported in SRIOV\n");
+       mlx4_foreach_non_ib_transport_port(i, dev)
+               num_ports++;
+
+       if (mlx4_is_mfunc(dev) && num_ports) {
+               dev_err(&dev->pdev->dev, "RoCE is not supported over SRIOV as yet\n");
                return NULL;
        }
 
+       num_ports = 0;
        mlx4_foreach_ib_transport_port(i, dev)
                num_ports++;
 
@@ -1380,10 +1408,12 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
        ibdev->ib_dev.detach_mcast      = mlx4_ib_mcg_detach;
        ibdev->ib_dev.process_mad       = mlx4_ib_process_mad;
 
-       ibdev->ib_dev.alloc_fmr         = mlx4_ib_fmr_alloc;
-       ibdev->ib_dev.map_phys_fmr      = mlx4_ib_map_phys_fmr;
-       ibdev->ib_dev.unmap_fmr         = mlx4_ib_unmap_fmr;
-       ibdev->ib_dev.dealloc_fmr       = mlx4_ib_fmr_dealloc;
+       if (!mlx4_is_slave(ibdev->dev)) {
+               ibdev->ib_dev.alloc_fmr         = mlx4_ib_fmr_alloc;
+               ibdev->ib_dev.map_phys_fmr      = mlx4_ib_map_phys_fmr;
+               ibdev->ib_dev.unmap_fmr         = mlx4_ib_unmap_fmr;
+               ibdev->ib_dev.dealloc_fmr       = mlx4_ib_fmr_dealloc;
+       }
 
        if (dev->caps.flags & MLX4_DEV_CAP_FLAG_XRC) {
                ibdev->ib_dev.alloc_xrcd = mlx4_ib_alloc_xrcd;
@@ -1566,6 +1596,11 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
        case MLX4_DEV_EVENT_PORT_UP:
                if (p > ibdev->num_ports)
                        return;
+               if (mlx4_is_master(dev) &&
+                   rdma_port_get_link_layer(&ibdev->ib_dev, p) ==
+                       IB_LINK_LAYER_INFINIBAND) {
+                       mlx4_ib_invalidate_all_guid_record(ibdev, p);
+               }
                ibev.event = IB_EVENT_PORT_ACTIVE;
                break;
 
@@ -1590,7 +1625,11 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
                INIT_WORK(&ew->work, handle_port_mgmt_change_event);
                memcpy(&ew->ib_eqe, eqe, sizeof *eqe);
                ew->ib_dev = ibdev;
-               handle_port_mgmt_change_event(&ew->work);
+               /* need to queue only for port owner, which uses GEN_EQE */
+               if (mlx4_is_master(dev))
+                       queue_work(wq, &ew->work);
+               else
+                       handle_port_mgmt_change_event(&ew->work);
                return;
 
        case MLX4_DEV_EVENT_SLAVE_INIT:
@@ -1628,18 +1667,28 @@ static int __init mlx4_ib_init(void)
        if (!wq)
                return -ENOMEM;
 
+       err = mlx4_ib_mcg_init();
+       if (err)
+               goto clean_wq;
+
        err = mlx4_register_interface(&mlx4_ib_interface);
-       if (err) {
-               destroy_workqueue(wq);
-               return err;
-       }
+       if (err)
+               goto clean_mcg;
 
        return 0;
+
+clean_mcg:
+       mlx4_ib_mcg_destroy();
+
+clean_wq:
+       destroy_workqueue(wq);
+       return err;
 }
 
 static void __exit mlx4_ib_cleanup(void)
 {
        mlx4_unregister_interface(&mlx4_ib_interface);
+       mlx4_ib_mcg_destroy();
        destroy_workqueue(wq);
 }