// SPDX-License-Identifier: GPL-2.0

/*
 * Driver to talk to a remote management controller on IPMB.
 */

#include <linux/acpi.h>
#include <linux/errno.h>
#include <linux/i2c.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/poll.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/semaphore.h>
#include <linux/kthread.h>
#include <linux/wait.h>
#include <linux/ipmi_msgdefs.h>
#include <linux/ipmi_smi.h>

#define DEVICE_NAME "ipmi-ipmb"

static int bmcaddr = 0x20;
module_param(bmcaddr, int, 0644);
MODULE_PARM_DESC(bmcaddr, "Address to use for BMC.");

static unsigned int retry_time_ms = 250;
module_param(retry_time_ms, uint, 0644);
MODULE_PARM_DESC(retry_time_ms, "Timeout time between retries, in milliseconds.");

static unsigned int max_retries = 1;
module_param(max_retries, uint, 0644);
MODULE_PARM_DESC(max_retries, "Max resends of a command before timing out.");

/* Add room for the two slave addresses, two checksums, and rqSeq. */
#define IPMB_MAX_MSG_LEN (IPMI_MAX_MSG_LENGTH + 5)

struct ipmi_ipmb_dev {
	struct ipmi_smi *intf;
	struct i2c_client *client;
	struct i2c_client *slave;

	struct ipmi_smi_handlers handlers;

	bool ready;

	u8 curr_seq;

	u8 bmcaddr;
	u32 retry_time_ms;
	u32 max_retries;

	struct ipmi_smi_msg *next_msg;
	struct ipmi_smi_msg *working_msg;

	/* Transmit thread. */
	struct task_struct *thread;
	struct semaphore wake_thread;
	struct semaphore got_rsp;
	spinlock_t lock;
	bool stopping;

	u8 xmitmsg[IPMB_MAX_MSG_LEN];
	unsigned int xmitlen;

	u8 rcvmsg[IPMB_MAX_MSG_LEN];
	unsigned int rcvlen;
	bool overrun;
};

static bool valid_ipmb(struct ipmi_ipmb_dev *iidev)
{
	u8 *msg = iidev->rcvmsg;
	u8 netfn;

	if (iidev->overrun)
		return false;

	/* Minimum message size. */
	if (iidev->rcvlen < 7)
		return false;

	/* Is it a response? */
	netfn = msg[1] >> 2;
	if (netfn & 1) {
		/* Response messages have an added completion code. */
		if (iidev->rcvlen < 8)
			return false;
	}

	if (ipmb_checksum(msg, 3) != 0)
		return false;
	if (ipmb_checksum(msg + 3, iidev->rcvlen - 3) != 0)
		return false;

	return true;
}

