Merge tag 'pci-v4.12-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/helgaa...
[linux-2.6-block.git] / drivers / infiniband / hw / hfi1 / hfi.h
index 40d7559fa723f59ca59ebe2fa63ff594a5275adb..14063bd30c2a1618d8c821aed325117db29478df 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _HFI1_KERNEL_H
 #define _HFI1_KERNEL_H
 /*
- * Copyright(c) 2015, 2016 Intel Corporation.
+ * Copyright(c) 2015-2017 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
@@ -54,6 +54,7 @@
 #include <linux/list.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
+#include <linux/idr.h>
 #include <linux/io.h>
 #include <linux/fs.h>
 #include <linux/completion.h>
@@ -66,6 +67,7 @@
 #include <linux/i2c-algo-bit.h>
 #include <rdma/ib_hdrs.h>
 #include <linux/rhashtable.h>
+#include <linux/netdevice.h>
 #include <rdma/rdma_vt.h>
 
 #include "chip_registers.h"
@@ -278,6 +280,8 @@ struct hfi1_ctxtdata {
        struct hfi1_devdata *dd;
        /* so functions that need physical port can get it easily */
        struct hfi1_pportdata *ppd;
+       /* associated msix interrupt */
+       u32 msix_intr;
        /* A page of memory for rcvhdrhead, rcvegrhead, rcvegrtail * N */
        void *subctxt_uregbase;
        /* An array of pages for the eager receive buffers * N */
@@ -337,6 +341,12 @@ struct hfi1_ctxtdata {
         * packets with the wrong interrupt handler.
         */
        int (*do_interrupt)(struct hfi1_ctxtdata *rcd, int threaded);
+
+       /* Indicates that this is vnic context */
+       bool is_vnic;
+
+       /* vnic queue index this context is mapped to */
+       u8 vnic_q_idx;
 };
 
 /*
@@ -474,7 +484,7 @@ struct rvt_sge_state;
 #define HFI1_PART_ENFORCE_OUT  0x2
 
 /* how often we check for synthetic counter wrap around */
-#define SYNTH_CNT_TIME 2
+#define SYNTH_CNT_TIME 3
 
 /* Counter flags */
 #define CNTR_NORMAL            0x0 /* Normal counters, just read register */
@@ -808,6 +818,32 @@ struct hfi1_asic_data {
        struct hfi1_i2c_bus *i2c_bus1;
 };
 
+/* sizes for both the QP and RSM map tables */
+#define NUM_MAP_ENTRIES         256
+#define NUM_MAP_REGS      32
+
+/*
+ * Number of VNIC contexts used. Ensure it is less than or equal to
+ * max queues supported by VNIC (HFI1_VNIC_MAX_QUEUE).
+ */
+#define HFI1_NUM_VNIC_CTXT   8
+
+/* Number of VNIC RSM entries */
+#define NUM_VNIC_MAP_ENTRIES 8
+
+/* Virtual NIC information */
+struct hfi1_vnic_data {
+       struct hfi1_ctxtdata *ctxt[HFI1_NUM_VNIC_CTXT];
+       struct kmem_cache *txreq_cache;
+       u8 num_vports;
+       struct idr vesw_idr;
+       u8 rmt_start;
+       u8 num_ctxt;
+       u32 msix_idx;
+};
+
+struct hfi1_vnic_vport_info;
+
 /* device data struct now contains only "general per-device" info.
  * fields related to a physical IB port are in a hfi1_pportdata struct.
  */
