/*
 * Intel MIC Platform Software Stack (MPSS)
 *
 * Copyright(c) 2015 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 "scif_main.h"

/**
 * scif_recv_mark: Handle SCIF_MARK request
 * @msg:	Interrupt message
 *
 * The peer has requested a mark.
 */
void scif_recv_mark(struct scif_dev *scifdev, struct scifmsg *msg)
{
	struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
	int mark = 0;
	int err;

	err = _scif_fence_mark(ep, &mark);
	if (err)
		msg->uop = SCIF_MARK_NACK;
	else
		msg->uop = SCIF_MARK_ACK;
	msg->payload[0] = ep->remote_ep;
	msg->payload[2] = mark;
	scif_nodeqp_send(ep->remote_dev, msg);
}

/**
 * scif_recv_mark_resp: Handle SCIF_MARK_(N)ACK messages.
 * @msg:	Interrupt message
 *
 * The peer has responded to a SCIF_MARK message.
 */
void scif_recv_mark_resp(struct scif_dev *scifdev, struct scifmsg *msg)
{
	struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
	struct scif_fence_info *fence_req =
		(struct scif_fence_info *)msg->payload[1];

	mutex_lock(&ep->rma_info.rma_lock);
	if (msg->uop == SCIF_MARK_ACK) {
		fence_req->state = OP_COMPLETED;
		fence_req->dma_mark = (int)msg->payload[2];
	} else {
		fence_req->state = OP_FAILED;
	}
	mutex_unlock(&ep->rma_info.rma_lock);
	complete(&fence_req->comp);
}

/**
 * scif_recv_wait: Handle SCIF_WAIT request
 * @msg:	Interrupt message
 *
 * The peer has requested waiting on a fence.
 */
void scif_recv_wait(struct scif_dev *scifdev, struct scifmsg *msg)
{
	struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
	struct scif_remote_fence_info *fence;

	/*
	 * Allocate structure for remote fence information and
	 * send a NACK if the allocation failed. The peer will
	 * return ENOMEM upon receiving a NACK.
	 */
	fence = kmalloc(sizeof(*fence), GFP_KERNEL);
	if (!fence) {
		msg->payload[0] = ep->remote_ep;
		msg->uop = SCIF_WAIT_NACK;
		scif_nodeqp_send(ep->remote_dev, msg);
		return;
	}

	/* Prepare the fence request */
	memcpy(&fence->msg, msg, sizeof(struct scifmsg));
	INIT_LIST_HEAD(&fence->list);

	/* Insert to the global remote fence request list */
	mutex_lock(&scif_info.fencelock);
	atomic_inc(&ep->rma_info.fence_refcount);
	list_add_tail(&fence->list, &scif_info.fence);
	mutex_unlock(&scif_info.fencelock);

	schedule_work(&scif_info.misc_work);
}

/**
 * scif_recv_wait_resp: Handle SCIF_WAIT_(N)ACK messages.
 * @msg:	Interrupt message
 *
 * The peer has responded to a SCIF_WAIT message.
 */
void scif_recv_wait_resp(struct scif_dev *scifdev, struct scifmsg *msg)
{
	struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
	struct scif_fence_info *fence_req =
		(struct scif_fence_info *)msg->payload[1];

	mutex_lock(&ep->rma_info.rma_lock);
	if (msg->uop == SCIF_WAIT_ACK)
		fence_req->state = OP_COMPLETED;
	else
		fence_req->state = OP_FAILED;
	mutex_unlock(&ep->rma_info.rma_lock);
	complete(&fence_req->comp);
}

/**
 * scif_recv_sig_local: Handle SCIF_SIG_LOCAL request
 * @msg:	Interrupt message
 *
 * The peer has requested a signal on a local offset.
 */
void scif_recv_sig_local(struct scif_dev *scifdev, struct scifmsg *msg)
{
	struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
	int err;

	err = scif_prog_signal(ep, msg->payload[1], msg->payload[2],
			       SCIF_WINDOW_SELF);
	if (err)
		msg->uop = SCIF_SIG_NACK;
	else
		msg->uop = SCIF_SIG_ACK;
	msg->payload[0] = ep->remote_ep;
	scif_nodeqp_send(ep->remote_dev, msg);
}

