// SPDX-License-Identifier: GPL-2.0
/*
 * bsg endpoint that supports UPIUs
 *
 * Copyright (C) 2018 Western Digital Corporation
 */

#include <linux/bsg-lib.h>
#include <linux/dma-mapping.h>
#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include "ufs_bsg.h"
#include <ufs/ufshcd.h>
#include "ufshcd-priv.h"

static int ufs_bsg_get_query_desc_size(struct ufs_hba *hba, int *desc_len,
				       struct utp_upiu_query *qr)
{
	int desc_size = be16_to_cpu(qr->length);

	if (desc_size <= 0)
		return -EINVAL;

	*desc_len = min_t(int, QUERY_DESC_MAX_SIZE, desc_size);

	return 0;
}

static int ufs_bsg_alloc_desc_buffer(struct ufs_hba *hba, struct bsg_job *job,
				     uint8_t **desc_buff, int *desc_len,
				     enum query_opcode desc_op)
{
	struct ufs_bsg_request *bsg_request = job->request;
	struct utp_upiu_query *qr;
	u8 *descp;

	if (desc_op != UPIU_QUERY_OPCODE_WRITE_DESC &&
	    desc_op != UPIU_QUERY_OPCODE_READ_DESC)
		goto out;

	qr = &bsg_request->upiu_req.qr;
	if (ufs_bsg_get_query_desc_size(hba, desc_len, qr)) {
		dev_err(hba->dev, "Illegal desc size\n");
		return -EINVAL;
	}

	if (*desc_len > job->request_payload.payload_len) {
		dev_err(hba->dev, "Illegal desc size\n");
		return -EINVAL;
	}

	descp = kzalloc(*desc_len, GFP_KERNEL);
	if (!descp)
		return -ENOMEM;

	if (desc_op == UPIU_QUERY_OPCODE_WRITE_DESC)
		sg_copy_to_buffer(job->request_payload.sg_list,
				  job->request_payload.sg_cnt, descp,
				  *desc_len);

	*desc_buff = descp;

out:
	return 0;
}

static int ufs_bsg_exec_advanced_rpmb_req(struct ufs_hba *hba, struct bsg_job *job)
{
	struct ufs_rpmb_request *rpmb_request = job->request;
	struct ufs_rpmb_reply *rpmb_reply = job->reply;
	struct bsg_buffer *payload = NULL;
	enum dma_data_direction dir;
	struct scatterlist *sg_list;
	int rpmb_req_type;
	int sg_cnt;
	int ret;
	int data_len;

	if (hba->ufs_version < ufshci_version(4, 0) || !hba->dev_info.b_advanced_rpmb_en ||
	    !(hba->capabilities & MASK_EHSLUTRD_SUPPORTED))
		return -EINVAL;

	if (rpmb_request->ehs_req.length != 2 || rpmb_request->ehs_req.ehs_type != 1)
		return -EINVAL;

	rpmb_req_type = be16_to_cpu(rpmb_request->ehs_req.meta.req_resp_type);

	switch (rpmb_req_type) {
	case UFS_RPMB_WRITE_KEY:
	case UFS_RPMB_READ_CNT:
	case UFS_RPMB_PURGE_ENABLE:
		dir = DMA_NONE;
		break;
	case UFS_RPMB_WRITE:
	case UFS_RPMB_SEC_CONF_WRITE:
		dir = DMA_TO_DEVICE;
		break;
	case UFS_RPMB_READ:
	case UFS_RPMB_SEC_CONF_READ:
	case UFS_RPMB_PURGE_STATUS_READ:
		dir = DMA_FROM_DEVICE;
		break;
	default:
		return -EINVAL;
	}

	if (dir != DMA_NONE) {
		payload = &job->request_payload;
		if (!payload || !payload->payload_len || !payload->sg_cnt)
			return -EINVAL;

		sg_cnt = dma_map_sg(hba->host->dma_dev, payload->sg_list, payload->sg_cnt, dir);
		if (unlikely(!sg_cnt))
			return -ENOMEM;
		sg_list = payload->sg_list;
		data_len = payload->payload_len;
	}

	ret = ufshcd_advanced_rpmb_req_handler(hba, &rpmb_request->bsg_request.upiu_req,
				   &rpmb_reply->bsg_reply.upiu_rsp, &rpmb_request->ehs_req,
				   &rpmb_reply->ehs_rsp, sg_cnt, sg_list, dir);

	if (dir != DMA_NONE) {
		dma_unmap_sg(hba->host->dma_dev, payload->sg_list, payload->sg_cnt, dir);

		if (!ret)
			rpmb_reply->bsg_reply.reply_payload_rcv_len = data_len;
	}

	return ret;
}