static void ipmi_ipmb_check_msg_done(struct ipmi_ipmb_dev *iidev)
{
	struct ipmi_smi_msg *imsg = NULL;
	u8 *msg = iidev->rcvmsg;
	bool is_cmd;
	unsigned long flags;

	if (iidev->rcvlen == 0)
		return;
	if (!valid_ipmb(iidev))
		goto done;

	is_cmd = ((msg[1] >> 2) & 1) == 0;

	if (is_cmd) {
		/* Ignore commands until we are up. */
		if (!iidev->ready)
			goto done;

		/* It's a command, allocate a message for it. */
		imsg = ipmi_alloc_smi_msg();
		if (!imsg)
			goto done;
		imsg->type = IPMI_SMI_MSG_TYPE_IPMB_DIRECT;
		imsg->data_size = 0;
	} else {
		spin_lock_irqsave(&iidev->lock, flags);
		if (iidev->working_msg) {
			u8 seq = msg[4] >> 2;
			bool xmit_rsp = (iidev->working_msg->data[0] >> 2) & 1;

			/*
			 * Responses should carry the sequence we sent
			 * them with.  If it's a transmitted response,
			 * ignore it.  And if the message hasn't been
			 * transmitted, ignore it.
			 */
			if (!xmit_rsp && seq == iidev->curr_seq) {
				iidev->curr_seq = (iidev->curr_seq + 1) & 0x3f;

				imsg = iidev->working_msg;
				iidev->working_msg = NULL;
			}
		}
		spin_unlock_irqrestore(&iidev->lock, flags);
	}

	if (!imsg)
		goto done;

	if (imsg->type == IPMI_SMI_MSG_TYPE_IPMB_DIRECT) {
		imsg->rsp[0] = msg[1]; /* NetFn/LUN */
		/*
		 * Keep the source address, rqSeq.  Drop the trailing
		 * checksum.
		 */
		memcpy(imsg->rsp + 1, msg + 3, iidev->rcvlen - 4);
		imsg->rsp_size = iidev->rcvlen - 3;
	} else {
		imsg->rsp[0] = msg[1]; /* NetFn/LUN */
		/*
		 * Skip the source address, rqSeq.  Drop the trailing
		 * checksum.
		 */
		memcpy(imsg->rsp + 1, msg + 5, iidev->rcvlen - 6);
		imsg->rsp_size = iidev->rcvlen - 5;
	}
	ipmi_smi_msg_received(iidev->intf, imsg);
	if (!is_cmd)
		up(&iidev->got_rsp);

done:
	iidev->overrun = false;
	iidev->rcvlen = 0;
}

/*
 * The IPMB protocol only supports i2c writes so there is no need to
 * support I2C_SLAVE_READ* events, except to know if the other end has
 * issued a read without going to stop mode.
 */
static int ipmi_ipmb_slave_cb(struct i2c_client *client,
			      enum i2c_slave_event event, u8 *val)
{
	struct ipmi_ipmb_dev *iidev = i2c_get_clientdata(client);

	switch (event) {
	case I2C_SLAVE_WRITE_REQUESTED:
		ipmi_ipmb_check_msg_done(iidev);
		/*
		 * First byte is the slave address, to ease the checksum
		 * calculation.
		 */
		iidev->rcvmsg[0] = client->addr << 1;
		iidev->rcvlen = 1;
		break;

	case I2C_SLAVE_WRITE_RECEIVED:
		if (iidev->rcvlen >= sizeof(iidev->rcvmsg))
			iidev->overrun = true;
		else
			iidev->rcvmsg[iidev->rcvlen++] = *val;
		break;

	case I2C_SLAVE_READ_REQUESTED:
	case I2C_SLAVE_STOP:
		ipmi_ipmb_check_msg_done(iidev);
		break;

	case I2C_SLAVE_READ_PROCESSED:
		break;
	}

	return 0;
}

static void ipmi_ipmb_send_response(struct ipmi_ipmb_dev *iidev,
				    struct ipmi_smi_msg *msg, u8 cc)
{
	if ((msg->data[0] >> 2) & 1) {
		/*
		 * It's a response being sent, we need to return a
		 * response to the response.  Fake a send msg command
		 * response with channel 0.  This will always be ipmb
		 * direct.
		 */
		msg->data[0] = (IPMI_NETFN_APP_REQUEST | 1) << 2;
		msg->data[3] = IPMI_SEND_MSG_CMD;
		msg->data[4] = cc;
		msg->data_size = 5;
	}
	msg->rsp[0] = msg->data[0] | (1 << 2);
	if (msg->type == IPMI_SMI_MSG_TYPE_IPMB_DIRECT) {
		msg->rsp[1] = msg->data[1];
		msg->rsp[2] = msg->data[2];
		msg->rsp[3] = msg->data[3];
		msg->rsp[4] = cc;
		msg->rsp_size = 5;
	} else {
		msg->rsp[1] = msg->data[1];
		msg->rsp[2] = cc;
		msg->rsp_size = 3;
	}
	ipmi_smi_msg_received(iidev->intf, msg);
}