/**
 * scif_recv_sig_remote: Handle SCIF_SIGNAL_REMOTE request
 * @msg:	Interrupt message
 *
 * The peer has requested a signal on a remote offset.
 */
void scif_recv_sig_remote(struct scif_dev *scifdev, struct scifmsg *msg)
{
	struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
	int err;

	err = scif_prog_signal(ep, msg->payload[1], msg->payload[2],
			       SCIF_WINDOW_PEER);
	if (err)
		msg->uop = SCIF_SIG_NACK;
	else
		msg->uop = SCIF_SIG_ACK;
	msg->payload[0] = ep->remote_ep;
	scif_nodeqp_send(ep->remote_dev, msg);
}

/**
 * scif_recv_sig_resp: Handle SCIF_SIG_(N)ACK messages.
 * @msg:	Interrupt message
 *
 * The peer has responded to a signal request.
 */
void scif_recv_sig_resp(struct scif_dev *scifdev, struct scifmsg *msg)
{
	struct scif_endpt *ep = (struct scif_endpt *)msg->payload[0];
	struct scif_fence_info *fence_req =
		(struct scif_fence_info *)msg->payload[3];

	mutex_lock(&ep->rma_info.rma_lock);
	if (msg->uop == SCIF_SIG_ACK)
		fence_req->state = OP_COMPLETED;
	else
		fence_req->state = OP_FAILED;
	mutex_unlock(&ep->rma_info.rma_lock);
	complete(&fence_req->comp);
}

static inline void *scif_get_local_va(off_t off, struct scif_window *window)
{
	struct page **pages = window->pinned_pages->pages;
	int page_nr = (off - window->offset) >> PAGE_SHIFT;
	off_t page_off = off & ~PAGE_MASK;

	return page_address(pages[page_nr]) + page_off;
}

static void scif_prog_signal_cb(void *arg)
{
	struct scif_status *status = arg;

	dma_pool_free(status->ep->remote_dev->signal_pool, status,
		      status->src_dma_addr);
}

static int _scif_prog_signal(scif_epd_t epd, dma_addr_t dst, u64 val)
{
	struct scif_endpt *ep = (struct scif_endpt *)epd;
	struct dma_chan *chan = ep->rma_info.dma_chan;
	struct dma_device *ddev = chan->device;
	bool x100 = !is_dma_copy_aligned(chan->device, 1, 1, 1);
	struct dma_async_tx_descriptor *tx;
	struct scif_status *status = NULL;
	dma_addr_t src;
	dma_cookie_t cookie;
	int err;

	tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, DMA_PREP_FENCE);
	if (!tx) {
		err = -ENOMEM;
		dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
			__func__, __LINE__, err);
		goto alloc_fail;
	}
	cookie = tx->tx_submit(tx);
	if (dma_submit_error(cookie)) {
		err = (int)cookie;
		dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
			__func__, __LINE__, err);
		goto alloc_fail;
	}
	dma_async_issue_pending(chan);
	if (x100) {
		/*
		 * For X100 use the status descriptor to write the value to
		 * the destination.
		 */
		tx = ddev->device_prep_dma_imm_data(chan, dst, val, 0);
	} else {
		status = dma_pool_alloc(ep->remote_dev->signal_pool, GFP_KERNEL,
					&src);
		if (!status) {
			err = -ENOMEM;
			dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
				__func__, __LINE__, err);
			goto alloc_fail;
		}
		status->val = val;
		status->src_dma_addr = src;
		status->ep = ep;
		src += offsetof(struct scif_status, val);
		tx = ddev->device_prep_dma_memcpy(chan, dst, src, sizeof(val),
						  DMA_PREP_INTERRUPT);
	}
	if (!tx) {
		err = -ENOMEM;
		dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
			__func__, __LINE__, err);
		goto dma_fail;
	}
	if (!x100) {
		tx->callback = scif_prog_signal_cb;
		tx->callback_param = status;
	}
	cookie = tx->tx_submit(tx);
	if (dma_submit_error(cookie)) {
		err = -EIO;
		dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
			__func__, __LINE__, err);
		goto dma_fail;
	}
	dma_async_issue_pending(chan);
	return 0;
dma_fail:
	if (!x100)
		dma_pool_free(ep->remote_dev->signal_pool, status,
			      status->src_dma_addr);
