/*
 * This file is provided under a dual BSD/GPLv2 license.  When using or
 *   redistributing this file, you may do so under either license.
 *
 *   GPL LICENSE SUMMARY
 *
 *   Copyright (C) 2015 EMC Corporation. All Rights Reserved.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of version 2 of the GNU General Public License 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.
 *
 *   BSD LICENSE
 *
 *   Copyright (C) 2015 EMC Corporation. All Rights Reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copy
 *       notice, this list of conditions and the following disclaimer in
 *       the documentation and/or other materials provided with the
 *       distribution.
 *     * Neither the name of Intel Corporation nor the names of its
 *       contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * PCIe NTB Pingpong Linux driver
 *
 * Contact Information:
 * Allen Hubbe <Allen.Hubbe@emc.com>
 */

/* Note: load this module with option 'dyndbg=+p' */

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

#include <linux/dma-mapping.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/spinlock.h>

#include <linux/ntb.h>

#define DRIVER_NAME			"ntb_pingpong"
#define DRIVER_DESCRIPTION		"PCIe NTB Simple Pingpong Client"

#define DRIVER_LICENSE			"Dual BSD/GPL"
#define DRIVER_VERSION			"1.0"
#define DRIVER_RELDATE			"24 March 2015"
#define DRIVER_AUTHOR			"Allen Hubbe <Allen.Hubbe@emc.com>"

MODULE_LICENSE(DRIVER_LICENSE);
MODULE_VERSION(DRIVER_VERSION);
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESCRIPTION);

static unsigned int unsafe;
module_param(unsafe, uint, 0644);
MODULE_PARM_DESC(unsafe, "Run even though ntb operations may be unsafe");

static unsigned int delay_ms = 1000;
module_param(delay_ms, uint, 0644);
MODULE_PARM_DESC(delay_ms, "Milliseconds to delay the response to peer");

static unsigned long db_init = 0x7;
module_param(db_init, ulong, 0644);
MODULE_PARM_DESC(delay_ms, "Initial doorbell bits to ring on the peer");

struct pp_ctx {
	struct ntb_dev			*ntb;
	u64				db_bits;
	/* synchronize access to db_bits by ping and pong */
	spinlock_t			db_lock;
	struct timer_list		db_timer;
	unsigned long			db_delay;
};

static void pp_ping(unsigned long ctx)
{
	struct pp_ctx *pp = (void *)ctx;
	unsigned long irqflags;
	u64 db_bits, db_mask;
	u32 spad_rd, spad_wr;

	spin_lock_irqsave(&pp->db_lock, irqflags);
	{
		db_mask = ntb_db_valid_mask(pp->ntb);
		db_bits = ntb_db_read(pp->ntb);

		if (db_bits) {
			dev_dbg(&pp->ntb->dev,
				"Masked pongs %#llx\n",
				db_bits);
			ntb_db_clear(pp->ntb, db_bits);
		}

		db_bits = ((pp->db_bits | db_bits) << 1) & db_mask;

		if (!db_bits)
			db_bits = db_init;

		spad_rd = ntb_spad_read(pp->ntb, 0);
		spad_wr = spad_rd + 1;

		dev_dbg(&pp->ntb->dev,
			"Ping bits %#llx read %#x write %#x\n",
			db_bits, spad_rd, spad_wr);

		ntb_peer_spad_write(pp->ntb, 0, spad_wr);
		ntb_peer_db_set(pp->ntb, db_bits);
		ntb_db_clear_mask(pp->ntb, db_mask);

		pp->db_bits = 0;
	}
	spin_unlock_irqrestore(&pp->db_lock, irqflags);
}

static void pp_link_event(void *ctx)
{
	struct pp_ctx *pp = ctx;

	if (ntb_link_is_up(pp->ntb, NULL, NULL) == 1) {
		dev_dbg(&pp->ntb->dev, "link is up\n");
		pp_ping((unsigned long)pp);
	} else {
		dev_dbg(&pp->ntb->dev, "link is down\n");
		del_timer(&pp->db_timer);
	}
}

static void pp_db_event(void *ctx, int vec)
{
	struct pp_ctx *pp = ctx;
	u64 db_bits, db_mask;
	unsigned long irqflags;

	spin_lock_irqsave(&pp->db_lock, irqflags);
	{
		db_mask = ntb_db_vector_mask(pp->ntb, vec);
		db_bits = db_mask & ntb_db_read(pp->ntb);
		ntb_db_set_mask(pp->ntb, db_mask);
		ntb_db_clear(pp->ntb, db_bits);

		pp->db_bits |= db_bits;

		mod_timer(&pp->db_timer, jiffies + pp->db_delay);

		dev_dbg(&pp->ntb->dev,
			"Pong vec %d bits %#llx\n",
			vec, db_bits);
	}
	spin_unlock_irqrestore(&pp->db_lock, irqflags);
}

static const struct ntb_ctx_ops pp_ops = {
	.link_event = pp_link_event,
	.db_event = pp_db_event,
};

static int pp_probe(struct ntb_client *client,
		    struct ntb_dev *ntb)
{
	struct pp_ctx *pp;
	int rc;

	if (ntb_db_is_unsafe(ntb)) {
		dev_dbg(&ntb->dev, "doorbell is unsafe\n");
		if (!unsafe) {
			rc = -EINVAL;
			goto err_pp;
		}
	}

	if (ntb_spad_is_unsafe(ntb)) {
		dev_dbg(&ntb->dev, "scratchpad is unsafe\n");
		if (!unsafe) {
			rc = -EINVAL;
			goto err_pp;
		}
	}

	pp = kmalloc(sizeof(*pp), GFP_KERNEL);
	if (!pp) {
		rc = -ENOMEM;
		goto err_pp;
	}

	pp->ntb = ntb;
	pp->db_bits = 0;
	spin_lock_init(&pp->db_lock);
	setup_timer(&pp->db_timer, pp_ping, (unsigned long)pp);
	pp->db_delay = msecs_to_jiffies(delay_ms);

	rc = ntb_set_ctx(ntb, pp, &pp_ops);
	if (rc)
		goto err_ctx;

	ntb_link_enable(ntb, NTB_SPEED_AUTO, NTB_WIDTH_AUTO);
	ntb_link_event(ntb);

	return 0;

err_ctx:
	kfree(pp);
err_pp:
	return rc;
}

static void pp_remove(struct ntb_client *client,
		      struct ntb_dev *ntb)
{
	struct pp_ctx *pp = ntb->ctx;

	ntb_clear_ctx(ntb);
	del_timer_sync(&pp->db_timer);
	ntb_link_disable(ntb);

	kfree(pp);
}

static struct ntb_client pp_client = {
	.ops = {
		.probe = pp_probe,
		.remove = pp_remove,
	},
};
module_ntb_client(pp_client);
