Blame psm_hal_gen1/opa_user_gen1.h

Packit 961e70
/*
Packit 961e70
Packit 961e70
  This file is provided under a dual BSD/GPLv2 license.  When using or
Packit 961e70
  redistributing this file, you may do so under either license.
Packit 961e70
Packit 961e70
  GPL LICENSE SUMMARY
Packit 961e70
Packit 961e70
  Copyright(c) 2015 Intel Corporation.
Packit 961e70
Packit 961e70
  This program is free software; you can redistribute it and/or modify
Packit 961e70
  it under the terms of version 2 of the GNU General Public License as
Packit 961e70
  published by the Free Software Foundation.
Packit 961e70
Packit 961e70
  This program is distributed in the hope that it will be useful, but
Packit 961e70
  WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 961e70
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 961e70
  General Public License for more details.
Packit 961e70
Packit 961e70
  Contact Information:
Packit 961e70
  Intel Corporation, www.intel.com
Packit 961e70
Packit 961e70
  BSD LICENSE
Packit 961e70
Packit 961e70
  Copyright(c) 2015 Intel Corporation.
Packit 961e70
Packit 961e70
  Redistribution and use in source and binary forms, with or without
Packit 961e70
  modification, are permitted provided that the following conditions
Packit 961e70
  are met:
Packit 961e70
Packit 961e70
    * Redistributions of source code must retain the above copyright
Packit 961e70
      notice, this list of conditions and the following disclaimer.
Packit 961e70
    * Redistributions in binary form must reproduce the above copyright
Packit 961e70
      notice, this list of conditions and the following disclaimer in
Packit 961e70
      the documentation and/or other materials provided with the
Packit 961e70
      distribution.
Packit 961e70
    * Neither the name of Intel Corporation nor the names of its
Packit 961e70
      contributors may be used to endorse or promote products derived
Packit 961e70
      from this software without specific prior written permission.
Packit 961e70
Packit 961e70
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 961e70
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 961e70
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 961e70
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 961e70
  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 961e70
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 961e70
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 961e70
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 961e70
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 961e70
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 961e70
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 961e70
Packit 961e70
*/
Packit 961e70
Packit 961e70
#ifndef OPA_USER_GEN1_H
Packit 961e70
#define OPA_USER_GEN1_H
Packit 961e70
Packit 961e70
/* This file contains all of the data structures and routines that are
Packit 961e70
   publicly visible and usable (to low level infrastructure code; it is
Packit 961e70
   not expected that any application, or even normal application-level library,
Packit 961e70
   will ever need to use any of this).
Packit 961e70
Packit 961e70
   Additional entry points and data structures that are used by these routines
Packit 961e70
   may be referenced in this file, but they should not be generally available;
Packit 961e70
   they are visible here only to allow use in inlined functions.  Any variable,
Packit 961e70
   data structure, or function that starts with a leading "_" is in this
Packit 961e70
   category.
Packit 961e70
*/
Packit 961e70
Packit 961e70
/* Include header files we need that are unlikely to otherwise be needed by */
Packit 961e70
/* programs. */
Packit 961e70
#include <stddef.h>
Packit 961e70
#include <stdarg.h>
Packit 961e70
#include <unistd.h>
Packit 961e70
#include <errno.h>
Packit 961e70
#include <string.h>
Packit 961e70
#include <sys/stat.h>
Packit 961e70
#include <sys/mman.h>
Packit 961e70
#include <sys/user.h>
Packit 961e70
#include <syslog.h>
Packit Service 7ed5cc
#include <stdbool.h>
Packit 961e70
#include "opa_intf.h"
Packit 961e70
#include "opa_common_gen1.h"
Packit 961e70
#include "opa_byteorder.h"
Packit 961e70
#include "opa_udebug.h"
Packit 961e70
#include "opa_service_gen1.h"
Packit 961e70
#include "opa_user.h"
Packit 961e70
Packit 961e70
#define HFI_RHF_USE_EGRBFR_MASK 0x1
Packit 961e70
#define HFI_RHF_USE_EGRBFR_SHIFT 15
Packit 961e70
#define HFI_RHF_EGRBFR_INDEX_MASK 0x7FF
Packit 961e70
#define HFI_RHF_EGRBFR_INDEX_SHIFT 16
Packit 961e70
Packit 961e70
#define HFI_RHF_SEQ_MASK 0xF
Packit 961e70
#define HFI_RHF_SEQ_SHIFT 28
Packit 961e70
#define HFI_RHF_EGRBFR_OFFSET_MASK 0xFFF
Packit 961e70
#define HFI_RHF_EGRBFR_OFFSET_SHIFT 0
Packit 961e70
#define HFI_RHF_HDRQ_OFFSET_MASK 0x1FF
Packit 961e70
#define HFI_RHF_HDRQ_OFFSET_SHIFT 12
Packit 961e70
#define HFI_RHF_TIDERR     0x08000000
Packit 961e70
Packit 961e70
/* TidFlow related bits */
Packit 961e70
#define HFI_TF_SEQNUM_SHIFT                 0
Packit 961e70
#define HFI_TF_SEQNUM_MASK                  0x7ff
Packit 961e70
Packit 961e70
#define HFI_TF_GENVAL_SHIFT                 11
Packit 961e70
#define HFI_TF_GENVAL_MASK                  0xfffff
Packit 961e70
Packit 961e70
#define HFI_TF_FLOWVALID_SHIFT              32
Packit 961e70
#define HFI_TF_FLOWVALID_MASK               0x1
Packit 961e70
#define HFI_TF_HDRSUPP_ENABLED_SHIFT        33
Packit 961e70
#define HFI_TF_HDRSUPP_ENABLED_MASK         0x1
Packit 961e70
Packit 961e70
#define HFI_TF_KEEP_AFTER_SEQERR_SHIFT      34
Packit 961e70
#define HFI_TF_KEEP_AFTER_SEQERR_MASK       0x1
Packit 961e70
#define HFI_TF_KEEP_ON_GENERR_SHIFT         35
Packit 961e70
#define HFI_TF_KEEP_ON_GENERR_MASK          0x1
Packit 961e70
#define HFI_TF_KEEP_PAYLOAD_ON_GENERR_SHIFT 36
Packit 961e70
#define HFI_TF_KEEP_PAYLOAD_ON_GENERR_MASK  0x1
Packit 961e70
#define HFI_TF_STATUS_SEQMISMATCH_SHIFT     37
Packit 961e70
#define HFI_TF_STATUS_SEQMISMATCH_MASK      0x1
Packit 961e70
#define HFI_TF_STATUS_GENMISMATCH_SHIFT     38
Packit 961e70
#define HFI_TF_STATUS_GENMISMATCH_MASK      0x1
Packit 961e70
Packit 961e70
/* PBC bits */
Packit 961e70
#define HFI_PBC_STATICRCC_SHIFT         0
Packit 961e70
#define HFI_PBC_STATICRCC_MASK          0xffff
Packit 961e70
Packit 961e70
#define HFI_PBC_SC4_SHIFT               4
Packit 961e70
#define HFI_PBC_SC4_MASK                0x1
Packit 961e70
Packit 961e70
#define HFI_PBC_INTR_SHIFT              31
Packit 961e70
#define HFI_PBC_DCINFO_SHIFT            30
Packit 961e70
#define HFI_PBC_TESTEBP_SHIFT           29
Packit 961e70
#define HFI_PBC_PACKETBYPASS_SHIFT      28
Packit 961e70
#define HFI_PBC_INSERTHCRC_SHIFT        26
Packit 961e70
#define HFI_PBC_INSERTHCRC_MASK         0x3
Packit 961e70
#define HFI_PBC_CREDITRETURN_SHIFT      25
Packit 961e70
#define HFI_PBC_INSERTBYPASSICRC_SHIFT  24
Packit 961e70
#define HFI_PBC_TESTBADICRC_SHIFT       23
Packit 961e70
#define HFI_PBC_FECN_SHIFT              22
Packit 961e70
#define HFI_PBC_VL_SHIFT                12
Packit 961e70
#define HFI_PBC_VL_MASK                 0xf
Packit 961e70
#define HFI_PBC_LENGTHDWS_SHIFT         0
Packit 961e70
#define HFI_PBC_LENGTHDWS_MASK          0xfff
Packit 961e70
Packit 961e70
/* this portion only defines what we currently use */
Packit 961e70
struct hfi_pbc {
Packit 961e70
	__u32 pbc0;
Packit 961e70
	__u16 PbcStaticRateControlCnt;
Packit 961e70
	__u16 fill1;
Packit 961e70
};
Packit 961e70
Packit Service 7ed5cc
typedef enum mapsize
Packit Service 7ed5cc
{	SC_CREDITS,
Packit Service 7ed5cc
	PIO_BUFBASE_SOP,
Packit Service 7ed5cc
	PIO_BUFBASE,
Packit Service 7ed5cc
	RCVHDR_BUFBASE,
Packit Service 7ed5cc
	RCVEGR_BUFBASE,
Packit Service 7ed5cc
	SDMA_COMP_BUFBASE,
Packit Service 7ed5cc
	USER_REGBASE,
Packit Service 7ed5cc
	RCVHDRTAIL_BASE,
Packit Service 7ed5cc
	EVENTS_BUFBASE,
Packit Service 7ed5cc
	STATUS_BUFBASE,
Packit Service 7ed5cc
	SUBCTXT_UREGBASE,
Packit Service 7ed5cc
	SUBCTXT_RCVHDRBUF,
Packit Service 7ed5cc
	SUBCTXT_RCVEGRBUF,
Packit Service 7ed5cc
	MAPSIZE_MAX
Packit Service 7ed5cc
} mapsize_t;
Packit Service 7ed5cc
Packit Service 7ed5cc
/* TODO: consider casting in the ALIGN() macro */
Packit Service 7ed5cc
#define ALIGN(x, a)				(((x)+(a)-1)&~((a)-1))
Packit Service 7ed5cc
#define ALIGNDOWN_PTR(x, a)			((void*)(((uintptr_t)(x))&~((uintptr_t)((a)-1))))
Packit Service 7ed5cc
Packit Service 7ed5cc
/* using the same flags for all the mappings */
Packit Service 7ed5cc
#define HFI_MMAP_FLAGS				(MAP_SHARED|MAP_LOCKED)
Packit Service 7ed5cc
#define HFI_MMAP_PGSIZE				sysconf(_SC_PAGESIZE)
Packit Service 7ed5cc
/* cast to uintptr_t as opposed to intptr_t which evaluates to a signed type
Packit Service 7ed5cc
 *  * on which one should not perform bitwise operations (undefined behavior)
Packit Service 7ed5cc
 *   */
