linux/drivers/misc/mic/scif/scif_epd.h
Sudeep Dutt d18243293a misc: mic: SCIF RMA nodeqp and minor miscellaneous changes
This patch adds the SCIF kernel node QP control messages required to
enable SCIF RMAs. Examples of such node QP control messages include
registration, unregistration, remote memory allocation requests,
remote memory unmap and SCIF remote fence requests.

The patch also updates the SCIF driver with minor changes required to
enable SCIF RMAs by adding the new files to the build, initializing
RMA specific information during SCIF endpoint creation, reserving SCIF
DMA channels, initializing SCIF RMA specific global data structures,
adding the IOCTL hooks required for SCIF RMAs and updating RMA
specific debugfs hooks.

Reviewed-by: Ashutosh Dixit <ashutosh.dixit@intel.com>
Reviewed-by: Nikhil Rao <nikhil.rao@intel.com>
Signed-off-by: Sudeep Dutt <sudeep.dutt@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2015-10-04 12:54:54 +01:00

211 lines
6.3 KiB
C

/*
* Intel MIC Platform Software Stack (MPSS)
*
* Copyright(c) 2014 Intel Corporation.
*
* 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.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* Intel SCIF driver.
*
*/
#ifndef SCIF_EPD_H
#define SCIF_EPD_H
#include <linux/delay.h>
#include <linux/scif.h>
#include <linux/scif_ioctl.h>
#define SCIF_EPLOCK_HELD true
enum scif_epd_state {
SCIFEP_UNBOUND,
SCIFEP_BOUND,
SCIFEP_LISTENING,
SCIFEP_CONNECTED,
SCIFEP_CONNECTING,
SCIFEP_MAPPING,
SCIFEP_CLOSING,
SCIFEP_CLLISTEN,
SCIFEP_DISCONNECTED,
SCIFEP_ZOMBIE
};
/*
* struct scif_conreq - Data structure added to the connection list.
*
* @msg: connection request message received
* @list: link to list of connection requests
*/
struct scif_conreq {
struct scifmsg msg;
struct list_head list;
};
/* Size of the RB for the Endpoint QP */
#define SCIF_ENDPT_QP_SIZE 0x1000
/*
* scif_endpt_qp_info - SCIF endpoint queue pair
*
* @qp - Qpair for this endpoint
* @qp_offset - DMA address of the QP
* @gnt_pld - Payload in a SCIF_CNCT_GNT message containing the
* physical address of the remote_qp.
*/
struct scif_endpt_qp_info {
struct scif_qp *qp;
dma_addr_t qp_offset;
dma_addr_t gnt_pld;
};
/*
* struct scif_endpt - The SCIF endpoint data structure
*
* @state: end point state
* @lock: lock synchronizing access to endpoint fields like state etc
* @port: self port information
* @peer: peer port information
* @backlog: maximum pending connection requests
* @qp_info: Endpoint QP information for SCIF messaging
* @remote_dev: scifdev used by this endpt to communicate with remote node.
* @remote_ep: remote endpoint
* @conreqcnt: Keep track of number of connection requests.
* @files: Open file information used to match the id passed in with
* the flush routine.
* @conlist: list of connection requests
* @conwq: waitqueue for connection processing
* @discon: completion used during disconnection
* @sendwq: waitqueue used during sending messages
* @recvwq: waitqueue used during message receipt
* @sendlock: Synchronize ordering of messages sent
* @recvlock: Synchronize ordering of messages received
* @list: link to list of various endpoints like connected, listening etc
* @li_accept: pending ACCEPTREG
* @acceptcnt: pending ACCEPTREG cnt
* @liacceptlist: link to listen accept
* @miacceptlist: link to uaccept
* @listenep: associated listen ep
* @conn_work: Non blocking connect work
* @conn_port: Connection port
* @conn_err: Errors during connection
* @conn_async_state: Async connection
* @conn_pend_wq: Used by poll while waiting for incoming connections
* @conn_list: List of async connection requests
* @rma_info: Information for triggering SCIF RMA and DMA operations
* @mmu_list: link to list of MMU notifier cleanup work
* @anon: anonymous file for use in kernel mode scif poll
*/
struct scif_endpt {
enum scif_epd_state state;
spinlock_t lock;
struct scif_port_id port;
struct scif_port_id peer;
int backlog;
struct scif_endpt_qp_info qp_info;
struct scif_dev *remote_dev;
u64 remote_ep;
int conreqcnt;
struct files_struct *files;
struct list_head conlist;
wait_queue_head_t conwq;
struct completion discon;
wait_queue_head_t sendwq;
wait_queue_head_t recvwq;
struct mutex sendlock;
struct mutex recvlock;
struct list_head list;
struct list_head li_accept;
int acceptcnt;
struct list_head liacceptlist;
struct list_head miacceptlist;
struct scif_endpt *listenep;
struct scif_port_id conn_port;
int conn_err;
int conn_async_state;
wait_queue_head_t conn_pend_wq;
struct list_head conn_list;
struct scif_endpt_rma_info rma_info;
struct list_head mmu_list;
struct file *anon;
};
static inline int scifdev_alive(struct scif_endpt *ep)
{
return _scifdev_alive(ep->remote_dev);
}
/*
* scif_verify_epd:
* ep: SCIF endpoint
*
* Checks several generic error conditions and returns the
* appropriate error.
*/
static inline int scif_verify_epd(struct scif_endpt *ep)
{
if (ep->state == SCIFEP_DISCONNECTED)
return -ECONNRESET;
if (ep->state != SCIFEP_CONNECTED)
return -ENOTCONN;
if (!scifdev_alive(ep))
return -ENODEV;
return 0;
}
static inline int scif_anon_inode_getfile(scif_epd_t epd)
{
epd->anon = anon_inode_getfile("scif", &scif_anon_fops, NULL, 0);
if (IS_ERR(epd->anon))
return PTR_ERR(epd->anon);
return 0;
}
static inline void scif_anon_inode_fput(scif_epd_t epd)
{
if (epd->anon) {
fput(epd->anon);
epd->anon = NULL;
}
}
void scif_cleanup_zombie_epd(void);
void scif_teardown_ep(void *endpt);
void scif_cleanup_ep_qp(struct scif_endpt *ep);
void scif_add_epd_to_zombie_list(struct scif_endpt *ep, bool eplock_held);
void scif_get_node_info(void);
void scif_send_acks(struct scif_dev *dev);
void scif_conn_handler(struct work_struct *work);
int scif_rsrv_port(u16 port);
void scif_get_port(u16 port);
int scif_get_new_port(void);
void scif_put_port(u16 port);
int scif_user_send(scif_epd_t epd, void __user *msg, int len, int flags);
int scif_user_recv(scif_epd_t epd, void __user *msg, int len, int flags);
void scif_cnctreq(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_cnctgnt(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_cnctgnt_ack(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_cnctgnt_nack(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_cnctrej(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_discnct(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_discnt_ack(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_clientsend(struct scif_dev *scifdev, struct scifmsg *msg);
void scif_clientrcvd(struct scif_dev *scifdev, struct scifmsg *msg);
int __scif_connect(scif_epd_t epd, struct scif_port_id *dst, bool non_block);
int __scif_flush(scif_epd_t epd);
int scif_mmap(struct vm_area_struct *vma, scif_epd_t epd);
unsigned int __scif_pollfd(struct file *f, poll_table *wait,
struct scif_endpt *ep);
int __scif_pin_pages(void *addr, size_t len, int *out_prot,
int map_flags, scif_pinned_pages_t *pages);
#endif /* SCIF_EPD_H */