/*
* 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.
*
*/
#include <linux/scif.h>
#include "scif_main.h"
#include "scif_map.h"
static const char * const scif_ep_states[] = {
"Unbound",
"Bound",
"Listening",
"Connected",
"Connecting",
"Mapping",
"Closing",
"Close Listening",
"Disconnected",
"Zombie"};
enum conn_async_state {
ASYNC_CONN_IDLE = 1, /* ep setup for async connect */
ASYNC_CONN_INPROGRESS, /* async connect in progress */
ASYNC_CONN_FLUSH_WORK /* async work flush in progress */
};
scif_epd_t scif_open(void)
{
struct scif_endpt *ep;
might_sleep();
ep = kzalloc(sizeof(*ep), GFP_KERNEL);
if (!ep)
goto err_ep_alloc;
ep->qp_info.qp = kzalloc(sizeof(*ep->qp_info.qp), GFP_KERNEL);
if (!ep->qp_info.qp)
goto err_qp_alloc;
spin_lock_init(&ep->lock);
mutex_init(&ep->sendlock);
mutex_init(&ep->recvlock);
ep->state = SCIFEP_UNBOUND;
dev_dbg(scif_info.mdev.this_device,
"SCIFAPI open: ep %p success\n", ep);
return ep;
err_qp_alloc:
kfree(ep);
err_ep_alloc:
return NULL;
}
EXPORT_SYMBOL_GPL(scif_open);
/*
* scif_disconnect_ep - Disconnects the endpoint if found
* @epd: The end point returned from scif_open()
*/
static struct scif_endpt *scif_disconnect_ep(struct scif_endpt *ep)
{
struct scifmsg msg;
struct scif_endpt *fep = NULL;
struct scif_endpt *tmpep;
struct list_head *pos, *tmpq;
int err;
/*
* Wake up any threads blocked in send()/recv() before closing
* out the connection. Grabbing and releasing the send/recv lock
* will ensure that any blocked senders/receivers have exited for
* Ring 0 endpoints. It is a Ring 0 bug to call send/recv after
* close. Ring 3 endpoints are not affected since close will not
* be called while there are IOCTLs executing.
*/
wake_up_interruptible(&ep->sendwq);
wake_up_interruptible(&ep->recvwq);
mutex_lock(&ep->sendlock);
mutex_unlock(&ep->sendlock);
mutex_lock(&ep->recvlock);
mutex_unlock(&ep->recvlock);
/* Remove from the connected list */
mutex_lock(&scif_info.connlock);
list_for_each_safe(pos, tmpq, &scif_info.connected) {
tmpep = list_entry(pos, struct scif_endpt, list);