Packit Service 7ed5cc
#define HFI_MMAP_PGMASK				(~(uintptr_t)(HFI_MMAP_PGSIZE-1))
Packit Service 7ed5cc
Packit Service 7ed5cc
/* this is only an auxiliary macro for HFI_MMAP_ERRCHECK()
Packit Service 7ed5cc
 * @off expected to be unsigned in order to AND with the page mask and avoid undefined behavior
Packit Service 7ed5cc
 */
Packit Service 7ed5cc
#define U64_TO_OFF64_PGMASK(off)		((__off64_t)((off) & HFI_MMAP_PGMASK))
Packit Service 7ed5cc
Packit Service 7ed5cc
#define HFI_MMAP_ALIGNOFF(fd, off, size, prot)	hfi_mmap64(0,(size),(prot),HFI_MMAP_FLAGS,(fd),U64_TO_OFF64_PGMASK((off)))
Packit Service 7ed5cc
/* complementary */
Packit Service 7ed5cc
#define HFI_MUNMAP(addr, size)			munmap((addr), (size))
Packit Service 7ed5cc
Packit Service 7ed5cc
/* make sure uintmax_t can hold the result of unsigned int multiplication */
Packit Service 7ed5cc
#if UINT_MAX > (UINTMAX_MAX / UINT_MAX)
Packit Service 7ed5cc
#error We cannot safely multiply unsigned integers on this platform
Packit Service 7ed5cc
#endif
Packit Service 7ed5cc
Packit Service 7ed5cc
/* @member assumed to be of type u64 and validated to be so */
Packit Service 7ed5cc
#define HFI_MMAP_ERRCHECK(fd, binfo, member, size, prot) ({						\
Packit Service 7ed5cc
		typeof((binfo)->member) *__tptr = (__u64 *)NULL;					\
