Merge tag 'renesas-soc-for-v4.8' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / drivers / infiniband / hw / mlx5 / main.c
index 6ad0489..b48ad85 100644 (file)
@@ -38,6 +38,9 @@
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/io-mapping.h>
+#if defined(CONFIG_X86)
+#include <asm/pat.h>
+#endif
 #include <linux/sched.h>
 #include <rdma/ib_user_verbs.h>
 #include <rdma/ib_addr.h>
@@ -517,6 +520,13 @@ static int mlx5_ib_query_device(struct ib_device *ibdev,
                props->device_cap_flags |= IB_DEVICE_UD_TSO;
        }
 
+       if (MLX5_CAP_GEN(dev->mdev, eth_net_offloads) &&
+           MLX5_CAP_ETH(dev->mdev, scatter_fcs))
+               props->device_cap_flags |= IB_DEVICE_RAW_SCATTER_FCS;
+
+       if (mlx5_get_flow_namespace(dev->mdev, MLX5_FLOW_NAMESPACE_BYPASS))
+               props->device_cap_flags |= IB_DEVICE_MANAGED_FLOW_STEERING;
+
        props->vendor_part_id      = mdev->pdev->device;
        props->hw_ver              = mdev->pdev->revision;
 
@@ -908,7 +918,8 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        num_uars = req.total_num_uuars / MLX5_NON_FP_BF_REGS_PER_PAGE;
        gross_uuars = num_uars * MLX5_BF_REGS_PER_PAGE;
        resp.qp_tab_size = 1 << MLX5_CAP_GEN(dev->mdev, log_max_qp);
-       resp.bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size);
+       if (mlx5_core_is_pf(dev->mdev) && MLX5_CAP_GEN(dev->mdev, bf))
+               resp.bf_reg_size = 1 << MLX5_CAP_GEN(dev->mdev, log_bf_reg_size);
        resp.cache_line_size = L1_CACHE_BYTES;
        resp.max_sq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_sq);
        resp.max_rq_desc_sz = MLX5_CAP_GEN(dev->mdev, max_wqe_sz_rq);
@@ -981,7 +992,14 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        if (field_avail(typeof(resp), cqe_version, udata->outlen))
                resp.response_length += sizeof(resp.cqe_version);
 
