include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / infiniband / hw / mlx4 / main.c
index 4d9b5ac..01f2a3f 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
  *
  * This software is available to you under a choice of one of two
  * licenses.  You may choose to be licensed under the terms of the GNU
@@ -32,6 +33,7 @@
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/slab.h>
 #include <linux/errno.h>
 
 #include <rdma/ib_smi.h>
@@ -90,7 +92,8 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
        props->device_cap_flags    = IB_DEVICE_CHANGE_PHY_PORT |
                IB_DEVICE_PORT_ACTIVE_EVENT             |
                IB_DEVICE_SYS_IMAGE_GUID                |
-               IB_DEVICE_RC_RNR_NAK_GEN;
+               IB_DEVICE_RC_RNR_NAK_GEN                |
+               IB_DEVICE_BLOCK_MULTICAST_LOOPBACK;
        if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_PKEY_CNTR)
                props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR;
        if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_QKEY_CNTR)
@@ -101,8 +104,14 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
                props->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE;
        if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM)
                props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM;
-       if (dev->dev->caps.max_gso_sz)
+       if (dev->dev->caps.max_gso_sz && dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BLH)
                props->device_cap_flags |= IB_DEVICE_UD_TSO;
+       if (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_RESERVED_LKEY)
+               props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY;
+       if ((dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_LOCAL_INV) &&
+           (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_REMOTE_INV) &&
+           (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_FAST_REG_WR))
+               props->device_cap_flags |= IB_DEVICE_MEM_MGT_EXTENSIONS;
 
        props->vendor_id           = be32_to_cpup((__be32 *) (out_mad->data + 36)) &
                0xffffff;
@@ -126,6 +135,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev,
        props->max_srq             = dev->dev->caps.num_srqs - dev->dev->caps.reserved_srqs;
        props->max_srq_wr          = dev->dev->caps.max_srq_wqes - 1;
        props->max_srq_sge         = dev->dev->caps.max_srq_sge;
+       props->max_fast_reg_page_list_len = PAGE_SIZE / sizeof (u64);
        props->local_ca_ack_delay  = dev->dev->caps.local_ca_ack_delay;
        props->atomic_cap          = dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_ATOMIC ?
                IB_ATOMIC_HCA : IB_ATOMIC_NONE;