alloc_fail:
	return err;
}

/*
 * scif_prog_signal:
 * @epd - Endpoint Descriptor
 * @offset - registered address to write @val to
 * @val - Value to be written at @offset
 * @type - Type of the window.
 *
 * Arrange to write a value to the registered offset after ensuring that the
 * offset provided is indeed valid.
 */
int scif_prog_signal(scif_epd_t epd, off_t offset, u64 val,
		     enum scif_window_type type)
{
	struct scif_endpt *ep = (struct scif_endpt *)epd;
	struct scif_window *window = NULL;
	struct scif_rma_req req;
	dma_addr_t dst_dma_addr;
	int err;

	mutex_lock(&ep->rma_info.rma_lock);
	req.out_window = &window;
	req.offset = offset;
	req.nr_bytes = sizeof(u64);
	req.prot = SCIF_PROT_WRITE;
	req.type = SCIF_WINDOW_SINGLE;
	if (type == SCIF_WINDOW_SELF)
		req.head = &ep->rma_info.reg_list;
	else
		req.head = &ep->rma_info.remote_reg_list;
	/* Does a valid window exist? */
	err = scif_query_window(&req);
	if (err) {
		dev_err(scif_info.mdev.this_device,
			"%s %d err %d\n", __func__, __LINE__, err);
		goto unlock_ret;
	}

	if (scif_is_mgmt_node() && scifdev_self(ep->remote_dev)) {
		u64 *dst_virt;

		if (type == SCIF_WINDOW_SELF)
			dst_virt = scif_get_local_va(offset, window);
		else
			dst_virt =
			scif_get_local_va(offset, (struct scif_window *)
					  window->peer_window);
		*dst_virt = val;
	} else {
		dst_dma_addr = __scif_off_to_dma_addr(window, offset);
		err = _scif_prog_signal(epd, dst_dma_addr, val);
	}
unlock_ret:
	mutex_unlock(&ep->rma_info.rma_lock);
	return err;
}

static int _scif_fence_wait(scif_epd_t epd, int mark)
{
	struct scif_endpt *ep = (struct scif_endpt *)epd;
	dma_cookie_t cookie = mark & ~SCIF_REMOTE_FENCE;
	int err;

	/* Wait for DMA callback in scif_fence_mark_cb(..) */
	err = wait_event_interruptible_timeout(ep->rma_info.markwq,
					       dma_async_is_tx_complete(
					       ep->rma_info.dma_chan,
					       cookie, NULL, NULL) ==
					       DMA_COMPLETE,
					       SCIF_NODE_ALIVE_TIMEOUT);
	if (!err)
		err = -ETIMEDOUT;
	else if (err > 0)
		err = 0;
	return err;
}

/**
 * scif_rma_handle_remote_fences:
 *
 * This routine services remote fence requests.
 */
void scif_rma_handle_remote_fences(void)
{
	struct list_head *item, *tmp;
	struct scif_remote_fence_info *fence;
	struct scif_endpt *ep;
	int mark, err;

	might_sleep();
	mutex_lock(&scif_info.fencelock);
	list_for_each_safe(item, tmp, &scif_info.fence) {
		fence = list_entry(item, struct scif_remote_fence_info,
				   list);
		/* Remove fence from global list */
		list_del(&fence->list);

		/* Initiate the fence operation */
		ep = (struct scif_endpt *)fence->msg.payload[0];
		mark = fence->msg.payload[2];
		err = _scif_fence_wait(ep, mark);
		if (err)
			fence->msg.uop = SCIF_WAIT_NACK;
		else
			fence->msg.uop = SCIF_WAIT_ACK;
		fence->msg.payload[0] = ep->remote_ep;
		scif_nodeqp_send(ep->remote_dev, &fence->msg);
		kfree(fence);
		if (!atomic_sub_return(1, &ep->rma_info.fence_refcount))
			schedule_work(&scif_info.misc_work);
	}
	mutex_unlock(&scif_info.fencelock);
}