static void ipmi_ipmb_format_for_xmit(struct ipmi_ipmb_dev *iidev,
				      struct ipmi_smi_msg *msg)
{
	if (msg->type == IPMI_SMI_MSG_TYPE_IPMB_DIRECT) {
		iidev->xmitmsg[0] = msg->data[1];
		iidev->xmitmsg[1] = msg->data[0];
		memcpy(iidev->xmitmsg + 4, msg->data + 2, msg->data_size - 2);
		iidev->xmitlen = msg->data_size + 2;
	} else {
		iidev->xmitmsg[0] = iidev->bmcaddr;
		iidev->xmitmsg[1] = msg->data[0];
		iidev->xmitmsg[4] = 0;
		memcpy(iidev->xmitmsg + 5, msg->data + 1, msg->data_size - 1);
		iidev->xmitlen = msg->data_size + 4;
	}
	iidev->xmitmsg[3] = iidev->slave->addr << 1;
	if (((msg->data[0] >> 2) & 1) == 0)
		/* If it's a command, put in our own sequence number. */
		iidev->xmitmsg[4] = ((iidev->xmitmsg[4] & 0x03) |
				     (iidev->curr_seq << 2));

	/* Now add on the final checksums. */
	iidev->xmitmsg[2] = ipmb_checksum(iidev->xmitmsg, 2);
	iidev->xmitmsg[iidev->xmitlen] =
		ipmb_checksum(iidev->xmitmsg + 3, iidev->xmitlen - 3);
	iidev->xmitlen++;
}

static int ipmi_ipmb_thread(void *data)
{
	struct ipmi_ipmb_dev *iidev = data;

	while (!kthread_should_stop()) {
		long ret;
		struct i2c_msg i2c_msg;
		struct ipmi_smi_msg *msg = NULL;
		unsigned long flags;
		unsigned int retries = 0;

		/* Wait for a message to send */
		ret = down_interruptible(&iidev->wake_thread);
		if (iidev->stopping)
			break;
		if (ret)
			continue;

		spin_lock_irqsave(&iidev->lock, flags);
		if (iidev->next_msg) {
			msg = iidev->next_msg;
			iidev->next_msg = NULL;
		}
		spin_unlock_irqrestore(&iidev->lock, flags);
		if (!msg)
			continue;

		ipmi_ipmb_format_for_xmit(iidev, msg);

retry:
		i2c_msg.len = iidev->xmitlen - 1;
		if (i2c_msg.len > 32) {
			ipmi_ipmb_send_response(iidev, msg,
						IPMI_REQ_LEN_EXCEEDED_ERR);
			continue;
		}

		i2c_msg.addr = iidev->xmitmsg[0] >> 1;
		i2c_msg.flags = 0;
		i2c_msg.buf = iidev->xmitmsg + 1;

		/* Rely on i2c_transfer for a barrier. */
		iidev->working_msg = msg;

		ret = i2c_transfer(iidev->client->adapter, &i2c_msg, 1);

		if ((msg->data[0] >> 2) & 1) {
			/*
			 * It's a response, nothing will be returned
			 * by the other end.
			 */

			iidev->working_msg = NULL;
			ipmi_ipmb_send_response(iidev, msg,
						ret < 0 ? IPMI_BUS_ERR : 0);
			continue;
		}
		if (ret < 0) {
			iidev->working_msg = NULL;
			ipmi_ipmb_send_response(iidev, msg, IPMI_BUS_ERR);
			continue;
		}

		/* A command was sent, wait for its response. */
		ret = down_timeout(&iidev->got_rsp,
				   msecs_to_jiffies(iidev->retry_time_ms));

		/*
		 * Grab the message if we can.  If the handler hasn't
		 * already handled it, the message will still be there.
		 */
		spin_lock_irqsave(&iidev->lock, flags);
		msg = iidev->working_msg;
		iidev->working_msg = NULL;
		spin_unlock_irqrestore(&iidev->lock, flags);

		if (!msg && ret) {
			/*
			 * If working_msg is not set and we timed out,
			 * that means the message grabbed by
			 * check_msg_done before we could grab it
			 * here.  Wait again for check_msg_done to up
			 * the semaphore.
			 */
			down(&iidev->got_rsp);
		} else if (msg && ++retries <= iidev->max_retries) {
			spin_lock_irqsave(&iidev->lock, flags);
			iidev->working_msg = msg;
			spin_unlock_irqrestore(&iidev->lock, flags);
			goto retry;
		}

		if (msg)
			ipmi_ipmb_send_response(iidev, msg, IPMI_TIMEOUT_ERR);
	}

	if (iidev->next_msg)
		/* Return an unspecified error. */
		ipmi_ipmb_send_response(iidev, iidev->next_msg, 0xff);

	return 0;
}

