linux_dsm_epyc7002/include/uapi/misc/cxl.h
Philippe Bergheaud b810253bd9 cxl: Add mechanism for delivering AFU driver specific events
This adds an afu_driver_ops structure with fetch_event() and
event_delivered() callbacks. An AFU driver such as cxlflash can fill
this out and associate it with a context to enable passing custom AFU
specific events to userspace.

This also adds a new kernel API function cxl_context_pending_events(),
that the AFU driver can use to notify the cxl driver that new specific
events are ready to be delivered, and wake up anyone waiting on the
context wait queue.

The current count of AFU driver specific events is stored in the field
afu_driver_events of the context structure.

The cxl driver checks the afu_driver_events count during poll, select,
read, etc. calls to check if an AFU driver specific event is pending,
and calls fetch_event() to obtain and deliver that event. This way, the
cxl driver takes care of all the usual locking semantics around these
calls and handles all the generic cxl events, so that the AFU driver
only needs to worry about it's own events.

fetch_event() return a struct cxl_event_afu_driver_reserved, allocated
by the AFU driver, and filled in with the specific event information and
size. Total event size (header + data) should not be greater than
CXL_READ_MIN_SIZE (4K).

Th cxl driver prepends an appropriate cxl event header, copies the event
to userspace, and finally calls event_delivered() to return the status of
the operation to the AFU driver. The event is identified by the context
and cxl_event_afu_driver_reserved pointers.

Since AFU drivers provide their own means for userspace to obtain the
AFU file descriptor (i.e. cxlflash uses an ioctl on their scsi file
descriptor to obtain the AFU file descriptor) and the generic cxl driver
will never use this event, the ABI of the event is up to each individual
AFU driver.

Signed-off-by: Philippe Bergheaud <felix@linux.vnet.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
2016-06-28 18:34:56 +10:00

154 lines
3.7 KiB
C

/*
* Copyright 2014 IBM Corp.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#ifndef _UAPI_MISC_CXL_H
#define _UAPI_MISC_CXL_H
#include <linux/types.h>
#include <linux/ioctl.h>
struct cxl_ioctl_start_work {
__u64 flags;
__u64 work_element_descriptor;
__u64 amr;
__s16 num_interrupts;
__s16 reserved1;
__s32 reserved2;
__u64 reserved3;
__u64 reserved4;
__u64 reserved5;
__u64 reserved6;
};
#define CXL_START_WORK_AMR 0x0000000000000001ULL
#define CXL_START_WORK_NUM_IRQS 0x0000000000000002ULL
#define CXL_START_WORK_ERR_FF 0x0000000000000004ULL
#define CXL_START_WORK_ALL (CXL_START_WORK_AMR |\
CXL_START_WORK_NUM_IRQS |\
CXL_START_WORK_ERR_FF)
/* Possible modes that an afu can be in */
#define CXL_MODE_DEDICATED 0x1
#define CXL_MODE_DIRECTED 0x2
/* possible flags for the cxl_afu_id flags field */
#define CXL_AFUID_FLAG_SLAVE 0x1 /* In directed-mode afu is in slave mode */
struct cxl_afu_id {
__u64 flags; /* One of CXL_AFUID_FLAG_X */
__u32 card_id;
__u32 afu_offset;
__u32 afu_mode; /* one of the CXL_MODE_X */
__u32 reserved1;
__u64 reserved2;
__u64 reserved3;
__u64 reserved4;
__u64 reserved5;
__u64 reserved6;
};
/* base adapter image header is included in the image */
#define CXL_AI_NEED_HEADER 0x0000000000000001ULL
#define CXL_AI_ALL CXL_AI_NEED_HEADER
#define CXL_AI_HEADER_SIZE 128
#define CXL_AI_BUFFER_SIZE 4096
#define CXL_AI_MAX_ENTRIES 256
#define CXL_AI_MAX_CHUNK_SIZE (CXL_AI_BUFFER_SIZE * CXL_AI_MAX_ENTRIES)
struct cxl_adapter_image {
__u64 flags;
__u64 data;
__u64 len_data;
__u64 len_image;
__u64 reserved1;
__u64 reserved2;
__u64 reserved3;
__u64 reserved4;
};
/* ioctl numbers */
#define CXL_MAGIC 0xCA
/* AFU devices */
#define CXL_IOCTL_START_WORK _IOW(CXL_MAGIC, 0x00, struct cxl_ioctl_start_work)
#define CXL_IOCTL_GET_PROCESS_ELEMENT _IOR(CXL_MAGIC, 0x01, __u32)
#define CXL_IOCTL_GET_AFU_ID _IOR(CXL_MAGIC, 0x02, struct cxl_afu_id)
/* adapter devices */
#define CXL_IOCTL_DOWNLOAD_IMAGE _IOW(CXL_MAGIC, 0x0A, struct cxl_adapter_image)
#define CXL_IOCTL_VALIDATE_IMAGE _IOW(CXL_MAGIC, 0x0B, struct cxl_adapter_image)
#define CXL_READ_MIN_SIZE 0x1000 /* 4K */
/* Events from read() */
enum cxl_event_type {
CXL_EVENT_RESERVED = 0,
CXL_EVENT_AFU_INTERRUPT = 1,
CXL_EVENT_DATA_STORAGE = 2,
CXL_EVENT_AFU_ERROR = 3,
CXL_EVENT_AFU_DRIVER = 4,
};
struct cxl_event_header {
__u16 type;
__u16 size;
__u16 process_element;
__u16 reserved1;
};
struct cxl_event_afu_interrupt {
__u16 flags;
__u16 irq; /* Raised AFU interrupt number */
__u32 reserved1;
};
struct cxl_event_data_storage {
__u16 flags;
__u16 reserved1;
__u32 reserved2;
__u64 addr;
__u64 dsisr;
__u64 reserved3;
};
struct cxl_event_afu_error {
__u16 flags;
__u16 reserved1;
__u32 reserved2;
__u64 error;
};
struct cxl_event_afu_driver_reserved {
/*
* Defines the buffer passed to the cxl driver by the AFU driver.
*
* This is not ABI since the event header.size passed to the user for
* existing events is set in the read call to sizeof(cxl_event_header)
* + sizeof(whatever event is being dispatched) and the user is already
* required to use a 4K buffer on the read call.
*
* Of course the contents will be ABI, but that's up the AFU driver.
*/
size_t data_size;
u8 data[];
};
struct cxl_event {
struct cxl_event_header header;
union {
struct cxl_event_afu_interrupt irq;
struct cxl_event_data_storage fault;
struct cxl_event_afu_error afu_error;
struct cxl_event_afu_driver_reserved afu_driver_event;
};
};
#endif /* _UAPI_MISC_CXL_H */