-       if (field_avail(typeof(resp), hca_core_clock_offset, udata->outlen)) {
+       /*
+        * We don't want to expose information from the PCI bar that is located
+        * after 4096 bytes, so if the arch only supports larger pages, let's
+        * pretend we don't support reading the HCA's core clock. This is also
+        * forced by mmap function.
+        */
+       if (PAGE_SIZE <= 4096 &&
+           field_avail(typeof(resp), hca_core_clock_offset, udata->outlen)) {
                resp.comp_mask |=
                        MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_CORE_CLOCK_OFFSET;
                resp.hca_core_clock_offset =
@@ -1068,38 +1086,89 @@ static int get_index(unsigned long offset)
        return get_arg(offset);
 }
 
+static inline char *mmap_cmd2str(enum mlx5_ib_mmap_cmd cmd)
+{
+       switch (cmd) {
+       case MLX5_IB_MMAP_WC_PAGE:
+               return "WC";
+       case MLX5_IB_MMAP_REGULAR_PAGE:
+               return "best effort WC";
+       case MLX5_IB_MMAP_NC_PAGE:
+               return "NC";
+       default:
+               return NULL;
+       }
+}
+
+static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,
+                   struct vm_area_struct *vma, struct mlx5_uuar_info *uuari)
+{
+       int err;
+       unsigned long idx;
+       phys_addr_t pfn, pa;
+       pgprot_t prot;
+
+       switch (cmd) {
+       case MLX5_IB_MMAP_WC_PAGE:
+/* Some architectures don't support WC memory */
+#if defined(CONFIG_X86)
+               if (!pat_enabled())
+                       return -EPERM;
+#elif !(defined(CONFIG_PPC) || (defined(CONFIG_ARM) && defined(CONFIG_MMU)))
+                       return -EPERM;
+#endif
+       /* fall through */
+       case MLX5_IB_MMAP_REGULAR_PAGE:
+               /* For MLX5_IB_MMAP_REGULAR_PAGE do the best effort to get WC */
+               prot = pgprot_writecombine(vma->vm_page_prot);
+               break;
+       case MLX5_IB_MMAP_NC_PAGE:
+               prot = pgprot_noncached(vma->vm_page_prot);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (vma->vm_end - vma->vm_start != PAGE_SIZE)
+               return -EINVAL;
+
+       idx = get_index(vma->vm_pgoff);
+       if (idx >= uuari->num_uars)
+               return -EINVAL;
+
+       pfn = uar_index2pfn(dev, uuari->uars[idx].index);
+       mlx5_ib_dbg(dev, "uar idx 0x%lx, pfn %pa\n", idx, &pfn);
+
+       vma->vm_page_prot = prot;
+       err = io_remap_pfn_range(vma, vma->vm_start, pfn,
+                                PAGE_SIZE, vma->vm_page_prot);
+       if (err) {
+               mlx5_ib_err(dev, "io_remap_pfn_range failed with error=%d, vm_start=0x%lx, pfn=%pa, mmap_cmd=%s\n",
+                           err, vma->vm_start, &pfn, mmap_cmd2str(cmd));
+               return -EAGAIN;
+       }
+
+       pa = pfn << PAGE_SHIFT;
+       mlx5_ib_dbg(dev, "mapped %s at 0x%lx, PA %pa\n", mmap_cmd2str(cmd),
+                   vma->vm_start, &pa);
+
+       return 0;
+}
+
 static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma)
 {
        struct mlx5_ib_ucontext *context = to_mucontext(ibcontext);
        struct mlx5_ib_dev *dev = to_mdev(ibcontext->device);
        struct mlx5_uuar_info *uuari = &context->uuari;
        unsigned long command;
-       unsigned long idx;
        phys_addr_t pfn;
 
        command = get_command(vma->vm_pgoff);
        switch (command) {
+       case MLX5_IB_MMAP_WC_PAGE:
+       case MLX5_IB_MMAP_NC_PAGE:
        case MLX5_IB_MMAP_REGULAR_PAGE:
-               if (vma->vm_end - vma->vm_start != PAGE_SIZE)
-                       return -EINVAL;
-
-               idx = get_index(vma->vm_pgoff);
-               if (idx >= uuari->num_uars)
-                       return -EINVAL;
-
-               pfn = uar_index2pfn(dev, uuari->uars[idx].index);
-               mlx5_ib_dbg(dev, "uar idx 0x%lx, pfn 0x%llx\n", idx,
-                           (unsigned long long)pfn);
-
-               vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-               if (io_remap_pfn_range(vma, vma->vm_start, pfn,
-                                      PAGE_SIZE, vma->vm_page_prot))
-                       return -EAGAIN;
-
-               mlx5_ib_dbg(dev, "mapped WC at 0x%lx, PA 0x%llx\n",
-                           vma->vm_start,
-                           (unsigned long long)pfn << PAGE_SHIFT);
-               break;
+               return uar_mmap(dev, command, vma, uuari);
 
        case MLX5_IB_MMAP_GET_CONTIGUOUS_PAGES:
                return -ENOSYS;
@@ -1108,7 +1177,7 @@ static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vm
                if (vma->vm_end - vma->vm_start != PAGE_SIZE)
                        return -EINVAL;
 
-               if (vma->vm_flags & (VM_WRITE | VM_EXEC))
+               if (vma->vm_flags & VM_WRITE)
                        return -EPERM;
 
                /* Don't expose to user-space information it shouldn't have */
@@ -1438,7 +1507,8 @@ static struct mlx5_ib_flow_prio *get_flow_table(struct mlx5_ib_dev *dev,
        if (!ft) {
                ft = mlx5_create_auto_grouped_flow_table(ns, priority,
                                                         num_entries,
-                                                        num_groups);
+                                                        num_groups,
+                                                        0);
 
                if (!IS_ERR(ft)) {
                        prio->refcount = 0;
@@ -1739,7 +1809,7 @@ static ssize_t show_fw_ver(struct device *device, struct device_attribute *attr,
 {
        struct mlx5_ib_dev *dev =
                container_of(device, struct mlx5_ib_dev, ib_dev.dev);
-       return sprintf(buf, "%d.%d.%d\n", fw_rev_maj(dev->mdev),
+       return sprintf(buf, "%d.%d.%04d\n", fw_rev_maj(dev->mdev),
                       fw_rev_min(dev->mdev), fw_rev_sub(dev->mdev));
 }
 
@@ -1807,14 +1877,11 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
                break;
 
        case MLX5_DEV_EVENT_PORT_DOWN:
+       case MLX5_DEV_EVENT_PORT_INITIALIZED:
                ibev.event = IB_EVENT_PORT_ERR;
                port = (u8)param;
                break;
 
-       case MLX5_DEV_EVENT_PORT_INITIALIZED:
-               /* not used by ULPs */
-               return;
-
        case MLX5_DEV_EVENT_LID_CHANGE:
                ibev.event = IB_EVENT_LID_CHANGE;
                port = (u8)param;