@@ -333,6 +343,9 @@ static struct ib_ucontext *mlx4_ib_alloc_ucontext(struct ib_device *ibdev,
        struct mlx4_ib_alloc_ucontext_resp resp;
        int err;
 
+       if (!dev->ib_active)
+               return ERR_PTR(-EAGAIN);
+
        resp.qp_tab_size      = dev->dev->caps.num_qps;
        resp.bf_reg_size      = dev->dev->caps.bf_reg_size;
        resp.bf_regs_per_page = dev->dev->caps.bf_regs_per_page;
@@ -385,8 +398,7 @@ static int mlx4_ib_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
                                       PAGE_SIZE, vma->vm_page_prot))
                        return -EAGAIN;
        } else if (vma->vm_pgoff == 1 && dev->dev->caps.bf_reg_size != 0) {
-               /* FIXME want pgprot_writecombine() for BlueFlame pages */
-               vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+               vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
 
                if (io_remap_pfn_range(vma, vma->vm_start,
                                       to_mucontext(context)->uar.pfn +
@@ -437,7 +449,9 @@ static int mlx4_ib_dealloc_pd(struct ib_pd *pd)
 static int mlx4_ib_mcg_attach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
 {
        return mlx4_multicast_attach(to_mdev(ibqp->device)->dev,
-                                    &to_mqp(ibqp)->mqp, gid->raw);
+                                    &to_mqp(ibqp)->mqp, gid->raw,
+                                    !!(to_mqp(ibqp)->flags &
+                                       MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK));
 }
 
 static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid)
@@ -530,15 +544,18 @@ static struct device_attribute *mlx4_class_attributes[] = {
 
 static void *mlx4_ib_add(struct mlx4_dev *dev)
 {
-       static int mlx4_ib_version_printed;
        struct mlx4_ib_dev *ibdev;
+       int num_ports = 0;
        int i;
 
+       printk_once(KERN_INFO "%s", mlx4_ib_version);
 
-       if (!mlx4_ib_version_printed) {
-               printk(KERN_INFO "%s", mlx4_ib_version);
-               ++mlx4_ib_version_printed;
-       }
+       mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB)
+               num_ports++;
+
+       /* No point in registering a device with no ports... */
+       if (num_ports == 0)
+               return NULL;
 
        ibdev = (struct mlx4_ib_dev *) ib_alloc_device(sizeof *ibdev);
        if (!ibdev) {
@@ -557,16 +574,15 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
                goto err_uar;
        MLX4_INIT_DOORBELL_LOCK(&ibdev->uar_lock);
 
-       INIT_LIST_HEAD(&ibdev->pgdir_list);
-       mutex_init(&ibdev->pgdir_mutex);
-
        ibdev->dev = dev;
 
        strlcpy(ibdev->ib_dev.name, "mlx4_%d", IB_DEVICE_NAME_MAX);
        ibdev->ib_dev.owner             = THIS_MODULE;
        ibdev->ib_dev.node_type         = RDMA_NODE_IB_CA;
-       ibdev->ib_dev.phys_port_cnt     = dev->caps.num_ports;
-       ibdev->ib_dev.num_comp_vectors  = 1;
+       ibdev->ib_dev.local_dma_lkey    = dev->caps.reserved_lkey;
+       ibdev->num_ports                = num_ports;
+       ibdev->ib_dev.phys_port_cnt     = ibdev->num_ports;
+       ibdev->ib_dev.num_comp_vectors  = dev->caps.num_comp_vectors;
        ibdev->ib_dev.dma_device        = &dev->pdev->dev;
 
        ibdev->ib_dev.uverbs_abi_ver    = MLX4_IB_UVERBS_ABI_VERSION;
@@ -627,6 +643,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
        ibdev->ib_dev.get_dma_mr        = mlx4_ib_get_dma_mr;
        ibdev->ib_dev.reg_user_mr       = mlx4_ib_reg_user_mr;
        ibdev->ib_dev.dereg_mr          = mlx4_ib_dereg_mr;
+       ibdev->ib_dev.alloc_fast_reg_mr = mlx4_ib_alloc_fast_reg_mr;
+       ibdev->ib_dev.alloc_fast_reg_page_list = mlx4_ib_alloc_fast_reg_page_list;
+       ibdev->ib_dev.free_fast_reg_page_list  = mlx4_ib_free_fast_reg_page_list;
        ibdev->ib_dev.attach_mcast      = mlx4_ib_mcg_attach;
        ibdev->ib_dev.detach_mcast      = mlx4_ib_mcg_detach;
        ibdev->ib_dev.process_mad       = mlx4_ib_process_mad;
@@ -654,6 +673,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev)
                        goto err_reg;
        }
 
+       ibdev->ib_active = true;
+
        return ibdev;
 
 err_reg:
@@ -679,11 +700,12 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
        struct mlx4_ib_dev *ibdev = ibdev_ptr;
        int p;
 
-       for (p = 1; p <= dev->caps.num_ports; ++p)
-               mlx4_CLOSE_PORT(dev, p);
-
        mlx4_ib_mad_cleanup(ibdev);
        ib_unregister_device(&ibdev->ib_dev);
+
+       for (p = 1; p <= ibdev->num_ports; ++p)
+               mlx4_CLOSE_PORT(dev, p);
+
        iounmap(ibdev->uar_map);
        mlx4_uar_free(dev, &ibdev->priv_uar);
        mlx4_pd_free(dev, ibdev->priv_pdn);
@@ -694,6 +716,10 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
                          enum mlx4_dev_event event, int port)
 {
        struct ib_event ibev;
+       struct mlx4_ib_dev *ibdev = to_mdev((struct ib_device *) ibdev_ptr);
+
+       if (port > ibdev->num_ports)
+               return;
 
        switch (event) {
        case MLX4_DEV_EVENT_PORT_UP:
@@ -705,6 +731,7 @@ static void mlx4_ib_event(struct mlx4_dev *dev, void *ibdev_ptr,
                break;
 
        case MLX4_DEV_EVENT_CATASTROPHIC_ERROR:
+               ibdev->ib_active = false;
                ibev.event = IB_EVENT_DEVICE_FATAL;
                break;