static int ipmi_ipmb_start_processing(void *send_info,
				      struct ipmi_smi *new_intf)
{
	struct ipmi_ipmb_dev *iidev = send_info;

	iidev->intf = new_intf;
	iidev->ready = true;
	return 0;
}

static void ipmi_ipmb_stop_thread(struct ipmi_ipmb_dev *iidev)
{
	if (iidev->thread) {
		struct task_struct *t = iidev->thread;

		iidev->thread = NULL;
		iidev->stopping = true;
		up(&iidev->wake_thread);
		up(&iidev->got_rsp);
		kthread_stop(t);
	}
}

static void ipmi_ipmb_shutdown(void *send_info)
{
	struct ipmi_ipmb_dev *iidev = send_info;

	ipmi_ipmb_stop_thread(iidev);
}

static void ipmi_ipmb_sender(void *send_info,
			     struct ipmi_smi_msg *msg)
{
	struct ipmi_ipmb_dev *iidev = send_info;
	unsigned long flags;

	spin_lock_irqsave(&iidev->lock, flags);
	BUG_ON(iidev->next_msg);

	iidev->next_msg = msg;
	spin_unlock_irqrestore(&iidev->lock, flags);

	up(&iidev->wake_thread);
}

static void ipmi_ipmb_request_events(void *send_info)
{
	/* We don't fetch events here. */
}

static void ipmi_ipmb_cleanup(struct ipmi_ipmb_dev *iidev)
{
	if (iidev->slave) {
		i2c_slave_unregister(iidev->slave);
		if (iidev->slave != iidev->client)
			i2c_unregister_device(iidev->slave);
	}
	iidev->slave = NULL;
	iidev->client = NULL;
	ipmi_ipmb_stop_thread(iidev);
}

static void ipmi_ipmb_remove(struct i2c_client *client)
{
	struct ipmi_ipmb_dev *iidev = i2c_get_clientdata(client);

	ipmi_ipmb_cleanup(iidev);
	ipmi_unregister_smi(iidev->intf);
}

