// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * RDMA Transport Layer
 *
 * Copyright (c) 2014 - 2018 ProfitBricks GmbH. All rights reserved.
 * Copyright (c) 2018 - 2019 1&1 IONOS Cloud GmbH. All rights reserved.
 * Copyright (c) 2019 - 2020 1&1 IONOS SE. All rights reserved.
 */
#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME " L" __stringify(__LINE__) ": " fmt

#include <linux/module.h>
#include <linux/inet.h>

#include "rtrs-pri.h"
#include "rtrs-log.h"

MODULE_DESCRIPTION("RDMA Transport Core");
MODULE_LICENSE("GPL");

struct rtrs_iu *rtrs_iu_alloc(u32 iu_num, size_t size, gfp_t gfp_mask,
			      struct ib_device *dma_dev,
			      enum dma_data_direction dir,
			      void (*done)(struct ib_cq *cq, struct ib_wc *wc))
{
	struct rtrs_iu *ius, *iu;
	int i;

	ius = kcalloc(iu_num, sizeof(*ius), gfp_mask);
	if (!ius)
		return NULL;
	for (i = 0; i < iu_num; i++) {
		iu = &ius[i];
		iu->direction = dir;
		iu->buf = kzalloc(size, gfp_mask);
		if (!iu->buf)
			goto err;

		iu->dma_addr = ib_dma_map_single(dma_dev, iu->buf, size, dir);
		if (ib_dma_mapping_error(dma_dev, iu->dma_addr)) {
			kfree(iu->buf);
			goto err;
		}

		iu->cqe.done  = done;
		iu->size      = size;
	}
	return ius;
err:
	rtrs_iu_free(ius, dma_dev, i);
	return NULL;
}
EXPORT_SYMBOL_GPL(rtrs_iu_alloc);

void rtrs_iu_free(struct rtrs_iu *ius, struct ib_device *ibdev, u32 queue_num)
{
	struct rtrs_iu *iu;
	int i;

	if (!ius)
		return;

	for (i = 0; i < queue_num; i++) {
		iu = &ius[i];
		ib_dma_unmap_single(ibdev, iu->dma_addr, iu->size, iu->direction);
		kfree(iu->buf);
	}
	kfree(ius);
}
EXPORT_SYMBOL_GPL(rtrs_iu_free);

int rtrs_iu_post_recv(struct rtrs_con *con, struct rtrs_iu *iu)
{
	struct rtrs_path *path = con->path;
	struct ib_recv_wr wr;
	struct ib_sge list;

	list.addr   = iu->dma_addr;
	list.length = iu->size;
	list.lkey   = path->dev->ib_pd->local_dma_lkey;

	if (list.length == 0) {
		rtrs_wrn(con->path,
			  "Posting receive work request failed, sg list is empty\n");
		return -EINVAL;
	}
	wr = (struct ib_recv_wr) {
		.wr_cqe  = &iu->cqe,
		.sg_list = &list,
		.num_sge = 1,
	};

	return ib_post_recv(con->qp, &wr, NULL);
}
EXPORT_SYMBOL_GPL(rtrs_iu_post_recv);

int rtrs_post_recv_empty(struct rtrs_con *con, struct ib_cqe *cqe)
{
	struct ib_recv_wr wr;

	wr = (struct ib_recv_wr) {
		.wr_cqe  = cqe,
	};

	return ib_post_recv(con->qp, &wr, NULL);
}
EXPORT_SYMBOL_GPL(rtrs_post_recv_empty);

static int rtrs_post_send(struct ib_qp *qp, struct ib_send_wr *head,
			  struct ib_send_wr *wr, struct ib_send_wr *tail)
{
	if (head) {
		struct ib_send_wr *next = head;

		while (next->next)
			next = next->next;
		next->next = wr;
	} else {
		head = wr;
	}

	if (tail)
		wr->next = tail;

	return ib_post_send(qp, head, NULL);
}

int rtrs_iu_post_send(struct rtrs_con *con, struct rtrs_iu *iu, size_t size,
		       struct ib_send_wr *head)
{
	struct rtrs_path *path = con->path;
	struct ib_send_wr wr;
	struct ib_sge list;

	if (WARN_ON(size == 0))
		return -EINVAL;

	list.addr   = iu->dma_addr;
	list.length = size;
	list.lkey   = path->dev->ib_pd->local_dma_lkey;

