]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
sif driver initial commit part 4
authorWei Lin Guay <wei.lin.guay@oracle.com>
Tue, 24 May 2016 07:37:22 +0000 (09:37 +0200)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Tue, 31 May 2016 15:41:16 +0000 (08:41 -0700)
sif_tqp.h:       Implementation of EPSA tunnelling QP for SIF
sif_user.h:      This file defines sif specific verbs extension request/response.
sif_verbs.c:     IB verbs API extensions specific to PSIF
sif_verbs.h:     IB verbs API extensions specific to PSIF
sif_vf.c:        SR/IOV support functions
sif_vf.h:        SR/IOV support functions
sif_xmmu.c:      Implementation of special MMU mappings.
sif_xmmu.h:      Implementation of special MMU mappings.
sif_xrc.c:       Implementation of XRC related functions
sif_xrc.h:       XRC related functions
version.h:       Detailed version info data structure

Signed-off-by: Knut Omang <knut.omang@oracle.com>
drivers/infiniband/hw/sif/sif_tqp.h [new file with mode: 0644]
drivers/infiniband/hw/sif/sif_user.h [new file with mode: 0644]
drivers/infiniband/hw/sif/sif_verbs.c [new file with mode: 0644]
drivers/infiniband/hw/sif/sif_verbs.h [new file with mode: 0644]
drivers/infiniband/hw/sif/sif_vf.c [new file with mode: 0644]
drivers/infiniband/hw/sif/sif_vf.h [new file with mode: 0644]
drivers/infiniband/hw/sif/sif_xmmu.c [new file with mode: 0644]
drivers/infiniband/hw/sif/sif_xmmu.h [new file with mode: 0644]
drivers/infiniband/hw/sif/sif_xrc.c [new file with mode: 0644]
drivers/infiniband/hw/sif/sif_xrc.h [new file with mode: 0644]
drivers/infiniband/hw/sif/version.h [new file with mode: 0644]