Packit Service 7ed5cc
		(void)__tptr;										\
Packit Service 7ed5cc
		void *__maddr = HFI_MMAP_ALIGNOFF((fd), (binfo)->member, (size), (prot));		\
Packit Service 7ed5cc
		do {											\
Packit Service 7ed5cc
			if (unlikely(__maddr == MAP_FAILED)) {						\
Packit Service 7ed5cc
				uintmax_t outval = (uintmax_t)((binfo)->member);			\
Packit Service 7ed5cc
				_HFI_INFO("mmap of " #member " (0x%jx) size %zu failed: %s\n",		\
Packit Service 7ed5cc
					outval, size, strerror(errno));					\
Packit Service 7ed5cc
				goto err_mmap_##member;							\
Packit Service 7ed5cc
			}										\
Packit Service 7ed5cc
			(binfo)->member = (__u64)__maddr;						\
Packit Service 7ed5cc
			_HFI_VDBG(#member "mmap %jx successful\n", (uintmax_t)((binfo)->member));	\
Packit Service 7ed5cc
		} while(0);										\
Packit Service 7ed5cc
		__maddr;										\
Packit Service 7ed5cc
})
Packit Service 7ed5cc
Packit Service 7ed5cc
/* assigns 0 to the member after unmapping */
Packit Service 7ed5cc
#define HFI_MUNMAP_ERRCHECK(binfo, member, size)						\
Packit Service 7ed5cc
		do {	typeof((binfo)->member) *__tptr = (__u64 *)NULL;			\
Packit Service 7ed5cc
			(void)__tptr;								\
Packit Service 7ed5cc
			void *__addr = ALIGNDOWN_PTR((binfo)->member, HFI_MMAP_PGSIZE);		\
Packit Service 7ed5cc
			if (unlikely( __addr == NULL || (munmap(__addr, (size)) == -1))) {	\
Packit Service 7ed5cc
				_HFI_INFO("unmap of " #member " (%p) failed: %s\n",		\
Packit Service 7ed5cc
					__addr, strerror(errno));				\
Packit Service 7ed5cc
			}									\
Packit Service 7ed5cc
			else {									\
Packit Service 7ed5cc
				_HFI_VDBG("unmap of " #member "(%p) succeeded\n", __addr);	\
Packit Service 7ed5cc
				(binfo)->member = 0;						\
Packit Service 7ed5cc
			}									\
Packit Service 7ed5cc
		} while(0)
Packit Service 7ed5cc
Packit 961e70
#define HFI_PCB_SIZE_IN_BYTES 8
Packit 961e70
Packit 961e70
/* Usable bytes in header (hdrsize - lrh - bth) */
Packit 961e70
#define HFI_MESSAGE_HDR_SIZE_HFI       (HFI_MESSAGE_HDR_SIZE-20)
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * SDMA includes 8B sdma hdr, 8B PBC, and message header.
Packit 961e70
 * If we are using GPU workloads, we need to set a new
Packit 961e70
 * "flags" member which takes another 2 bytes in the
Packit 961e70
 * sdma hdr. We let the driver know of this 2 extra bytes
Packit 961e70
 * at runtime when we set the length for the iovecs.
Packit 961e70
 */
Packit 961e70
#define HFI_SDMA_HDR_SIZE      (8+8+56)
Packit 961e70
Packit 961e70
static inline __u32 hfi_hdrget_seq(const __le32 *rbuf)
Packit 961e70
{
Packit 961e70
	return (__le32_to_cpu(rbuf[0]) >> HFI_RHF_SEQ_SHIFT)
Packit 961e70
	    & HFI_RHF_SEQ_MASK;
Packit 961e70
}
Packit 961e70
Packit 961e70
static inline __u32 hfi_hdrget_hdrq_offset(const __le32 *rbuf)
Packit 961e70
{
Packit 961e70
	return (__le32_to_cpu(rbuf[1]) >> HFI_RHF_HDRQ_OFFSET_SHIFT)
Packit 961e70
	    & HFI_RHF_HDRQ_OFFSET_MASK;
Packit 961e70
}
Packit 961e70
Packit 961e70
struct _hfi_ctrl {
Packit 961e70
	int32_t fd;		/* device file descriptor */
Packit 961e70
	/* tidflow valid */
Packit 961e70
	uint32_t __hfi_tfvalid;
Packit 961e70
	/* unit id */
Packit 961e70
	uint32_t __hfi_unit;
Packit 961e70
	/* port id */
Packit 961e70
	uint32_t __hfi_port;
Packit 961e70
Packit 961e70
	/* number of eager tid entries */
Packit 961e70
	uint32_t __hfi_tidegrcnt;
Packit 961e70
	/* number of expected tid entries */
Packit 961e70
	uint32_t __hfi_tidexpcnt;
Packit 961e70
Packit 961e70
	/* effective mtu size, should be <= base_info.mtu */
Packit 961e70
	uint32_t __hfi_mtusize;
Packit 961e70
	/* max PIO size, should be <= effective mtu size */
Packit 961e70
	uint32_t __hfi_piosize;
Packit 961e70
Packit 961e70
	/* two struct output from driver. */
Packit 961e70
	struct hfi1_ctxt_info ctxt_info;
Packit 961e70
	struct hfi1_base_info base_info;
Packit 961e70
Packit 961e70
	/* some local storages in some condition: */
Packit Service 7ed5cc
	/* as storage of __hfi_rcvtidflow in hfi_userinit_internal(). */
Packit 961e70
	__le64 regs[HFI_TF_NFLOWS];
Packit 961e70
Packit 961e70
	/* location to which OPA writes the rcvhdrtail register whenever
Packit 961e70
	   it changes, so that no chip registers are read in the performance
Packit 961e70
	   path. */
Packit 961e70
	volatile __le64 *__hfi_rcvtail;
Packit 961e70
Packit 961e70
	/* address where ur_rcvhdrtail is written */
Packit 961e70
	volatile __le64 *__hfi_rcvhdrtail;
Packit 961e70
	/* address where ur_rcvhdrhead is written */
Packit 961e70
	volatile __le64 *__hfi_rcvhdrhead;
Packit 961e70
	/* address where ur_rcvegrindextail is read */
Packit 961e70
	volatile __le64 *__hfi_rcvegrtail;
Packit 961e70
	/* address where ur_rcvegrindexhead is written */
Packit 961e70
	volatile __le64 *__hfi_rcvegrhead;
Packit 961e70
	/* address where ur_rcvegroffsettail is read */
Packit 961e70
	volatile __le64 *__hfi_rcvofftail;
Packit 961e70
	/* address where ur_rcvtidflow is written */
Packit 961e70
	volatile __le64 *__hfi_rcvtidflow;
Packit 961e70
};
Packit 961e70
Packit 961e70
/* After the device is opened, hfi_userinit() is called to give the driver the
Packit 961e70
   parameters the user code wants to use, and to get the implementation values,
Packit 961e70
   etc. back.  0 is returned on success, a positive value is a standard errno,
Packit 961e70
   and a negative value is reserved for future use.  The first argument is
Packit 961e70
   the filedescriptor returned by the device open.
Packit 961e70
Packit 961e70
   It is allowed to have multiple devices (and of different types)
Packit 961e70
   simultaneously opened and initialized, although this won't be fully
Packit 961e70
   implemented initially.  This routine is used by the low level
Packit 961e70
   hfi protocol code (and any other code that has similar low level
Packit 961e70
   functionality).
Packit 961e70
   This is the only routine that takes a file descriptor, rather than an
Packit 961e70
   struct _hfi_ctrl *.  The struct _hfi_ctrl * used for everything
Packit 961e70
   else is returned by this routine.
Packit 961e70
*/
Packit 961e70
struct _hfi_ctrl *hfi_userinit(int32_t, struct hfi1_user_info_dep *);
Packit 961e70
Packit Service 7ed5cc
/* Internal function extends API, while original remains for backwards
Packit Service 7ed5cc
   compatibility with external code
Packit Service 7ed5cc
*/
Packit Service 7ed5cc
struct _hfi_ctrl *hfi_userinit_internal(int32_t, bool, struct hfi1_user_info_dep *);
Packit Service 7ed5cc
Packit 961e70
/* don't inline these; it's all init code, and not inlining makes the */
Packit 961e70
/* overall code shorter and easier to debug */
Packit 961e70
void hfi_touch_mmap(void *, size_t) __attribute__ ((noinline));
Packit 961e70
Packit 961e70
/* set the BTH pkey to check for this process. */
Packit 961e70
/* This is for receive checks, not for sends.  It isn't necessary
Packit 961e70
   to set the default key, that's always allowed by the hardware.
Packit 961e70
   If too many pkeys are in use for the hardware to support, this
Packit 961e70
   will return EAGAIN, and the caller should then fail and exit
Packit 961e70
   or use the default key and check the pkey in the received packet
Packit 961e70
   checking. */
Packit 961e70
/* set send context pkey to verify, error if driver is not configured with */
Packit 961e70
/* this pkey in its pkey table. */
Packit 961e70
int hfi_set_pkey(struct _hfi_ctrl *, uint16_t);
Packit 961e70
Packit 961e70
int hfi_wait_for_packet(struct _hfi_ctrl *);
Packit 961e70
Packit 961e70
/* New user event mechanism, using spi_sendbuf_status HFI_EVENT_* bits
Packit 961e70
   obsoletes hfi_disarm_bufs(), and extends it, although old mechanism
Packit 961e70
   remains for binary compatibility. */
Packit 961e70
int hfi_event_ack(struct _hfi_ctrl *ctrl, __u64 ackbits);
Packit 961e70
Packit 961e70
/* set whether we want an interrupt on all packets, or just urgent ones */
Packit 961e70
int hfi_poll_type(struct _hfi_ctrl *ctrl, uint16_t poll_type);
Packit 961e70
Packit 961e70
/* reset halted send context, error if context is not halted. */
Packit 961e70
int hfi_reset_context(struct _hfi_ctrl *ctrl);
Packit 961e70
Packit 961e70
/*
Packit 961e70
* Safe version of hfi_[d/q]wordcpy that is guaranteed to only copy each byte once.
Packit 961e70
*/
Packit 961e70
#if defined(__x86_64__)
Packit 961e70
void hfi_dwordcpy_safe(volatile uint32_t *dest, const uint32_t *src,
Packit 961e70
		       uint32_t ndwords);
Packit 961e70
void hfi_qwordcpy_safe(volatile uint64_t *dest, const uint64_t *src,
Packit 961e70
		       uint32_t nqwords);
Packit 961e70
#else
Packit 961e70
#define hfi_dwordcpy_safe hfi_dwordcpy
Packit 961e70
#define hfi_qwordcpy_safe hfi_qwordcpy
Packit 961e70
#endif
Packit 961e70
Packit 961e70
static __inline__ void hfi_tidflow_set_entry(struct _hfi_ctrl *ctrl,
Packit 961e70
					 uint32_t flowid, uint32_t genval,
Packit 961e70
					 uint32_t seqnum)
Packit 961e70
{
Packit 961e70
/* For proper behavior with RSM interception of FECN packets for CCA,
Packit 961e70
 * the tidflow entry needs the KeepAfterSequenceError bit set.
Packit 961e70
 * A packet that is converted from expected to eager by RSM will not
Packit 961e70
 * trigger an update in the tidflow state.  This will cause the tidflow
Packit 961e70
 * to incorrectly report a sequence error on any non-FECN packets that
Packit 961e70
 * arrive after the RSM intercepted packets.  If the KeepAfterSequenceError
Packit 961e70
 * bit is set, PSM can properly detect this "false SeqErr" condition,
Packit 961e70
 * and recover without dropping packets.
Packit 961e70
 * Note that if CCA/RSM are not important, this change will slightly
Packit 961e70
 * increase the CPU load when packets are dropped.  If this is significant,
Packit 961e70
 * consider hiding this change behind a CCA/RSM environment variable.
Packit 961e70
 */
Packit 961e70
Packit 961e70
	ctrl->__hfi_rcvtidflow[flowid] = __cpu_to_le64(
Packit 961e70
		((genval & HFI_TF_GENVAL_MASK) << HFI_TF_GENVAL_SHIFT) |
Packit 961e70
		((seqnum & HFI_TF_SEQNUM_MASK) << HFI_TF_SEQNUM_SHIFT) |
Packit 961e70
		((uint64_t)ctrl->__hfi_tfvalid << HFI_TF_FLOWVALID_SHIFT) |
Packit 961e70
		(1ULL << HFI_TF_HDRSUPP_ENABLED_SHIFT) |
Packit 961e70
		/* KeepAfterSequenceError = 1 -- previously was 0 */
Packit 961e70
		(1ULL << HFI_TF_KEEP_AFTER_SEQERR_SHIFT) |
Packit 961e70
		(1ULL << HFI_TF_KEEP_ON_GENERR_SHIFT) |
Packit 961e70
		/* KeePayloadOnGenErr = 0 */
Packit 961e70
		(1ULL << HFI_TF_STATUS_SEQMISMATCH_SHIFT) |
Packit 961e70
		(1ULL << HFI_TF_STATUS_GENMISMATCH_SHIFT));
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ void hfi_tidflow_reset(struct _hfi_ctrl *ctrl,
Packit 961e70
					 uint32_t flowid, uint32_t genval,
Packit 961e70
					 uint32_t seqnum)
Packit 961e70
{
Packit 961e70
/*
Packit 961e70
 * If a tidflow table entry is set to "Invalid", we want to drop
Packit 961e70
 * header if payload is dropped, we want to get a header if the payload
Packit 961e70
 * is delivered.
Packit 961e70
 *
Packit 961e70
 * We set a tidflow table entry "Invalid" by setting FlowValid=1 and
Packit 961e70
 * GenVal=0x1FFF/0xFFFFF, this is a special generation number and no
Packit 961e70
 * packet will use this value. We don't care SeqNum but we set it to
Packit 961e70
 * 0x7FF. So if GenVal does not match, the payload is dropped because
Packit 961e70
 * KeepPayloadOnGenErr=0; for packet header, KeepOnGenErr=0 make sure
Packit 961e70
 * header is not generated. But if a packet happens to have the special
Packit 961e70
 * generation number, the payload is delivered, HdrSuppEnabled=0 make
Packit 961e70
 * sure header is generated if SeqNUm matches, if SeqNum does not match,
Packit 961e70
 * KeepAfterSeqErr=1 makes sure the header is generated.
Packit 961e70
 */
Packit 961e70
	ctrl->__hfi_rcvtidflow[flowid] = __cpu_to_le64(
Packit 961e70
		/* genval = 0x1FFF or 0xFFFFF */
Packit 961e70
		((genval & HFI_TF_GENVAL_MASK) << HFI_TF_GENVAL_SHIFT) |
Packit 961e70
		/* seqnum = 0x7FF */
Packit 961e70
		((seqnum & HFI_TF_SEQNUM_MASK) << HFI_TF_SEQNUM_SHIFT) |
Packit 961e70
		((uint64_t)ctrl->__hfi_tfvalid << HFI_TF_FLOWVALID_SHIFT) |
Packit 961e70
		/* HdrSuppEnabled = 0 */
Packit 961e70
		(1ULL << HFI_TF_KEEP_AFTER_SEQERR_SHIFT) |
Packit 961e70
		/* KeepOnGenErr = 0 */
Packit 961e70
		/* KeepPayloadOnGenErr = 0 */
Packit 961e70
		(1ULL << HFI_TF_STATUS_SEQMISMATCH_SHIFT) |
Packit 961e70
		(1ULL << HFI_TF_STATUS_GENMISMATCH_SHIFT));
Packit 961e70
}
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * This should only be used for debugging.
Packit 961e70
 * Normally, we shouldn't read the chip.
Packit 961e70
 */
Packit 961e70
static __inline__ uint64_t hfi_tidflow_get(struct _hfi_ctrl *ctrl,
Packit 961e70
					   uint32_t flowid)
Packit 961e70
{
Packit 961e70
	return __le64_to_cpu(ctrl->__hfi_rcvtidflow[flowid]);
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ uint32_t hfi_tidflow_get_seqnum(uint64_t val)
Packit 961e70
{
Packit 961e70
	return (val >> HFI_TF_SEQNUM_SHIFT) & HFI_TF_SEQNUM_MASK;
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ uint32_t hfi_tidflow_get_genval(uint64_t val)
Packit 961e70
{
Packit 961e70
	return (val >> HFI_TF_GENVAL_SHIFT) & HFI_TF_GENVAL_MASK;
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ uint32_t hfi_tidflow_get_flowvalid(uint64_t val)
Packit 961e70
{
Packit 961e70
	return (val >> HFI_TF_FLOWVALID_SHIFT) & HFI_TF_FLOWVALID_MASK;
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ uint32_t hfi_tidflow_get_enabled(uint64_t val)
Packit 961e70
{
Packit 961e70
	return (val >> HFI_TF_HDRSUPP_ENABLED_SHIFT) &
Packit 961e70
	    HFI_TF_HDRSUPP_ENABLED_MASK;
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ uint32_t hfi_tidflow_get_keep_after_seqerr(uint64_t val)
Packit 961e70
{
Packit 961e70
	return (val >> HFI_TF_KEEP_AFTER_SEQERR_SHIFT) &
Packit 961e70
	    HFI_TF_KEEP_AFTER_SEQERR_MASK;
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ uint32_t hfi_tidflow_get_keep_on_generr(uint64_t val)
Packit 961e70
{
Packit 961e70
	return (val >> HFI_TF_KEEP_ON_GENERR_SHIFT) &
Packit 961e70
	    HFI_TF_KEEP_ON_GENERR_MASK;
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ uint32_t hfi_tidflow_get_keep_payload_on_generr(uint64_t val)
Packit 961e70
{
Packit 961e70
	return (val >> HFI_TF_KEEP_PAYLOAD_ON_GENERR_SHIFT) &
Packit 961e70
	    HFI_TF_KEEP_PAYLOAD_ON_GENERR_MASK;
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ uint32_t hfi_tidflow_get_seqmismatch(uint64_t val)
Packit 961e70
{
Packit 961e70
	return (val >> HFI_TF_STATUS_SEQMISMATCH_SHIFT) &
Packit 961e70
	    HFI_TF_STATUS_SEQMISMATCH_MASK;
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ uint32_t hfi_tidflow_get_genmismatch(uint64_t val)
Packit 961e70
{
Packit 961e70
	return (val >> HFI_TF_STATUS_GENMISMATCH_SHIFT) &
Packit 961e70
	    HFI_TF_STATUS_GENMISMATCH_MASK;
Packit 961e70
}
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * This should only be used by a process to write the eager index into
Packit 961e70
 * a subcontext's eager header entry.
Packit 961e70
 */
Packit 961e70
static __inline__ void hfi_hdrset_use_egrbfr(__le32 *rbuf, uint32_t val)
Packit 961e70
{
Packit 961e70
	rbuf[0] =
Packit 961e70
	    (rbuf[0] &
Packit 961e70
	     __cpu_to_le32(~(HFI_RHF_USE_EGRBFR_MASK <<
Packit 961e70
			     HFI_RHF_USE_EGRBFR_SHIFT))) |
Packit 961e70
	    __cpu_to_le32((val & HFI_RHF_USE_EGRBFR_MASK) <<
Packit 961e70
			  HFI_RHF_USE_EGRBFR_SHIFT);
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ void hfi_hdrset_egrbfr_index(__le32 *rbuf, uint32_t val)
Packit 961e70
{
Packit 961e70
	rbuf[0] =
Packit 961e70
	    (rbuf[0] &
Packit 961e70
	     __cpu_to_le32(~(HFI_RHF_EGRBFR_INDEX_MASK <<
Packit 961e70
			     HFI_RHF_EGRBFR_INDEX_SHIFT))) |
Packit 961e70
	    __cpu_to_le32((val & HFI_RHF_EGRBFR_INDEX_MASK) <<
Packit 961e70
			  HFI_RHF_EGRBFR_INDEX_SHIFT);
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ void hfi_hdrset_egrbfr_offset(__le32 *rbuf, uint32_t val)
Packit 961e70
{
Packit 961e70
	rbuf[1] =
Packit 961e70
	    (rbuf[1] &
Packit 961e70
	     __cpu_to_le32(~(HFI_RHF_EGRBFR_OFFSET_MASK <<
Packit 961e70
			     HFI_RHF_EGRBFR_OFFSET_SHIFT))) |
Packit 961e70
	    __cpu_to_le32((val & HFI_RHF_EGRBFR_OFFSET_MASK) <<
Packit 961e70
			  HFI_RHF_EGRBFR_OFFSET_SHIFT);
Packit 961e70
}
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * This should only be used by a process to update the receive header
Packit 961e70
 * error flags.
Packit 961e70
 */
Packit 961e70
static __inline__ void hfi_hdrset_err_flags(__le32 *rbuf, uint32_t val)
Packit 961e70
{
Packit 961e70
	rbuf[1] |= __cpu_to_le32(val);
Packit 961e70
}
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * This should only be used by a process to write the rhf seq number into
Packit 961e70
 * a subcontext's eager header entry.
Packit 961e70
 */
Packit 961e70
static __inline__ void hfi_hdrset_seq(__le32 *rbuf, uint32_t val)
Packit 961e70
{
Packit 961e70
	rbuf[0] =
Packit 961e70
	    (rbuf[0] &
Packit 961e70
	     __cpu_to_le32(~(HFI_RHF_SEQ_MASK <<
Packit 961e70
			     HFI_RHF_SEQ_SHIFT))) |
Packit 961e70
	    __cpu_to_le32((val & HFI_RHF_SEQ_MASK) << HFI_RHF_SEQ_SHIFT);
Packit 961e70
}
Packit 961e70
Packit 961e70
/* Manage TID entries.  It is possible that not all entries
Packit 961e70
   requested may be allocated.  A matching hfi_free_tid() must be
Packit 961e70
   done for each hfi_update_tid(), because currently no caching or
Packit 961e70
   reuse of expected tid entries is allowed, to work around malloc/free
Packit 961e70
   and mmap/munmap issues.  The driver decides which TID entries to allocate.
Packit 961e70
   If hfi_free_tid is called to free entries in use by a different
Packit 961e70
   send by the same process, data corruption will probably occur,
Packit 961e70
   but only within that process, not for other processes.
Packit 961e70
*/
Packit 961e70
Packit 961e70
/* update tidcnt expected TID entries from the array pointed to by tidinfo. */
Packit 961e70
/* Returns 0 on success, else an errno.  See full description at declaration */
Packit 961e70
static __inline__ int32_t hfi_update_tid(struct _hfi_ctrl *ctrl,
Packit 961e70
					 uint64_t vaddr, uint32_t *length,
Packit 961e70
					 uint64_t tidlist, uint32_t *tidcnt, uint16_t flags)
Packit 961e70
{
Packit 961e70
	struct hfi1_cmd cmd;
Packit 961e70
	struct hfi1_tid_info tidinfo;
Packit Service 7ed5cc
#ifdef PSM_CUDA
Packit Service 7ed5cc
	struct hfi1_tid_info_v2 tidinfov2;
Packit 961e70
#endif
Packit 961e70
	int err;
Packit 961e70
Packit 961e70
	tidinfo.vaddr = vaddr;		/* base address for this send to map */
Packit 961e70
	tidinfo.length = *length;	/* length of vaddr */
Packit 961e70
Packit 961e70
	tidinfo.tidlist = tidlist;	/* driver copies tids back directly */
Packit 961e70
	tidinfo.tidcnt = 0;		/* clear to zero */
Packit 961e70
Packit 961e70
	cmd.type = PSMI_HFI_CMD_TID_UPDATE;
Packit 961e70
	cmd.len = sizeof(tidinfo);
Packit 961e70
	cmd.addr = (__u64) &tidinfo;
Packit Service 7ed5cc
#ifdef PSM_CUDA
Packit Service 7ed5cc
	if (PSMI_IS_DRIVER_GPUDIRECT_ENABLED) {
Packit Service 7ed5cc
		/* Copy values to v2 struct */
Packit Service 7ed5cc
		tidinfov2.vaddr   = tidinfo.vaddr;
Packit Service 7ed5cc
		tidinfov2.length  = tidinfo.length;
Packit Service 7ed5cc
		tidinfov2.tidlist = tidinfo.tidlist;
Packit Service 7ed5cc
		tidinfov2.tidcnt  = tidinfo.tidcnt;
Packit Service 7ed5cc
		tidinfov2.flags   = flags;
Packit Service 7ed5cc
Packit Service 7ed5cc
		cmd.type = PSMI_HFI_CMD_TID_UPDATE_V2;
Packit Service 7ed5cc
		cmd.len = sizeof(tidinfov2);
Packit Service 7ed5cc
		cmd.addr = (__u64) &tidinfov2;
Packit Service 7ed5cc
	}
Packit Service 7ed5cc
#endif
Packit 961e70
Packit 961e70
	err = hfi_cmd_write(ctrl->fd, &cmd, sizeof(cmd));
Packit 961e70
Packit 961e70
	if (err != -1) {
Packit Service 7ed5cc
		struct hfi1_tid_info *rettidinfo =
Packit Service 7ed5cc
			(struct hfi1_tid_info *)cmd.addr;
Packit Service 7ed5cc
		*length = rettidinfo->length;
Packit Service 7ed5cc
		*tidcnt = rettidinfo->tidcnt;
Packit 961e70
	}
Packit 961e70
Packit 961e70
	return err;
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ int32_t hfi_free_tid(struct _hfi_ctrl *ctrl,
Packit 961e70
					 uint64_t tidlist, uint32_t tidcnt)
Packit 961e70
{
Packit 961e70
	struct hfi1_cmd cmd;
Packit 961e70
	struct hfi1_tid_info tidinfo;
Packit 961e70
	int err;
Packit 961e70
Packit 961e70
	tidinfo.tidlist = tidlist;	/* input to driver */
Packit 961e70
	tidinfo.tidcnt = tidcnt;
Packit 961e70
Packit 961e70
	cmd.type = PSMI_HFI_CMD_TID_FREE;
Packit 961e70
	cmd.len = sizeof(tidinfo);
Packit 961e70
	cmd.addr = (__u64) &tidinfo;
Packit 961e70
Packit 961e70
	err = hfi_cmd_write(ctrl->fd, &cmd, sizeof(cmd));
Packit 961e70
Packit 961e70
	return err;
Packit 961e70
}
Packit 961e70
Packit 961e70
static __inline__ int32_t hfi_get_invalidation(struct _hfi_ctrl *ctrl,
Packit 961e70
					 uint64_t tidlist, uint32_t *tidcnt)
Packit 961e70
{
Packit 961e70
	struct hfi1_cmd cmd;
Packit 961e70
	struct hfi1_tid_info tidinfo;
Packit 961e70
	int err;
Packit 961e70
Packit 961e70
	tidinfo.tidlist = tidlist;	/* driver copies tids back directly */
Packit 961e70
	tidinfo.tidcnt = 0;		/* clear to zero */
Packit 961e70
Packit 961e70
	cmd.type = PSMI_HFI_CMD_TID_INVAL_READ;
Packit 961e70
	cmd.len = sizeof(tidinfo);
Packit 961e70
	cmd.addr = (__u64) &tidinfo;
Packit 961e70
Packit 961e70
	err = hfi_cmd_write(ctrl->fd, &cmd, sizeof(cmd));
Packit 961e70
Packit 961e70
	if (err != -1)
Packit 961e70
		*tidcnt = tidinfo.tidcnt;
Packit 961e70
Packit 961e70
	return err;
Packit 961e70
}
Packit 961e70
Packit 961e70
/*
Packit 961e70
 * Data layout in I2C flash (for GUID, etc.)
Packit 961e70
 * All fields are little-endian binary unless otherwise stated
Packit 961e70
 */
Packit 961e70
#define HFI_FLASH_VERSION 2
Packit 961e70
struct hfi_flash {
Packit 961e70
	/* flash layout version (HFI_FLASH_VERSION) */
Packit 961e70
	__u8 if_fversion;
Packit 961e70
	/* checksum protecting if_length bytes */
Packit 961e70
	__u8 if_csum;
Packit 961e70
	/*
Packit 961e70
	 * valid length (in use, protected by if_csum), including
Packit 961e70
	 * if_fversion and if_csum themselves)
Packit 961e70
	 */
Packit 961e70
	__u8 if_length;
Packit 961e70
	/* the GUID, in network order */
Packit 961e70
	__u8 if_guid[8];
Packit 961e70
	/* number of GUIDs to use, starting from if_guid */
Packit 961e70
	__u8 if_numguid;
Packit 961e70
	/* the (last 10 characters of) board serial number, in ASCII */
Packit 961e70
	char if_serial[12];
Packit 961e70
	/* board mfg date (YYYYMMDD ASCII) */
Packit 961e70
	char if_mfgdate[8];
Packit 961e70
	/* last board rework/test date (YYYYMMDD ASCII) */
Packit 961e70
	char if_testdate[8];
Packit 961e70
	/* logging of error counts, TBD */
Packit 961e70
	__u8 if_errcntp[4];
Packit 961e70
	/* powered on hours, updated at driver unload */
Packit 961e70
	__u8 if_powerhour[2];
Packit 961e70
	/* ASCII free-form comment field */
Packit 961e70
	char if_comment[32];
Packit 961e70
	/* Backwards compatible prefix for longer QLogic Serial Numbers */
Packit 961e70
	char if_sprefix[4];
Packit 961e70
	/* 82 bytes used, min flash size is 128 bytes */
Packit 961e70
	__u8 if_future[46];
Packit 961e70
};
Packit 961e70
#endif /* OPA_USER_GEN1_H */