	wr = (struct ib_send_wr) {
		.wr_cqe     = &iu->cqe,
		.sg_list    = &list,
		.num_sge    = 1,
		.opcode     = IB_WR_SEND,
		.send_flags = IB_SEND_SIGNALED,
	};

	return rtrs_post_send(con->qp, head, &wr, NULL);
}
EXPORT_SYMBOL_GPL(rtrs_iu_post_send);

int rtrs_iu_post_rdma_write_imm(struct rtrs_con *con, struct rtrs_iu *iu,
				struct ib_sge *sge, unsigned int num_sge,
				u32 rkey, u64 rdma_addr, u32 imm_data,
				enum ib_send_flags flags,
				struct ib_send_wr *head,
				struct ib_send_wr *tail)
{
	struct ib_rdma_wr wr;
	int i;

	wr = (struct ib_rdma_wr) {
		.wr.wr_cqe	  = &iu->cqe,
		.wr.sg_list	  = sge,
		.wr.num_sge	  = num_sge,
		.rkey		  = rkey,
		.remote_addr	  = rdma_addr,
		.wr.opcode	  = IB_WR_RDMA_WRITE_WITH_IMM,
		.wr.ex.imm_data = cpu_to_be32(imm_data),
		.wr.send_flags  = flags,
	};

	/*
	 * If one of the sges has 0 size, the operation will fail with a
	 * length error
	 */
	for (i = 0; i < num_sge; i++)
		if (WARN_ONCE(sge[i].length == 0, "sg %d is zero length\n", i))
			return -EINVAL;

	return rtrs_post_send(con->qp, head, &wr.wr, tail);
}
EXPORT_SYMBOL_GPL(rtrs_iu_post_rdma_write_imm);

static int rtrs_post_rdma_write_imm_empty(struct rtrs_con *con,
					  struct ib_cqe *cqe,
					  u32 imm_data,
					  struct ib_send_wr *head)
{
	struct ib_rdma_wr wr;
	struct rtrs_path *path = con->path;
	enum ib_send_flags sflags;

	atomic_dec_if_positive(&con->sq_wr_avail);
	sflags = (atomic_inc_return(&con->wr_cnt) % path->signal_interval) ?
		0 : IB_SEND_SIGNALED;

	wr = (struct ib_rdma_wr) {
		.wr.wr_cqe	= cqe,
		.wr.send_flags	= sflags,
		.wr.opcode	= IB_WR_RDMA_WRITE_WITH_IMM,
		.wr.ex.imm_data	= cpu_to_be32(imm_data),
	};

	return rtrs_post_send(con->qp, head, &wr.wr, NULL);
}

static void qp_event_handler(struct ib_event *ev, void *ctx)
{
	struct rtrs_con *con = ctx;

	switch (ev->event) {
	case IB_EVENT_COMM_EST:
		rtrs_info(con->path, "QP event %s (%d) received\n",
			   ib_event_msg(ev->event), ev->event);
		rdma_notify(con->cm_id, IB_EVENT_COMM_EST);
		break;
	default:
		rtrs_info(con->path, "Unhandled QP event %s (%d) received\n",
			   ib_event_msg(ev->event), ev->event);
		break;
	}
}

static bool is_pollqueue(struct rtrs_con *con)
{
	return con->cid >= con->path->irq_con_num;
}

static int create_cq(struct rtrs_con *con, int cq_vector, int nr_cqe,
		     enum ib_poll_context poll_ctx)
{
	struct rdma_cm_id *cm_id = con->cm_id;
	struct ib_cq *cq;

	if (is_pollqueue(con))
		cq = ib_alloc_cq(cm_id->device, con, nr_cqe, cq_vector,
				 poll_ctx);
	else
		cq = ib_cq_pool_get(cm_id->device, nr_cqe, cq_vector, poll_ctx);

	if (IS_ERR(cq)) {
		rtrs_err(con->path, "Creating completion queue failed, errno: %pe\n",
			  cq);
		return PTR_ERR(cq);
	}
	con->cq = cq;
	con->nr_cqe = nr_cqe;

	return 0;
}