@@ -926,8 +962,9 @@ struct hfi1_devdata {
        spinlock_t rcvctrl_lock; /* protect changes to RcvCtrl */
        /* around rcd and (user ctxts) ctxt_cnt use (intr vs free) */
        spinlock_t uctxt_lock; /* rcd and user context changes */
-       /* exclusive access to 8051 */
-       spinlock_t dc8051_lock;
+       struct mutex dc8051_lock; /* exclusive access to 8051 */
+       struct workqueue_struct *update_cntr_wq;
+       struct work_struct update_cntr_work;
        /* exclusive access to 8051 memory */
        spinlock_t dc8051_memlock;
        int dc8051_timed_out;   /* remember if the 8051 timed out */
@@ -1020,7 +1057,7 @@ struct hfi1_devdata {
        u8 qos_shift;
 
        u16 irev;       /* implementation revision */
-       u16 dc8051_ver; /* 8051 firmware version */
+       u32 dc8051_ver; /* 8051 firmware version */
 
        spinlock_t hfi1_diag_trans_lock; /* protect diag observer ops */
        struct platform_config platform_config;
@@ -1031,6 +1068,7 @@ struct hfi1_devdata {
        /* MSI-X information */
        struct hfi1_msix_entry *msix_entries;
        u32 num_msix_entries;
+       u32 first_dyn_msix_idx;
 
        /* INTx information */
        u32 requested_intx_irq;         /* did we request one? */
@@ -1115,6 +1153,9 @@ struct hfi1_devdata {
        send_routine process_dma_send;
        void (*pio_inline_send)(struct hfi1_devdata *dd, struct pio_buf *pbuf,
                                u64 pbc, const void *from, size_t count);
+       int (*process_vnic_dma_send)(struct hfi1_devdata *dd, u8 q_idx,
+                                    struct hfi1_vnic_vport_info *vinfo,
+                                    struct sk_buff *skb, u64 pbc, u8 plen);
        /* hfi1_pportdata, points to array of (physical) port-specific
         * data structs, indexed by pidx (0..n-1)
         */
@@ -1126,8 +1167,8 @@ struct hfi1_devdata {
        u16 flags;
        /* Number of physical ports available */
        u8 num_pports;
-       /* Lowest context number which can be used by user processes */
-       u8 first_user_ctxt;
+       /* Lowest context number which can be used by user processes or VNIC */
+       u8 first_dyn_alloc_ctxt;
        /* adding a new field here would make it part of this cacheline */
 
        /* seqlock for sc2vl */
@@ -1167,15 +1208,24 @@ struct hfi1_devdata {
        bool eprom_available;   /* true if EPROM is available for this device */
        bool aspm_supported;    /* Does HW support ASPM */
        bool aspm_enabled;      /* ASPM state: enabled/disabled */
-       struct rhashtable sdma_rht;
+       struct rhashtable *sdma_rht;
 
        struct kobject kobj;
+
+       /* vnic data */
+       struct hfi1_vnic_data vnic;
 };
 
+static inline bool hfi1_vnic_is_rsm_full(struct hfi1_devdata *dd, int spare)
+{
+       return (dd->vnic.rmt_start + spare) > NUM_MAP_ENTRIES;
+}
+
 /* 8051 firmware version helper */
-#define dc8051_ver(a, b) ((a) << 8 | (b))
-#define dc8051_ver_maj(a) ((a & 0xff00) >> 8)
-#define dc8051_ver_min(a)  (a & 0x00ff)
+#define dc8051_ver(a, b, c) ((a) << 16 | (b) << 8 | (c))
+#define dc8051_ver_maj(a) (((a) & 0xff0000) >> 16)
+#define dc8051_ver_min(a) (((a) & 0x00ff00) >> 8)
+#define dc8051_ver_patch(a) ((a) & 0x0000ff)
 
 /* f_put_tid types */
 #define PT_EXPECTED 0
@@ -1235,6 +1285,9 @@ int handle_receive_interrupt(struct hfi1_ctxtdata *, int);
 int handle_receive_interrupt_nodma_rtail(struct hfi1_ctxtdata *, int);
 int handle_receive_interrupt_dma_rtail(struct hfi1_ctxtdata *, int);
 void set_all_slowpath(struct hfi1_devdata *dd);
+void hfi1_vnic_synchronize_irq(struct hfi1_devdata *dd);
+void hfi1_set_vnic_msix_info(struct hfi1_ctxtdata *rcd);
+void hfi1_reset_vnic_msix_info(struct hfi1_ctxtdata *rcd);
 
 extern const struct pci_device_id hfi1_pci_tbl[];
 
@@ -1254,16 +1307,24 @@ int hfi1_reset_device(int);
 /* return the driver's idea of the logical OPA port state */
 static inline u32 driver_lstate(struct hfi1_pportdata *ppd)
 {
-       return ppd->lstate; /* use the cached value */
+       /*
+        * The driver does some processing from the time the logical
+        * link state is at INIT to the time the SM can be notified
+        * as such. Return IB_PORT_DOWN until the software state
+        * is ready.
+        */
+       if (ppd->lstate == IB_PORT_INIT && !(ppd->host_link_state & HLS_UP))
+               return IB_PORT_DOWN;
+       else
+               return ppd->lstate;
 }
 
 void receive_interrupt_work(struct work_struct *work);
 
 /* extract service channel from header and rhf */
-static inline int hdr2sc(struct ib_header *hdr, u64 rhf)
+static inline int hfi1_9B_get_sc5(struct ib_header *hdr, u64 rhf)
 {
-       return ((be16_to_cpu(hdr->lrh[0]) >> 12) & 0xf) |
-              ((!!(rhf_dc_info(rhf))) << 4);
+       return ib_get_sc(hdr) | ((!!(rhf_dc_info(rhf))) << 4);
 }
 
 #define HFI1_JKEY_WIDTH       16
@@ -1597,9 +1658,9 @@ static inline bool process_ecn(struct rvt_qp *qp, struct hfi1_packet *pkt,
        u32 bth1;
 
        bth1 = be32_to_cpu(ohdr->bth[1]);
-       if (unlikely(bth1 & (HFI1_BECN_SMASK | HFI1_FECN_SMASK))) {
+       if (unlikely(bth1 & (IB_BECN_SMASK | IB_FECN_SMASK))) {
                hfi1_process_ecn_slowpath(qp, pkt, do_cnp);
-               return bth1 & HFI1_FECN_SMASK;
+               return !!(bth1 & IB_FECN_SMASK);
        }
        return false;
 }