static int _scif_send_fence(scif_epd_t epd, int uop, int mark, int *out_mark)
{
	int err;
	struct scifmsg msg;
	struct scif_fence_info *fence_req;
	struct scif_endpt *ep = (struct scif_endpt *)epd;

	fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL);
	if (!fence_req) {
		err = -ENOMEM;
		goto error;
	}

	fence_req->state = OP_IN_PROGRESS;
	init_completion(&fence_req->comp);

	msg.src = ep->port;
	msg.uop = uop;
	msg.payload[0] = ep->remote_ep;
	msg.payload[1] = (u64)fence_req;
	if (uop == SCIF_WAIT)
		msg.payload[2] = mark;
	spin_lock(&ep->lock);
	if (ep->state == SCIFEP_CONNECTED)
		err = scif_nodeqp_send(ep->remote_dev, &msg);
	else
		err = -ENOTCONN;
	spin_unlock(&ep->lock);
	if (err)
		goto error_free;
retry:
	/* Wait for a SCIF_WAIT_(N)ACK message */
	err = wait_for_completion_timeout(&fence_req->comp,
					  SCIF_NODE_ALIVE_TIMEOUT);
	if (!err && scifdev_alive(ep))
		goto retry;
	if (!err)
		err = -ENODEV;
	if (err > 0)
		err = 0;
	mutex_lock(&ep->rma_info.rma_lock);
	if (err < 0) {
		if (fence_req->state == OP_IN_PROGRESS)
			fence_req->state = OP_FAILED;
	}
	if (fence_req->state == OP_FAILED && !err)
		err = -ENOMEM;
	if (uop == SCIF_MARK && fence_req->state == OP_COMPLETED)
		*out_mark = SCIF_REMOTE_FENCE | fence_req->dma_mark;
	mutex_unlock(&ep->rma_info.rma_lock);
error_free:
	kfree(fence_req);
error:
	return err;
}

/**
 * scif_send_fence_mark:
 * @epd: end point descriptor.
 * @out_mark: Output DMA mark reported by peer.
 *
 * Send a remote fence mark request.
 */
static int scif_send_fence_mark(scif_epd_t epd, int *out_mark)
{
	return _scif_send_fence(epd, SCIF_MARK, 0, out_mark);
}

/**
 * scif_send_fence_wait:
 * @epd: end point descriptor.
 * @mark: DMA mark to wait for.
 *
 * Send a remote fence wait request.
 */
static int scif_send_fence_wait(scif_epd_t epd, int mark)
{
	return _scif_send_fence(epd, SCIF_WAIT, mark, NULL);
}

static int _scif_send_fence_signal_wait(struct scif_endpt *ep,
					struct scif_fence_info *fence_req)
{
	int err;

retry:
	/* Wait for a SCIF_SIG_(N)ACK message */
	err = wait_for_completion_timeout(&fence_req->comp,
					  SCIF_NODE_ALIVE_TIMEOUT);
	if (!err && scifdev_alive(ep))
		goto retry;
	if (!err)
		err = -ENODEV;
	if (err > 0)
		err = 0;
	if (err < 0) {
		mutex_lock(&ep->rma_info.rma_lock);
		if (fence_req->state == OP_IN_PROGRESS)
			fence_req->state = OP_FAILED;
		mutex_unlock(&ep->rma_info.rma_lock);
	}
	if (fence_req->state == OP_FAILED && !err)
		err = -ENXIO;
	return err;
}

/**
 * scif_send_fence_signal:
 * @epd - endpoint descriptor
 * @loff - local offset
 * @lval - local value to write to loffset
 * @roff - remote offset
 * @rval - remote value to write to roffset
 * @flags - flags
 *
 * Sends a remote fence signal request
 */