static int create_qp(struct rtrs_con *con, struct ib_pd *pd,
		     u32 max_send_wr, u32 max_recv_wr, u32 max_sge)
{
	struct ib_qp_init_attr init_attr = {};
	struct rdma_cm_id *cm_id = con->cm_id;
	int ret;

	init_attr.cap.max_send_wr = max_send_wr;
	init_attr.cap.max_recv_wr = max_recv_wr;
	init_attr.cap.max_recv_sge = 1;
	init_attr.event_handler = qp_event_handler;
	init_attr.qp_context = con;
	init_attr.cap.max_send_sge = max_sge;

	init_attr.qp_type = IB_QPT_RC;
	init_attr.send_cq = con->cq;
	init_attr.recv_cq = con->cq;
	init_attr.sq_sig_type = IB_SIGNAL_REQ_WR;

	ret = rdma_create_qp(cm_id, pd, &init_attr);
	if (ret) {
		rtrs_err(con->path, "Creating QP failed, err: %d\n", ret);
		return ret;
	}
	con->qp = cm_id->qp;

	return ret;
}

static void destroy_cq(struct rtrs_con *con)
{
	if (con->cq) {
		if (is_pollqueue(con))
			ib_free_cq(con->cq);
		else
			ib_cq_pool_put(con->cq, con->nr_cqe);
	}
	con->cq = NULL;
}

int rtrs_cq_qp_create(struct rtrs_path *path, struct rtrs_con *con,
		       u32 max_send_sge, int cq_vector, int nr_cqe,
		       u32 max_send_wr, u32 max_recv_wr,
		       enum ib_poll_context poll_ctx)
{
	int err;

	err = create_cq(con, cq_vector, nr_cqe, poll_ctx);
	if (err)
		return err;

	err = create_qp(con, path->dev->ib_pd, max_send_wr, max_recv_wr,
			max_send_sge);
	if (err) {
		destroy_cq(con);
		return err;
	}
	con->path = path;

	return 0;
}
EXPORT_SYMBOL_GPL(rtrs_cq_qp_create);

void rtrs_cq_qp_destroy(struct rtrs_con *con)
{
	if (con->qp) {
		rdma_destroy_qp(con->cm_id);
		con->qp = NULL;
	}
	destroy_cq(con);
}
EXPORT_SYMBOL_GPL(rtrs_cq_qp_destroy);

static void schedule_hb(struct rtrs_path *path)
{
	queue_delayed_work(path->hb_wq, &path->hb_dwork,
			   msecs_to_jiffies(path->hb_interval_ms));
}

void rtrs_send_hb_ack(struct rtrs_path *path)
{
	struct rtrs_con *usr_con = path->con[0];
	u32 imm;
	int err;

	imm = rtrs_to_imm(RTRS_HB_ACK_IMM, 0);
	err = rtrs_post_rdma_write_imm_empty(usr_con, path->hb_cqe, imm,
					     NULL);
	if (err) {
		rtrs_err(path, "send HB ACK failed, errno: %d\n", err);
		path->hb_err_handler(usr_con);
		return;
	}
}
EXPORT_SYMBOL_GPL(rtrs_send_hb_ack);

static void hb_work(struct work_struct *work)
{
	struct rtrs_con *usr_con;
	struct rtrs_path *path;
	u32 imm;
	int err;

	path = container_of(to_delayed_work(work), typeof(*path), hb_dwork);
	usr_con = path->con[0];

	if (path->hb_missed_cnt > path->hb_missed_max) {
		rtrs_err(path, "HB missed max reached.\n");
		path->hb_err_handler(usr_con);
		return;
	}
	if (path->hb_missed_cnt++) {
		/* Reschedule work without sending hb */
		schedule_hb(path);
		return;
	}

	path->hb_last_sent = ktime_get();

	imm = rtrs_to_imm(RTRS_HB_MSG_IMM, 0);
	err = rtrs_post_rdma_write_imm_empty(usr_con, path->hb_cqe, imm,
					     NULL);
	if (err) {
		rtrs_err(path, "HB send failed, errno: %d\n", err);
		path->hb_err_handler(usr_con);
		return;
	}

	schedule_hb(path);
}

void rtrs_init_hb(struct rtrs_path *path, struct ib_cqe *cqe,
		  unsigned int interval_ms, unsigned int missed_max,
		  void (*err_handler)(struct rtrs_con *con),
		  struct workqueue_struct *wq)
{
	path->hb_cqe = cqe;
	path->hb_interval_ms = interval_ms;
	path->hb_err_handler = err_handler;
	path->hb_wq = wq;
	path->hb_missed_max = missed_max;
	path->hb_missed_cnt = 0;
	INIT_DELAYED_WORK(&path->hb_dwork, hb_work);
}
EXPORT_SYMBOL_GPL(rtrs_init_hb);