static int ufs_bsg_request(struct bsg_job *job)
{
	struct ufs_bsg_request *bsg_request = job->request;
	struct ufs_bsg_reply *bsg_reply = job->reply;
	struct ufs_hba *hba = shost_priv(dev_to_shost(job->dev->parent));
	struct uic_command uc = {};
	int msgcode;
	uint8_t *buff = NULL;
	int desc_len = 0;
	enum query_opcode desc_op = UPIU_QUERY_OPCODE_NOP;
	int ret;
	bool rpmb = false;

	bsg_reply->reply_payload_rcv_len = 0;

	ufshcd_rpm_get_sync(hba);

	msgcode = bsg_request->msgcode;
	switch (msgcode) {
	case UPIU_TRANSACTION_QUERY_REQ:
		desc_op = bsg_request->upiu_req.qr.opcode;
		ret = ufs_bsg_alloc_desc_buffer(hba, job, &buff, &desc_len, desc_op);
		if (ret)
			goto out;
		fallthrough;
	case UPIU_TRANSACTION_NOP_OUT:
	case UPIU_TRANSACTION_TASK_REQ:
		ret = ufshcd_exec_raw_upiu_cmd(hba, &bsg_request->upiu_req,
					       &bsg_reply->upiu_rsp, msgcode,
					       buff, &desc_len, desc_op);
		if (ret)
			dev_err(hba->dev, "exe raw upiu: error code %d\n", ret);
		else if (desc_op == UPIU_QUERY_OPCODE_READ_DESC && desc_len) {
			bsg_reply->reply_payload_rcv_len =
				sg_copy_from_buffer(job->request_payload.sg_list,
						    job->request_payload.sg_cnt,
						    buff, desc_len);
		}
		break;
	case UPIU_TRANSACTION_UIC_CMD:
		memcpy(&uc, &bsg_request->upiu_req.uc, UIC_CMD_SIZE);
		ret = ufshcd_send_uic_cmd(hba, &uc);
		if (ret)
			dev_err(hba->dev, "send uic cmd: error code %d\n", ret);

		memcpy(&bsg_reply->upiu_rsp.uc, &uc, UIC_CMD_SIZE);

		break;
	case UPIU_TRANSACTION_ARPMB_CMD:
		rpmb = true;
		ret = ufs_bsg_exec_advanced_rpmb_req(hba, job);
		if (ret)
			dev_err(hba->dev, "ARPMB OP failed: error code  %d\n", ret);
		break;
	default:
		ret = -ENOTSUPP;
		dev_err(hba->dev, "unsupported msgcode 0x%x\n", msgcode);

		break;
	}

out:
	ufshcd_rpm_put_sync(hba);
	kfree(buff);
	bsg_reply->result = ret;
	job->reply_len = !rpmb ? sizeof(struct ufs_bsg_reply) : sizeof(struct ufs_rpmb_reply);
	/* complete the job here only if no error */
	if (ret == 0)
		bsg_job_done(job, ret, bsg_reply->reply_payload_rcv_len);

	return ret;
}

/**
 * ufs_bsg_remove - detach and remove the added ufs-bsg node
 * @hba: per adapter object
 *
 * Should be called when unloading the driver.
 */
void ufs_bsg_remove(struct ufs_hba *hba)
{
	struct device *bsg_dev = &hba->bsg_dev;

	if (!hba->bsg_queue)
		return;

	bsg_remove_queue(hba->bsg_queue);

	device_del(bsg_dev);
	put_device(bsg_dev);
}

static inline void ufs_bsg_node_release(struct device *dev)
{
	put_device(dev->parent);
}

/**
 * ufs_bsg_probe - Add ufs bsg device node
 * @hba: per adapter object
 *
 * Called during initial loading of the driver, and before scsi_scan_host.
 */
int ufs_bsg_probe(struct ufs_hba *hba)
{
	struct device *bsg_dev = &hba->bsg_dev;
	struct Scsi_Host *shost = hba->host;
	struct device *parent = &shost->shost_gendev;
	struct request_queue *q;
	int ret;

	device_initialize(bsg_dev);

	bsg_dev->parent = get_device(parent);
	bsg_dev->release = ufs_bsg_node_release;

	dev_set_name(bsg_dev, "ufs-bsg%u", shost->host_no);

	ret = device_add(bsg_dev);
	if (ret)
		goto out;

	q = bsg_setup_queue(bsg_dev, dev_name(bsg_dev), ufs_bsg_request, NULL, 0);
	if (IS_ERR(q)) {
		ret = PTR_ERR(q);
		goto out;
	}

	hba->bsg_queue = q;

	return 0;

out:
	dev_err(bsg_dev, "fail to initialize a bsg dev %d\n", shost->host_no);
	put_device(bsg_dev);
	return ret;
}