static int scif_send_fence_signal(scif_epd_t epd, off_t roff, u64 rval,
				  off_t loff, u64 lval, int flags)
{
	int err = 0;
	struct scifmsg msg;
	struct scif_fence_info *fence_req;
	struct scif_endpt *ep = (struct scif_endpt *)epd;

	fence_req = kmalloc(sizeof(*fence_req), GFP_KERNEL);
	if (!fence_req) {
		err = -ENOMEM;
		goto error;
	}

	fence_req->state = OP_IN_PROGRESS;
	init_completion(&fence_req->comp);
	msg.src = ep->port;
	if (flags & SCIF_SIGNAL_LOCAL) {
		msg.uop = SCIF_SIG_LOCAL;
		msg.payload[0] = ep->remote_ep;
		msg.payload[1] = roff;
		msg.payload[2] = rval;
		msg.payload[3] = (u64)fence_req;
		spin_lock(&ep->lock);
		if (ep->state == SCIFEP_CONNECTED)
			err = scif_nodeqp_send(ep->remote_dev, &msg);
		else
			err = -ENOTCONN;
		spin_unlock(&ep->lock);
		if (err)
			goto error_free;
		err = _scif_send_fence_signal_wait(ep, fence_req);
		if (err)
			goto error_free;
	}
	fence_req->state = OP_IN_PROGRESS;

	if (flags & SCIF_SIGNAL_REMOTE) {
		msg.uop = SCIF_SIG_REMOTE;
		msg.payload[0] = ep->remote_ep;
		msg.payload[1] = loff;
		msg.payload[2] = lval;
		msg.payload[3] = (u64)fence_req;
		spin_lock(&ep->lock);
		if (ep->state == SCIFEP_CONNECTED)
			err = scif_nodeqp_send(ep->remote_dev, &msg);
		else
			err = -ENOTCONN;
		spin_unlock(&ep->lock);
		if (err)
			goto error_free;
		err = _scif_send_fence_signal_wait(ep, fence_req);
	}
error_free:
	kfree(fence_req);
error:
	return err;
}

static void scif_fence_mark_cb(void *arg)
{
	struct scif_endpt *ep = (struct scif_endpt *)arg;

	wake_up_interruptible(&ep->rma_info.markwq);
	atomic_dec(&ep->rma_info.fence_refcount);
}

/*
 * _scif_fence_mark:
 *
 * @epd - endpoint descriptor
 * Set up a mark for this endpoint and return the value of the mark.
 */
int _scif_fence_mark(scif_epd_t epd, int *mark)
{
	struct scif_endpt *ep = (struct scif_endpt *)epd;
	struct dma_chan *chan = ep->rma_info.dma_chan;
	struct dma_device *ddev = chan->device;
	struct dma_async_tx_descriptor *tx;
	dma_cookie_t cookie;
	int err;

	tx = ddev->device_prep_dma_memcpy(chan, 0, 0, 0, DMA_PREP_FENCE);
	if (!tx) {
		err = -ENOMEM;
		dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
			__func__, __LINE__, err);
		return err;
	}
	cookie = tx->tx_submit(tx);
	if (dma_submit_error(cookie)) {
		err = (int)cookie;
		dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
			__func__, __LINE__, err);
		return err;
	}
	dma_async_issue_pending(chan);
	tx = ddev->device_prep_dma_interrupt(chan, DMA_PREP_INTERRUPT);
	if (!tx) {
		err = -ENOMEM;
		dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
			__func__, __LINE__, err);
		return err;
	}
	tx->callback = scif_fence_mark_cb;
	tx->callback_param = ep;
	*mark = cookie = tx->tx_submit(tx);
	if (dma_submit_error(cookie)) {
		err = (int)cookie;
		dev_err(&ep->remote_dev->sdev->dev, "%s %d err %d\n",
			__func__, __LINE__, err);
		return err;
	}
	atomic_inc(&ep->rma_info.fence_refcount);
	dma_async_issue_pending(chan);
	return 0;
}

#define SCIF_LOOPB_MAGIC_MARK 0xdead

int scif_fence_mark(scif_epd_t epd, int flags, int *mark)
{
	struct scif_endpt *ep = (struct scif_endpt *)epd;
	int err = 0;

	dev_dbg(scif_info.mdev.this_device,
		"SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x\n",
		ep, flags, *mark);
	err = scif_verify_epd(ep);
	if (err)
		return err;

	/* Invalid flags? */
	if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER))
		return -EINVAL;

	/* At least one of init self or peer RMA should be set */
	if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER)))
		return -EINVAL;

	/* Exactly one of init self or peer RMA should be set but not both */
	if ((flags & SCIF_FENCE_INIT_SELF) && (flags & SCIF_FENCE_INIT_PEER))
		return -EINVAL;

	/*
	 * Management node loopback does not need to use DMA.
	 * Return a valid mark to be symmetric.
	 */
	if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) {
		*mark = SCIF_LOOPB_MAGIC_MARK;
		return 0;
	}

	if (flags & SCIF_FENCE_INIT_SELF)
		err = _scif_fence_mark(epd, mark);
	else
		err = scif_send_fence_mark(ep, mark);

	if (err)
		dev_err(scif_info.mdev.this_device,
			"%s %d err %d\n", __func__, __LINE__, err);
	dev_dbg(scif_info.mdev.this_device,
		"SCIFAPI fence_mark: ep %p flags 0x%x mark 0x%x err %d\n",
		ep, flags, *mark, err);
	return err;
}
EXPORT_SYMBOL_GPL(scif_fence_mark);