void rtrs_start_hb(struct rtrs_path *path)
{
	schedule_hb(path);
}
EXPORT_SYMBOL_GPL(rtrs_start_hb);

void rtrs_stop_hb(struct rtrs_path *path)
{
	cancel_delayed_work_sync(&path->hb_dwork);
	path->hb_missed_cnt = 0;
}
EXPORT_SYMBOL_GPL(rtrs_stop_hb);

static int rtrs_str_gid_to_sockaddr(const char *addr, size_t len,
				     short port, struct sockaddr_storage *dst)
{
	struct sockaddr_ib *dst_ib = (struct sockaddr_ib *)dst;
	int ret;

	/*
	 * We can use some of the IPv6 functions since GID is a valid
	 * IPv6 address format
	 */
	ret = in6_pton(addr, len, dst_ib->sib_addr.sib_raw, '\0', NULL);
	if (ret == 0)
		return -EINVAL;

	dst_ib->sib_family = AF_IB;
	/*
	 * Use the same TCP server port number as the IB service ID
	 * on the IB port space range
	 */
	dst_ib->sib_sid = cpu_to_be64(RDMA_IB_IP_PS_IB | port);
	dst_ib->sib_sid_mask = cpu_to_be64(0xffffffffffffffffULL);
	dst_ib->sib_pkey = cpu_to_be16(0xffff);

	return 0;
}

/**
 * rtrs_str_to_sockaddr() - Convert rtrs address string to sockaddr
 * @addr:	String representation of an addr (IPv4, IPv6 or IB GID):
 *              - "ip:192.168.1.1"
 *              - "ip:fe80::200:5aee:feaa:20a2"
 *              - "gid:fe80::200:5aee:feaa:20a2"
 * @len:        String address length
 * @port:	Destination port
 * @dst:	Destination sockaddr structure
 *
 * Returns 0 if conversion successful. Non-zero on error.
 */
static int rtrs_str_to_sockaddr(const char *addr, size_t len,
				u16 port, struct sockaddr_storage *dst)
{
	if (strncmp(addr, "gid:", 4) == 0) {
		return rtrs_str_gid_to_sockaddr(addr + 4, len - 4, port, dst);
	} else if (strncmp(addr, "ip:", 3) == 0) {
		char port_str[8];
		char *cpy;
		int err;

		snprintf(port_str, sizeof(port_str), "%u", port);
		cpy = kstrndup(addr + 3, len - 3, GFP_KERNEL);
		err = cpy ? inet_pton_with_scope(&init_net, AF_UNSPEC,
						 cpy, port_str, dst) : -ENOMEM;
		kfree(cpy);

		return err;
	}
	return -EPROTONOSUPPORT;
}

/**
 * sockaddr_to_str() - convert sockaddr to a string.
 * @addr:	the sockadddr structure to be converted.
 * @buf:	string containing socket addr.
 * @len:	string length.
 *
 * The return value is the number of characters written into buf not
 * including the trailing '\0'. If len is == 0 the function returns 0..
 */
int sockaddr_to_str(const struct sockaddr *addr, char *buf, size_t len)
{
	switch (addr->sa_family) {
	case AF_IB:
		return scnprintf(buf, len, "gid:%pI6",
			&((struct sockaddr_ib *)addr)->sib_addr.sib_raw);
	case AF_INET:
		return scnprintf(buf, len, "ip:%pI4",
			&((struct sockaddr_in *)addr)->sin_addr);
	case AF_INET6:
		return scnprintf(buf, len, "ip:%pI6c",
			  &((struct sockaddr_in6 *)addr)->sin6_addr);
	}
	return scnprintf(buf, len, "<invalid address family>");
}
EXPORT_SYMBOL(sockaddr_to_str);

/**
 * rtrs_addr_to_str() - convert rtrs_addr to a string "src@dst"
 * @addr:	the rtrs_addr structure to be converted
 * @buf:	string containing source and destination addr of a path
 *		separated by '@' I.e. "ip:1.1.1.1@ip:1.1.1.2"
 *		"ip:1.1.1.1@ip:1.1.1.2".
 * @len:	string length
 *
 * The return value is the number of characters written into buf not
 * including the trailing '\0'.
 */