diff --git a/drivers/infiniband/hw/sif/sif_tqp.h b/drivers/infiniband/hw/sif/sif_tqp.h
new file mode 100644 (file)
index 0000000..857d45a
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Wei Lin Guay <wei.lin.guay@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * Driver for Oracle Scalable Infiniband Fabric (SIF) Host Channel Adapters
+ *
+ * sif_tqp.h: Implementation of EPSA tunnelling QP for SIF
+ */
+
+#ifndef __SIF_TQP_H
+#define __SIF_TQP_H
+#include <rdma/ib_verbs.h>
+#include "sif_dev.h"
+#include "sif_base.h"
+#include "sif_epsc.h"
+#include "sif_cq.h"
+
+static inline enum psif_mbox_type u32_to_mbox(u32 proxy)
+{
+       switch (proxy) {
+       case 0:
+               return MBOX_EPSA0;
+       case 1:
+               return MBOX_EPSA1;
+       case 2:
+               return MBOX_EPSA2;
+       case 3:
+               return MBOX_EPSA3;
+       default:
+               break;
+       }
+       return (enum psif_mbox_type) -1;
+}
+
+extern int sif_epsa_tunneling_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
+                                       struct ib_send_wr **bad_wr);
+
+#endif
+
diff --git a/drivers/infiniband/hw/sif/sif_user.h b/drivers/infiniband/hw/sif/sif_user.h
new file mode 100644 (file)
index 0000000..b46211b
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Knut Omang <knut.omang@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * Driver for Oracle Scalable Infiniband Fabric (SIF) Host Channel Adapters
+ *
+ * sif_user.h: This file defines sif specific verbs extension request/response.
+ */
+
+#ifndef _SIF_USER_H
+#define _SIF_USER_H
+
+/* Binary interface control:
+ *   Major version difference indicate backward incompatible changes
+ *   Minor version difference indicate that only a common subset of
+ *   features are available.
+ *
+ */
+#define SIF_UVERBS_ABI_MAJOR_VERSION    3
+#define SIF_UVERBS_ABI_MINOR_VERSION    4
+
+#define SIF_UVERBS_VERSION(x, y) ((x) << 8 | (y))
+
+#define SIF_UVERBS_ABI_VERSION \
+       SIF_UVERBS_VERSION(SIF_UVERBS_ABI_MAJOR_VERSION, SIF_UVERBS_ABI_MINOR_VERSION)
+
+/*
+ * Bit 5 is not used by the PSIF_WC_OPCODE_FOO_BAR enums. Hence, using
+ * it to indicate if QP has been destroyed before the CQE has been
+ * polled
+ */
+#define SIF_WC_QP_DESTROYED (1<<5)
+
+/*
+ * This struct will be amended to an un-polled cqe, in case the QP has
+ * been destroyed before the CQEs are polled. The information is
+ * needed in order to handle flushing of SRQs and generation of Last
+ * WQE Reached event.
+ *
+ * The information amended to the CQE is _only_ valid if the CQE has
+ * been marked with SIF_WC_QP_DESTROYED.
+ */
+struct sif_post_mortem_qp_info_in_cqe {
+       bool was_srq;
+       int srq_idx;
+       int qpn; /* Could be useful for de-bugging/logging */
+};
+
+
+#ifndef _SIF_H
+/* These definitions must be kept in sync with
+ * the ones in libsif's sif.h
+ */
+enum sif_vendor_flags {
+       MMU_special   =  0x1,   /* Use special mmu setup in associated mappings
+                                * NB! Modifies input to ibv_reg_mr!
+                                */
+       SQ_mode       =  0x2,   /* Trigger send queue mode instead of using VCBs */
+       proxy_mode    =  0x4,   /* Enable EPS-A proxying - requires the eps_a field to be set */
+       SVF_kernel_mode =  0x8, /* Enable kernel mode - default is direct user mode */
+       tsu_qosl      = 0x10,   /* Value to use for the qosl bit in the qp state */
+       no_checksum   = 0x20,   /* No csum for qp, wqe.wr.csum = qp.magic */
+       dynamic_mtu   = 0x40,   /* dynamic MTU - use 256B instead of the path MTU */
+};
+
+enum sif_mem_type {
+       SIFMT_BYPASS,    /* Use MMU bypass in associated mmu contexts */
+       SIFMT_UMEM,      /* Normal default umem based user level mapping */
+       SIFMT_UMEM_SPT,  /* Mapping of user memory based on the process' own page table */
+       SIFMT_CS,        /* A large (sparsely populated) SIF only vaddr mapping (used for SQ CMPL) */
+       SIFMT_ZERO,      /* Special mapping of a vaddr range to a single page (see #1931) */
+       SIFMT_BYPASS_RO, /* MMU bypass mapped read only for device (requires IOMMU enabled) */
+       SIFMT_UMEM_RO,   /* GVA2GPA mapped read only for device (requires IOMMU enabled) */
+       SIFMT_PHYS,      /* Use GVA2GPA but input is based on a phys_buf array instead of umem */
+       SIFMT_FMR,       /* Use GVA2GPA but input is based on a page address array instead of umem */
+       SIFMT_2M,        /* sif_kmem based 2M page allocation */
+       SIFMT_NOMEM,     /* Bypass mode - special kernel mappings with no memory allocated */
+       SIFMT_4K,        /* sif_kmem based 4K page allocation */
+       SIFMT_PTONLY,    /* No memory allocated but full page table needed (FMR init) */
+       SIFMT_MAX
+};
+
+enum sif_proxy_type {
+       SIFPX_OFF, /* Default value - no proxying */
+       SIFPX_EPSA_1,
+       SIFPX_EPSA_2,
+       SIFPX_EPSA_3,
+       SIFPX_EPSA_4
+};
+
+enum sif_flush_type {
+       NO_FLUSH,
+       FLUSH_SQ,
+       FLUSH_RQ
+};
+#endif
+
+/* These should be multiple of 64 bytes and densely packed: */
+
+struct sif_get_context_ext {
+       __u32 abi_version;  /* Let the driver know which version we are */
+       __u32 reserved;
+};
+
+struct sif_get_context_resp_ext {
+       __u32 sq_sw_ext_sz;        /* Distance in bytes between descriptor elements */
+       __u32 rq_ext_sz;
+       __u32 cq_ext_sz;
+       __u32 sq_entry_per_block;  /* Number of entries per block of descriptors */
+       __u32 rq_entry_per_block;
+       __u32 cq_entry_per_block;
+       __u32 sq_hw_ext_sz;        /* Dist between sq hw descriptor elms, from >= v.3.3 */
+       __u32 reserved;
+};
+
+struct sif_alloc_pd_resp_ext {
+       __u32 cb_idx;  /* The virtual collect buffer to use by this protection domain */
+       __u32 reserved;
+};
+
+/* TBD: We must filter this structure before we go upstream */
+struct sif_share_pd_resp_ext {
+       __u32 cb_idx;  /* The virtual collect buffer to use by this shared protection domain */
+       __u32 reserved;
+};
+
+struct sif_create_cq_ext {
+       enum sif_vendor_flags flags;
+       enum sif_proxy_type proxy;
+};
+
+struct sif_create_cq_resp_ext {
+       __u32 cq_idx;
+       __u32 reserved;
+};
+
+struct sif_create_qp_ext {
+       enum sif_vendor_flags flags;
+       enum sif_proxy_type proxy;
+};
+
+struct sif_create_qp_resp_ext {
+       __u32 qp_idx;
+       __u32 rq_idx;
+       __u32 magic;
+       __u32 sq_extent;
+       __u32 rq_extent;
+       __u32 sq_sgl_offset;
+       __u32 sq_mr_idx;
+       __u32 reserved;
+       __u64 sq_dma_handle;
+};
+
+struct sif_modify_qp_ext {
+       enum sif_flush_type flush;
+       __u32 reserved;
+};
+
+struct sif_reg_mr_ext {
+       enum sif_vendor_flags flags;
+       enum sif_mem_type mem_type;
+       __u64 map_length;  /* Used by gva_type SIFGT_ZERO - indicates psif vmap length */
+       __u64 phys_length; /* Used by gva_type SIFGT_ZERO - indicates valid memory length */
+};
+
+struct sif_reg_mr_resp_ext {
+       __u64 uv2dma;  /* Used to support bypass mode */
+};
+
+struct sif_create_srq_ext {
+       enum sif_vendor_flags flags;
+       __u32 res1;
+};
+
+struct sif_create_srq_resp_ext {
+       __u32 index;
+       __u32 extent;
+};
+
+struct sif_create_ah_resp_ext {
+       __u32 index;
+       __u32 reserved;
+};
+
+/* mmap offset encoding */
+
+enum sif_mmap_cmd {
+       SIF_MAP_NONE,   /* No mapping */
+       SIF_MAP_CB,     /* Map a collect buffer - cb index as argument */
+       SIF_MAP_SQ,     /* Map an SQ,RQ or CQ (entries) - queue index as argument */
+       SIF_MAP_RQ,
+       SIF_MAP_CQ,
+       SIF_MAP_SQ_SW,  /* Map a block of SQ,RQ or CQ software descriptors - block index as argument */
+       SIF_MAP_RQ_SW,
+       SIF_MAP_CQ_SW,
+       /* These are safe to map read-only (so far only sq_hw in use) */
+       SIF_MAP_QP,     /* Map a block of qp descriptors - block index as argument */
+       SIF_MAP_SQ_HW,  /* Map a block of SQ,RQ or CQ hardware descriptors - block index as argument */
+       SIF_MAP_RQ_HW,
+       SIF_MAP_CQ_HW,
+       SIF_MAP_MAX
+};
+
+
+#define SIF_MCMD_SHIFT (PAGE_SHIFT + 32)
+
+static inline __u64 mmap_set_cmd(enum sif_mmap_cmd cmd, __u32 index)
+{
+       return ((__u64)cmd << SIF_MCMD_SHIFT) | ((__u64)index << PAGE_SHIFT);
+}
+
+static inline void mmap_get_cmd(__u64 offset, enum sif_mmap_cmd *cmdp, __u32 *idxp)
+{
+       *cmdp = (enum sif_mmap_cmd)((offset >> SIF_MCMD_SHIFT) & 0xff);
+       *idxp = (offset >> PAGE_SHIFT) & 0xffffffff;
+}
+
+#endif
diff --git a/drivers/infiniband/hw/sif/sif_verbs.c b/drivers/infiniband/hw/sif/sif_verbs.c
new file mode 100644 (file)
index 0000000..0525ccc
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Knut Omang <knut.omang@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * Driver for Oracle Scalable Infiniband Fabric (SIF) Host Channel Adapters
+ *
+ * sif_verbs.c: IB verbs API extensions specific to PSIF
+ */
+
+#include <linux/module.h>
+#include "sif_verbs.h"
+#include "sif_dev.h"
+#include "sif_epsc.h"
+#include "psif_hw_data.h"
+#include "psif_hw_csr.h"
+
+/* Set/get the 48 bit ethernet mac address for a port */
+int sif_get_mac(struct ib_device *dev, u8 port, u16 uf, u64 *address)
+{
+       int ret = 0;
+       struct sif_dev *sdev = to_sdev(dev);
+       struct psif_epsc_csr_rsp cqe;
+       struct psif_epsc_csr_req req;
+
+       if (port > 2)
+               return -ENODEV;
+
+       memset(&req, 0, sizeof(req));
+
+       req.opcode = EPSC_QUERY;
+       req.uf = uf;
+       req.u.query.info.op = EPSC_QUERY_VPD_MAC;
+       req.u.query.info.index = port;
+       req.u.query.data.op = EPSC_QUERY_BLANK; /* Single query */
+
+       ret = sif_epsc_wr(sdev, &req, &cqe);
+       if (ret) {
+               *address = 0;
+               sif_log(sdev, SIF_INFO, "Failed with status %d", ret);
+       } else {
+               *address = cqe.info;
+       }
+       return ret;
+}
+EXPORT_SYMBOL(sif_get_mac);
+
+int sif_set_mac(struct ib_device *dev, u8 port, u16 uf, u64 address)
+{
+       int ret = 0;
+       struct sif_dev *sdev = to_sdev(dev);
+       struct psif_epsc_csr_rsp cqe;
+       struct psif_epsc_csr_req req;
+
+       if (port > 2)
+               return -ENODEV;
+
+       memset(&req, 0, sizeof(req));
+
+       req.opcode = EPSC_SET_EOIB_MAC;
+       req.uf = uf;
+       req.u.set_eoib_mac.port = port;
+       req.u.set_eoib_mac.mac = address;
+       req.u.set_eoib_mac.index = 1; /* */
+
+       ret = sif_epsc_wr(sdev, &req, &cqe);
+       if (ret)
+               sif_log(sdev, SIF_INFO, "Failed with status %d", ret);
+       return ret;
+}
+EXPORT_SYMBOL(sif_set_mac);
diff --git a/drivers/infiniband/hw/sif/sif_verbs.h b/drivers/infiniband/hw/sif/sif_verbs.h
new file mode 100644 (file)
index 0000000..1614e6a
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Knut Omang <knut.omang@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * Driver for Oracle Scalable Infiniband Fabric (SIF) Host Channel Adapters
+ *
+ * sif_verbs.h: IB verbs API extensions specific to PSIF
+ */
+
+#ifndef _SIF_VERBS_H
+#define _SIF_VERBS_H
+#include <rdma/ib_verbs.h>
+#include "sif_user.h"
+
+/*** sif verbs extensions ***/
+
+enum sif_eoib_ctrl {
+       /* Per UF controls */
+       SIF_EC_UPM  = 1 <<  0,  /* Unicast promiscuous mode */
+       SIF_EC_MPM  = 1 <<  1,  /* Multicast promiscuous mode */
+       SIF_EC_ABC  = 1 <<  2,  /* Accept broadcast packets */
+       SIF_EC_PAD  = 1 <<  3,  /* Ethernet padding */
+       /* HCA wide (PF only) controls */
+       SIF_EC_UOFE = 1 << 10,   /* Unicast overflow table enable */
+       SIF_EC_RTP  = 1 << 11,   /* Receive tossed packets */
+       SIF_EC_DVM  = 1 << 12,   /* Double VLAN mode */
+       SIF_EC_VEM  = 1 << 13,   /* VLAN Enforcement mode */
+       SIF_EC_NSM  = 1 << 14,   /* No strip mode */
+};
+
+
+/* If this bit is set in the device_modify_mask to ib_modify_device
+ * the sif ib driver will assume that the provided ib_device_attr
+ * is embedded in a sif_device_modify struct.
+ */
+enum sif_device_modify_flags {
+       IB_DEVICE_MODIFY_EXTENDED = 1 << 3
+};
+
+
+struct sif_device_modify {
+       struct ib_device_modify ib;
+       /* These two masks use values from sif_eoib_ctrl */
+       u32 eoib_ctrl;  /* Indicate affected bits in eoib_data */
+       u32 eoib_data;  /* Values to set/unset, only bits set in eoib_ctrl affected */
+       u16 uf;         /* This field is only valid from PF */
+};
+
+
+/* Extension bits in the qp create mask to ib_create_qp
+ */
+enum sif_qp_create_flags {
+       IB_QP_CREATE_EOIB            = 1 << 4,  /* Indicate that this is an Ethernet over IB QP */
+       IB_QP_CREATE_RSS             = 1 << 5,  /* Enable receive side scaling */
+       IB_QP_CREATE_HDR_SPLIT       = 1 << 6,  /* Enable header/data split for offloading */
+       IB_QP_CREATE_RCV_DYNAMIC_MTU = 1 << 7,  /* Enable receive side dynamic mtu */
+       IB_QP_CREATE_PROXY           = 1 << 8,  /* Enable a special EPSA proxy */
+       IB_QP_NO_CSUM                = 1 << 9,  /* No csum for qp, wqe.wr.csum = qp.magic */
+       IB_QP_CREATE_SND_DYNAMIC_MTU = 1 << 10,  /* Enable receive side dynamic mtu */
+};
+
+
+/* Extension bits in the qp attr mask to ib_modify_qp
+ * TBD: Not implemented yet
+ */
+enum sif_qp_attr_mask {
+       IB_QP_EOIB         = 1 << 24,  /* Enable as an Ethernet over IB QP */
+       IB_QP_IPOIB        = 1 << 25,  /* Enable as an IP over IB QP */
+       IB_QP_RSS          = 1 << 26,  /* Enable receive side scaling */
+       IB_QP_HDR_SPLIT    = 1 << 27,  /* Enable header/data split for offloading */
+       IB_QP_RCV_DYN_MTU  = 1 << 28,  /* Enable receive side dynamic mtu */
+       IB_QP_SND_DYN_MTU  = 1 << 29,  /* Enable send side dynamic mtu */
+};
+
+
+/* Set/get the 48 bit ethernet mac address for a port on a uf
+ * The uf field is ignored for all ufs except uf 0 (PF)
+ */
+int sif_get_mac(struct ib_device *dev, u8 port, u16 uf, u64 *address);
+int sif_set_mac(struct ib_device *dev, u8 port, u16 uf, u64 address);
+
+struct sif_dev;
+struct psif_epsc_csr_req;
+struct psif_epsc_csr_rsp;
+enum psif_mbox_type;
+
+struct sif_verbs {
+       /* Exposed internal create_cq call to allow creation of proxy CQs.
+        * Needed by EPSA users. Implemented in sif_cq.c.
+        */
+       struct ib_cq * (*create_cq)(struct ib_device *ibdev, int cqe,
+                               int comp_vector, struct ib_ucontext *context,
+                               struct ib_udata *udata,
+                               enum sif_proxy_type proxy);
+       int (*eps_wr)(struct  ib_device *ibdev, enum psif_mbox_type eps_num,
+               struct psif_epsc_csr_req *req, struct psif_epsc_csr_rsp *cqe);
+};
+
+/* TBD: External rep of struct sif_dev - must be kept synchronized */
+struct sif_device {
+       struct ib_device ib_dev;
+       struct sif_verbs sv;
+};
+
+static inline struct sif_device *to_sif_device(struct ib_device *ibdev)
+{
+       return container_of(ibdev, struct sif_device, ib_dev);
+}
+
+#endif
diff --git a/drivers/infiniband/hw/sif/sif_vf.c b/drivers/infiniband/hw/sif/sif_vf.c
new file mode 100644 (file)
index 0000000..a2cbcbe
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Knut Omang <knut.omang@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * Driver for Oracle Scalable Infiniband Fabric (SIF) Host Channel Adapters
+ *
+ * sif_vf.c: SR/IOV support functions
+ */
+#include "sif_dev.h"
+#include "sif_vf.h"
+
+int sif_vf_enable(struct pci_dev *dev, int num_vfs)
+{
+       struct sif_dev *sdev = pci_get_drvdata(dev);
+       int ret = 0;
+
+       if (sdev->is_vf)
+               return 0;
+       if (sdev->fw_vfs < 0) {
+               struct psif_epsc_csr_req req;
+               struct psif_epsc_csr_rsp rsp;
+               /* Ask the EPSC how many VFs that are enabled */
+               memset(&req, 0, sizeof(req));
+               req.opcode = EPSC_QUERY;
+               req.u.query.data.op = EPSC_QUERY_NUM_UF;
+               ret = sif_epsc_wr(sdev, &req, &rsp);
+               if (ret) {
+                       sif_log(sdev, SIF_INFO,
+                               "Request to the EPSC for number of VFs configured failed with %d", ret);
+                       return ret;
+               }
+               sdev->fw_vfs = rsp.data - 1;
+               sif_log(sdev, SIF_INFO, "Firmware supports %d VFs", sdev->fw_vfs);
+       }
+
+       if (num_vfs > sdev->fw_vfs) {
+               sif_log(sdev, SIF_INFO, "Requested %d vfs - limited by firmware to %d",
+                       num_vfs, sdev->fw_vfs);
+               num_vfs = sdev->fw_vfs;
+       }
+       if (num_vfs) {
+               ret = pci_enable_sriov(dev, num_vfs);
+               if (ret < 0) {
+                       sif_log(sdev, SIF_INFO, "Failed (status %d) to enable %d VFs",
+                               ret, num_vfs);
+                       goto sriov_failed;
+               }
+               sif_log(sdev, SIF_INFO, "Enabled %d VFs", num_vfs);
+               sdev->num_vfs = num_vfs;
+       } else
+               pci_disable_sriov(sdev->pdev);
+sriov_failed:
+       return ret;
+}
+
+
+void sif_vf_disable(struct sif_dev *sdev)
+{
+       if (sdev->num_vfs) {
+               pci_disable_sriov(sdev->pdev);
+               sdev->num_vfs = 0;
+       }
+}
diff --git a/drivers/infiniband/hw/sif/sif_vf.h b/drivers/infiniband/hw/sif/sif_vf.h
new file mode 100644 (file)
index 0000000..5184a35
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Knut Omang <knut.omang@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * Driver for Oracle Scalable Infiniband Fabric (SIF) Host Channel Adapters
+ *
+ * sif_vf.h: SR/IOV support functions
+ */
+#ifndef __SIF_VF_H
+#define __SIF_VF_H
+
+int sif_vf_enable(struct pci_dev *dev, int num_vfs);
+void sif_vf_disable(struct sif_dev *sdev);
+
+#endif
diff --git a/drivers/infiniband/hw/sif/sif_xmmu.c b/drivers/infiniband/hw/sif/sif_xmmu.c
new file mode 100644 (file)
index 0000000..7b69280
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Knut Omang <knut.omang@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * Driver for Oracle Scalable Infiniband Fabric (SIF) Host Channel Adapters
+ *
+ * sif_xmmu.c: Implementation of special MMU mappings.
+ */
+
+#include "sif_mmu.h"
+#include "sif_spt.h"
+#include "sif_xmmu.h"
+#include "sif_dev.h"
+#include "sif_dma.h"
+#include "sif_mem.h"
+#include "sif_pt.h"
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <linux/highmem.h>
+#include <linux/kgdb.h>
+
+int sif_zero_map_gva_ctx(struct sif_dev *sdev,
+                       struct sif_mmu_ctx *ctx,
+                       struct sif_mem *mem,
+                       bool write)
+{
+       int i, ret;
+       u32 map_cnt; /* Number of overlapping maps of the same physical region */
+       u64 phys_size = ctx->phys_sz = mem->size; /* Tyically smaller than ctx->size */
+       u64 phys_pages;
+       u64 start = ctx->base;
+       struct sif_pt *pt;
+       struct psif_mmu_cntx *hw_ctx = &ctx->mctx;
+       struct scatterlist *sg = sif_mem_get_sgl(mem);
+
+       if (!phys_size || phys_size & ~PAGE_MASK) {
+               sif_log(sdev, SIF_INFO, "Invalid phys_length specified (0x%llx)", phys_size);
+               return -EINVAL;
+       }
+
+       map_cnt = ctx->size / phys_size;
+       phys_pages = phys_size >> sdev->mi.page_shift;
+
+       if (phys_pages > sdev->mi.ptes_per_page) {
+               sif_log(sdev, SIF_INFO,
+                       "Illegal phys_length specified (0x%llx) max %u pages supported",
+                       phys_size, sdev->mi.ptes_per_page);
+               return -EINVAL;
+       }
+       if (map_cnt * phys_size != ctx->size) {
+               sif_log(sdev, SIF_INFO,
+                       "Illegal virtual/phys length specified (0x%llx/0x%llx) must be a multiple",
+                       ctx->size, phys_size);
+               return -EINVAL;
+       }
+
+       pt = sif_pt_create_empty(sdev, start, mem->mem_type);
+       if (!pt)
+               return -ENOMEM;
+
+       ctx->pt = pt;
+       hw_ctx->wr_access = write;
+       hw_ctx->translation_type = MMU_GVA2GPA_MODE;
+       hw_ctx->page_size = PAGE_SIZE_IA32E_4KB;
+
+       for (i = 0; i < map_cnt; i++) {
+               ret = sif_pt_extend(pt, sg, start, phys_size);
+               if (ret < 0)
+                       goto extend_failed;
+               start += phys_size;
+       }
+       return 0;
+
+extend_failed:
+       for (; i >= 0; i--) {
+               start -= phys_size;
+               sif_pt_free_part(pt, start, phys_size);
+       }
+       return ret;
+}
+
+void sif_zero_unmap_gva_ctx(struct sif_dev *sdev, struct sif_mmu_ctx *ctx)
+{
+       int i;
+       u64 start = ctx->base;
+       u64 phys_size = ctx->phys_sz;
+       u32 map_cnt = ctx->size / phys_size;
+
+       for (i = 0; i < map_cnt; i++) {
+               sif_pt_free_part(ctx->pt, start, phys_size);
+               start += phys_size;
+       }
+       sif_unmap_gva_ctx(sdev, ctx);
+}
diff --git a/drivers/infiniband/hw/sif/sif_xmmu.h b/drivers/infiniband/hw/sif/sif_xmmu.h
new file mode 100644 (file)
index 0000000..d45147b
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Knut Omang <knut.omang@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * Driver for Oracle Scalable Infiniband Fabric (SIF) Host Channel Adapters
+ *
+ * sif_xmmu.h: Implementation of special MMU mappings.
+ */
+
+#ifndef _SIF_XMMU_H
+#define _SIF_XMMU_H
+struct sif_dev;
+struct sif_mmu_ctx;
+
+/* Implementation of a mapping of a virtual address space onto a single page
+ * with minimal use of page table memory (workaround for #1931 + test support)
+ */
+int sif_zero_map_gva_ctx(struct sif_dev *sdev,
+                       struct sif_mmu_ctx *ctx,
+                       struct sif_mem *mem,
+                       bool write);
+
+void sif_zero_unmap_gva_ctx(struct sif_dev *sdev, struct sif_mmu_ctx *ctx);
+
+#endif
diff --git a/drivers/infiniband/hw/sif/sif_xrc.c b/drivers/infiniband/hw/sif/sif_xrc.c
new file mode 100644 (file)
index 0000000..134d714
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Knut Omang <knut.omang@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * Driver for Oracle Scalable Infiniband Fabric (SIF) Host Channel Adapters
+ *
+ * sif_xrc.c: Implementation of XRC related functions
+ */
+
+#include <linux/idr.h>
+#include <rdma/ib_verbs.h>
+#include "sif_dev.h"
+#include "sif_pd.h"
+#include "sif_xrc.h"
+#include "sif_idr.h"
+
+
+int sif_init_xrcd(struct sif_dev *sdev)
+{
+       sif_idr_init(&sdev->xrcd_refs, 1, SIF_MAX_XRCD_INDEX);
+       return 0;
+}
+
+
+void sif_deinit_xrcd(struct sif_dev *sdev)
+{
+       /* Nothing to do yet  */
+}
+
+
+struct ib_xrcd *sif_alloc_xrcd(struct ib_device *device,
+                               struct ib_ucontext *ucontext,
+                               struct ib_udata *udata)
+{
+       struct sif_dev *sdev = to_sdev(device);
+       struct sif_xrcd *xrcd;
+       int ret = -ENOMEM;
+
+       xrcd = kzalloc(sizeof(struct sif_xrcd), GFP_KERNEL);
+       if (!xrcd)
+               goto err_res_xrcd;
+
+       ret = sif_idr_alloc(&sdev->xrcd_refs, xrcd, GFP_KERNEL);
+       if (ret < 0) {
+               sif_log(sdev, SIF_XRC, "idr_alloc failed with %d", ret);
+               goto err_idr_alloc;
+       }
+       xrcd->index = ret;
+       xrcd->pd = alloc_pd(sdev);
+       if (!xrcd->pd) {
+               ret = -ENOMEM;
+               sif_log(sdev, SIF_XRC, "alloc_pd failed with %d", ret);
+               goto err_alloc_pd;
+       }
+       xrcd->pd->ibpd.device = &sdev->ib_dev;
+       xrcd->pd->xrcd = xrcd;
+       sif_log(sdev, SIF_XRC, "index %d (pd %d)", xrcd->index, xrcd->pd->idx);
+       return &xrcd->ib_xrcd;
+
+err_alloc_pd:
+       sif_idr_remove(&sdev->xrcd_refs, xrcd->index);
+err_idr_alloc:
+       kfree(xrcd);
+err_res_xrcd:
+       return ERR_PTR(ret);
+}
+
+int sif_dealloc_xrcd(struct ib_xrcd *ib_xrcd)
+{
+       struct sif_dev *sdev = to_sdev(ib_xrcd->device);
+       struct sif_xrcd *xrcd = to_sxrcd(ib_xrcd);
+
+       sif_log(sdev, SIF_XRC, "index %d", xrcd->index);
+
+       dealloc_pd(xrcd->pd);
+       sif_idr_remove(&sdev->xrcd_refs, xrcd->index);
+       kfree(xrcd);
+       return 0;
+}
diff --git a/drivers/infiniband/hw/sif/sif_xrc.h b/drivers/infiniband/hw/sif/sif_xrc.h
new file mode 100644 (file)
index 0000000..0a41bd1
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Knut Omang <knut.omang@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * Driver for Oracle Scalable Infiniband Fabric (SIF) Host Channel Adapters
+ *
+ * sif_xrc.h: XRC related functions
+ */
+
+#ifndef __SIF_XRC_H
+#define __SIF_XRC_H
+
+/* SIF supports a 24 bit XRCD domain index: */
+#define SIF_MAX_XRCD_INDEX ((1 << 24) - 1)
+
+struct sif_xrcd {
+       struct ib_xrcd ib_xrcd;
+       int index;
+       struct sif_pd *pd;
+};
+
+static inline struct sif_xrcd *to_sxrcd(struct ib_xrcd *ibxrcd)
+{
+       return container_of(ibxrcd, struct sif_xrcd, ib_xrcd);
+}
+
+int sif_init_xrcd(struct sif_dev *sdev);
+void sif_deinit_xrcd(struct sif_dev *sdev);
+
+struct ib_xrcd *sif_alloc_xrcd(struct ib_device *device,
+                               struct ib_ucontext *ucontext,
+                               struct ib_udata *udata);
+int sif_dealloc_xrcd(struct ib_xrcd *xrcd);
+
+#endif
diff --git a/drivers/infiniband/hw/sif/version.h b/drivers/infiniband/hw/sif/version.h
new file mode 100644 (file)
index 0000000..9e91c00
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ *    Author: Knut Omang <knut.omang@oracle.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * Driver for Oracle Scalable Infiniband Fabric (SIF) Host Channel Adapters
+ *
+ * version.h: Detailed version info data structure
+ */
+#ifndef SIF_VERSION_H
+#define SIF_VERSION_H
+
+struct sif_version {
+       const char *git_repo;
+       const char *last_commit;
+       const char *git_status;
+       const char *build_user;
+       const char *build_git_time;
+       const char *git_psifapi_repo;
+       const char *last_psifapi_commit;
+       const char *git_psifapi_status;
+};
+
+extern struct sif_version sif_version;
+
+#endif /* SIF_VERSION_H */