int scif_fence_wait(scif_epd_t epd, int mark)
{
	struct scif_endpt *ep = (struct scif_endpt *)epd;
	int err = 0;

	dev_dbg(scif_info.mdev.this_device,
		"SCIFAPI fence_wait: ep %p mark 0x%x\n",
		ep, mark);
	err = scif_verify_epd(ep);
	if (err)
		return err;
	/*
	 * Management node loopback does not need to use DMA.
	 * The only valid mark provided is 0 so simply
	 * return success if the mark is valid.
	 */
	if (scifdev_self(ep->remote_dev) && scif_is_mgmt_node()) {
		if (mark == SCIF_LOOPB_MAGIC_MARK)
			return 0;
		else
			return -EINVAL;
	}
	if (mark & SCIF_REMOTE_FENCE)
		err = scif_send_fence_wait(epd, mark);
	else
		err = _scif_fence_wait(epd, mark);
	if (err < 0)
		dev_err(scif_info.mdev.this_device,
			"%s %d err %d\n", __func__, __LINE__, err);
	return err;
}
EXPORT_SYMBOL_GPL(scif_fence_wait);

int scif_fence_signal(scif_epd_t epd, off_t loff, u64 lval,
		      off_t roff, u64 rval, int flags)
{
	struct scif_endpt *ep = (struct scif_endpt *)epd;
	int err = 0;

	dev_dbg(scif_info.mdev.this_device,
		"SCIFAPI fence_signal: ep %p loff 0x%lx lval 0x%llx roff 0x%lx rval 0x%llx flags 0x%x\n",
		ep, loff, lval, roff, rval, flags);
	err = scif_verify_epd(ep);
	if (err)
		return err;

	/* Invalid flags? */
	if (flags & ~(SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER |
			SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE))
		return -EINVAL;

	/* At least one of init self or peer RMA should be set */
	if (!(flags & (SCIF_FENCE_INIT_SELF | SCIF_FENCE_INIT_PEER)))
		return -EINVAL;

	/* Exactly one of init self or peer RMA should be set but not both */
	if ((flags & SCIF_FENCE_INIT_SELF) && (flags & SCIF_FENCE_INIT_PEER))
		return -EINVAL;

	/* At least one of SCIF_SIGNAL_LOCAL or SCIF_SIGNAL_REMOTE required */
	if (!(flags & (SCIF_SIGNAL_LOCAL | SCIF_SIGNAL_REMOTE)))
		return -EINVAL;

	/* Only Dword offsets allowed */
	if ((flags & SCIF_SIGNAL_LOCAL) && (loff & (sizeof(u32) - 1)))
		return -EINVAL;

	/* Only Dword aligned offsets allowed */
	if ((flags & SCIF_SIGNAL_REMOTE) && (roff & (sizeof(u32) - 1)))
		return -EINVAL;

	if (flags & SCIF_FENCE_INIT_PEER) {
		err = scif_send_fence_signal(epd, roff, rval, loff,
					     lval, flags);
	} else {
		/* Local Signal in Local RAS */
		if (flags & SCIF_SIGNAL_LOCAL) {
			err = scif_prog_signal(epd, loff, lval,
					       SCIF_WINDOW_SELF);
			if (err)
				goto error_ret;
		}

		/* Signal in Remote RAS */
		if (flags & SCIF_SIGNAL_REMOTE)
			err = scif_prog_signal(epd, roff,
					       rval, SCIF_WINDOW_PEER);
	}
error_ret:
	if (err)
		dev_err(scif_info.mdev.this_device,
			"%s %d err %d\n", __func__, __LINE__, err);
	return err;
}
EXPORT_SYMBOL_GPL(scif_fence_signal);