static int ipmi_ipmb_probe(struct i2c_client *client)
{
	struct device *dev = &client->dev;
	struct ipmi_ipmb_dev *iidev;
	struct device_node *slave_np;
	struct i2c_adapter *slave_adap = NULL;
	struct i2c_client *slave = NULL;
	int rv;

	iidev = devm_kzalloc(&client->dev, sizeof(*iidev), GFP_KERNEL);
	if (!iidev)
		return -ENOMEM;

	if (of_property_read_u8(dev->of_node, "bmcaddr", &iidev->bmcaddr) != 0)
		iidev->bmcaddr = bmcaddr;
	if (iidev->bmcaddr == 0 || iidev->bmcaddr & 1) {
		/* Can't have the write bit set. */
		dev_notice(&client->dev,
			   "Invalid bmc address value %2.2x\n", iidev->bmcaddr);
		return -EINVAL;
	}

	if (of_property_read_u32(dev->of_node, "retry-time",
				 &iidev->retry_time_ms) != 0)
		iidev->retry_time_ms = retry_time_ms;

	if (of_property_read_u32(dev->of_node, "max-retries",
				 &iidev->max_retries) != 0)
		iidev->max_retries = max_retries;

	slave_np = of_parse_phandle(dev->of_node, "slave-dev", 0);
	if (slave_np) {
		slave_adap = of_get_i2c_adapter_by_node(slave_np);
		of_node_put(slave_np);
		if (!slave_adap) {
			dev_notice(&client->dev,
				   "Could not find slave adapter\n");
			return -EINVAL;
		}
	}

	iidev->client = client;

	if (slave_adap) {
		struct i2c_board_info binfo;

		memset(&binfo, 0, sizeof(binfo));
		strscpy(binfo.type, "ipmb-slave", I2C_NAME_SIZE);
		binfo.addr = client->addr;
		binfo.flags = I2C_CLIENT_SLAVE;
		slave = i2c_new_client_device(slave_adap, &binfo);
		i2c_put_adapter(slave_adap);
		if (IS_ERR(slave)) {
			rv = PTR_ERR(slave);
			dev_notice(&client->dev,
				   "Could not allocate slave device: %d\n", rv);
			return rv;
		}
		i2c_set_clientdata(slave, iidev);
	} else {
		slave = client;
	}
	i2c_set_clientdata(client, iidev);
	slave->flags |= I2C_CLIENT_SLAVE;

	rv = i2c_slave_register(slave, ipmi_ipmb_slave_cb);
	if (rv)
		goto out_err;
	iidev->slave = slave;
	slave = NULL;

	iidev->handlers.flags = IPMI_SMI_CAN_HANDLE_IPMB_DIRECT;
	iidev->handlers.start_processing = ipmi_ipmb_start_processing;
	iidev->handlers.shutdown = ipmi_ipmb_shutdown;
	iidev->handlers.sender = ipmi_ipmb_sender;
	iidev->handlers.request_events = ipmi_ipmb_request_events;

	spin_lock_init(&iidev->lock);
	sema_init(&iidev->wake_thread, 0);
	sema_init(&iidev->got_rsp, 0);

	iidev->thread = kthread_run(ipmi_ipmb_thread, iidev,
				    "kipmb%4.4x", client->addr);
	if (IS_ERR(iidev->thread)) {
		rv = PTR_ERR(iidev->thread);
		dev_notice(&client->dev,
			   "Could not start kernel thread: error %d\n", rv);
		goto out_err;
	}

	rv = ipmi_register_smi(&iidev->handlers,
			       iidev,
			       &client->dev,
			       iidev->bmcaddr);
	if (rv)
		goto out_err;

	return 0;

out_err:
	if (slave && slave != client)
		i2c_unregister_device(slave);
	ipmi_ipmb_cleanup(iidev);
	return rv;
}

#ifdef CONFIG_OF
static const struct of_device_id of_ipmi_ipmb_match[] = {
	{ .type = "ipmi", .compatible = DEVICE_NAME },
	{},
};
MODULE_DEVICE_TABLE(of, of_ipmi_ipmb_match);
#else
#define of_ipmi_ipmb_match NULL
#endif

static const struct i2c_device_id ipmi_ipmb_id[] = {
	{ DEVICE_NAME, 0 },
	{},
};
MODULE_DEVICE_TABLE(i2c, ipmi_ipmb_id);

static struct i2c_driver ipmi_ipmb_driver = {
	.class		= I2C_CLASS_HWMON,
	.driver = {
		.name = DEVICE_NAME,
		.of_match_table = of_ipmi_ipmb_match,
	},
	.probe		= ipmi_ipmb_probe,
	.remove		= ipmi_ipmb_remove,
	.id_table	= ipmi_ipmb_id,
};
module_i2c_driver(ipmi_ipmb_driver);

MODULE_AUTHOR("Corey Minyard");
MODULE_DESCRIPTION("IPMI IPMB driver");
MODULE_LICENSE("GPL v2");