int rtrs_addr_to_str(const struct rtrs_addr *addr, char *buf, size_t len)
{
	int cnt;

	cnt = sockaddr_to_str((struct sockaddr *)addr->src,
			      buf, len);
	cnt += scnprintf(buf + cnt, len - cnt, "@");
	sockaddr_to_str((struct sockaddr *)addr->dst,
			buf + cnt, len - cnt);
	return cnt;
}
EXPORT_SYMBOL(rtrs_addr_to_str);

/**
 * rtrs_addr_to_sockaddr() - convert path string "src,dst" or "src@dst"
 * to sockaddreses
 * @str:	string containing source and destination addr of a path
 *		separated by ',' or '@' I.e. "ip:1.1.1.1,ip:1.1.1.2" or
 *		"ip:1.1.1.1@ip:1.1.1.2". If str contains only one address it's
 *		considered to be destination.
 * @len:	string length
 * @port:	Destination port number.
 * @addr:	will be set to the source/destination address or to NULL
 *		if str doesn't contain any source address.
 *
 * Returns zero if conversion successful. Non-zero otherwise.
 */
int rtrs_addr_to_sockaddr(const char *str, size_t len, u16 port,
			  struct rtrs_addr *addr)
{
	const char *d;

	d = strchr(str, ',');
	if (!d)
		d = strchr(str, '@');
	if (d) {
		if (rtrs_str_to_sockaddr(str, d - str, 0, addr->src))
			return -EINVAL;
		d += 1;
		len -= d - str;
		str  = d;

	} else {
		addr->src = NULL;
	}
	return rtrs_str_to_sockaddr(str, len, port, addr->dst);
}
EXPORT_SYMBOL(rtrs_addr_to_sockaddr);

void rtrs_rdma_dev_pd_init(enum ib_pd_flags pd_flags,
			    struct rtrs_rdma_dev_pd *pool)
{
	INIT_LIST_HEAD(&pool->list);
	mutex_init(&pool->mutex);
	pool->pd_flags = pd_flags;
}
EXPORT_SYMBOL(rtrs_rdma_dev_pd_init);

void rtrs_rdma_dev_pd_deinit(struct rtrs_rdma_dev_pd *pool)
{
	mutex_destroy(&pool->mutex);
	WARN_ON(!list_empty(&pool->list));
}
EXPORT_SYMBOL(rtrs_rdma_dev_pd_deinit);

static void dev_free(struct kref *ref)
{
	struct rtrs_rdma_dev_pd *pool;
	struct rtrs_ib_dev *dev;

	dev = container_of(ref, typeof(*dev), ref);
	pool = dev->pool;

	mutex_lock(&pool->mutex);
	list_del(&dev->entry);
	mutex_unlock(&pool->mutex);

	ib_dealloc_pd(dev->ib_pd);
	kfree(dev);
}

int rtrs_ib_dev_put(struct rtrs_ib_dev *dev)
{
	return kref_put(&dev->ref, dev_free);
}
EXPORT_SYMBOL(rtrs_ib_dev_put);

static int rtrs_ib_dev_get(struct rtrs_ib_dev *dev)
{
	return kref_get_unless_zero(&dev->ref);
}

struct rtrs_ib_dev *
rtrs_ib_dev_find_or_add(struct ib_device *ib_dev,
			 struct rtrs_rdma_dev_pd *pool)
{
	struct rtrs_ib_dev *dev;

	mutex_lock(&pool->mutex);
	list_for_each_entry(dev, &pool->list, entry) {
		if (dev->ib_dev->node_guid == ib_dev->node_guid &&
		    rtrs_ib_dev_get(dev))
			goto out_unlock;
	}
	mutex_unlock(&pool->mutex);
	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev)
		goto out_err;

	kref_init(&dev->ref);
	dev->pool = pool;
	dev->ib_dev = ib_dev;
	dev->ib_pd = ib_alloc_pd(ib_dev, pool->pd_flags);
	if (IS_ERR(dev->ib_pd))
		goto out_free_dev;

	if (pool->ops && pool->ops->init && pool->ops->init(dev))
		goto out_free_pd;

	mutex_lock(&pool->mutex);
	list_add(&dev->entry, &pool->list);
out_unlock:
	mutex_unlock(&pool->mutex);
	return dev;

out_free_pd:
	ib_dealloc_pd(dev->ib_pd);
out_free_dev:
	kfree(dev);
out_err:
	return NULL;
}
EXPORT_SYMBOL(rtrs_ib_dev_find_or_add);
