Commit 85261c1f authored by Alexander Usyskin's avatar Alexander Usyskin Committed by Greg Kroah-Hartman
Browse files

mei: bus: add vtag support



Add API to support vtag in communication on mei bus.

Add mei_cldev_send_vtag, mei_cldev_recv_vtag and
mei_cldev_recv_nonblock_vtag functions to allow sending a message
with vtag set and to receive vtag of an incoming message.

Cc: Sean Z Huang <sean.z.huang@intel.com>
Signed-off-by: default avatarAlexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Link: https://lore.kernel.org/r/20201116125612.1660971-1-tomas.winkler@intel.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6e559fe1
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -148,7 +148,7 @@ static int mei_osver(struct mei_cl_device *cldev)
	os_ver = (struct mei_os_ver *)fwcaps->data;
	os_ver->os_type = OSTYPE_LINUX;

	return __mei_cl_send(cldev->cl, buf, size, mode);
	return __mei_cl_send(cldev->cl, buf, size, 0, mode);
}

#define MKHI_FWVER_BUF_LEN (sizeof(struct mkhi_msg_hdr) + \
@@ -169,7 +169,7 @@ static int mei_fwver(struct mei_cl_device *cldev)
	req.hdr.group_id = MKHI_GEN_GROUP_ID;
	req.hdr.command = MKHI_GEN_GET_FW_VERSION_CMD;

	ret = __mei_cl_send(cldev->cl, (u8 *)&req, sizeof(req),
	ret = __mei_cl_send(cldev->cl, (u8 *)&req, sizeof(req), 0,
			    MEI_CL_IO_TX_BLOCKING);
	if (ret < 0) {
		dev_err(&cldev->dev, "Could not send ReqFWVersion cmd\n");
@@ -177,7 +177,7 @@ static int mei_fwver(struct mei_cl_device *cldev)
	}

	ret = 0;
	bytes_recv = __mei_cl_recv(cldev->cl, buf, sizeof(buf), 0,
	bytes_recv = __mei_cl_recv(cldev->cl, buf, sizeof(buf), NULL, 0,
				   MKHI_RCV_TIMEOUT);
	if (bytes_recv < 0 || (size_t)bytes_recv < MKHI_FWVER_LEN(1)) {
		/*
@@ -324,13 +324,15 @@ static int mei_nfc_if_version(struct mei_cl *cl,
	};
	struct mei_nfc_reply *reply = NULL;
	size_t if_version_length;
	u8 vtag;
	int bytes_recv, ret;

	bus = cl->dev;

	WARN_ON(mutex_is_locked(&bus->device_lock));

	ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(cmd), MEI_CL_IO_TX_BLOCKING);
	ret = __mei_cl_send(cl, (u8 *)&cmd, sizeof(cmd), 0,
			    MEI_CL_IO_TX_BLOCKING);
	if (ret < 0) {
		dev_err(bus->dev, "Could not send IF version cmd\n");
		return ret;
@@ -344,7 +346,8 @@ static int mei_nfc_if_version(struct mei_cl *cl,
		return -ENOMEM;

	ret = 0;
	bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0, 0);
	bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, &vtag,
				   0, 0);
	if (bytes_recv < 0 || (size_t)bytes_recv < if_version_length) {
		dev_err(bus->dev, "Could not read IF version\n");
		ret = -EIO;
+84 −17
Original line number Diff line number Diff line
@@ -26,11 +26,12 @@
 * @cl: host client
 * @buf: buffer to send
 * @length: buffer length
 * @vtag: virtual tag
 * @mode: sending mode
 *
 * Return: written size bytes or < 0 on error
 */
ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, u8 vtag,
		      unsigned int mode)
{
	struct mei_device *bus;
@@ -86,6 +87,7 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
		rets = -ENOMEM;
		goto out;
	}
	cb->vtag = vtag;

	cb->internal = !!(mode & MEI_CL_IO_TX_INTERNAL);
	cb->blocking = !!(mode & MEI_CL_IO_TX_BLOCKING);
@@ -106,11 +108,12 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
 * @buf: buffer to receive
 * @length: buffer length
 * @mode: io mode
 * @vtag: virtual tag
 * @timeout: recv timeout, 0 for infinite timeout
 *
 * Return: read size in bytes of < 0 on error
 */
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length, u8 *vtag,
		      unsigned int mode, unsigned long timeout)
{
	struct mei_device *bus;
@@ -196,6 +199,8 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
	r_length = min_t(size_t, length, cb->buf_idx);
	memcpy(buf, cb->buf.data, r_length);
	rets = r_length;
	if (vtag)
		*vtag = cb->vtag;

free:
	mei_cl_del_rd_completed(cl, cb);
@@ -206,40 +211,87 @@ ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
}

/**
 * mei_cldev_send - me device send  (write)
 * mei_cldev_send_vtag - me device send with vtag  (write)
 *
 * @cldev: me client device
 * @buf: buffer to send
 * @length: buffer length
 * @vtag: virtual tag
 *
 * Return: written size in bytes or < 0 on error
 * Return:
 *  * written size in bytes
 *  * < 0 on error
 */
ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length)

ssize_t mei_cldev_send_vtag(struct mei_cl_device *cldev, u8 *buf, size_t length,
			    u8 vtag)
{
	struct mei_cl *cl = cldev->cl;

	return __mei_cl_send(cl, buf, length, MEI_CL_IO_TX_BLOCKING);
	return __mei_cl_send(cl, buf, length, vtag, MEI_CL_IO_TX_BLOCKING);
}
EXPORT_SYMBOL_GPL(mei_cldev_send);
EXPORT_SYMBOL_GPL(mei_cldev_send_vtag);

/**
 * mei_cldev_recv_nonblock - non block client receive (read)
 * mei_cldev_recv_vtag - client receive with vtag (read)
 *
 * @cldev: me client device
 * @buf: buffer to receive
 * @length: buffer length
 * @vtag: virtual tag
 *
 * Return: read size in bytes of < 0 on error
 *         -EAGAIN if function will block.
 * Return:
 * * read size in bytes
 * *  < 0 on error
 */
ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
				size_t length)

ssize_t mei_cldev_recv_vtag(struct mei_cl_device *cldev, u8 *buf, size_t length,
			    u8 *vtag)
{
	struct mei_cl *cl = cldev->cl;

	return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK, 0);
	return __mei_cl_recv(cl, buf, length, vtag, 0, 0);
}
EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
EXPORT_SYMBOL_GPL(mei_cldev_recv_vtag);

/**
 * mei_cldev_recv_nonblock_vtag - non block client receive with vtag (read)
 *
 * @cldev: me client device
 * @buf: buffer to receive
 * @length: buffer length
 * @vtag: virtual tag
 *
 * Return:
 * * read size in bytes
 * * -EAGAIN if function will block.
 * * < 0 on other error
 */
ssize_t mei_cldev_recv_nonblock_vtag(struct mei_cl_device *cldev, u8 *buf,
				     size_t length, u8 *vtag)
{
	struct mei_cl *cl = cldev->cl;

	return __mei_cl_recv(cl, buf, length, vtag, MEI_CL_IO_RX_NONBLOCK, 0);
}
EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock_vtag);

/**
 * mei_cldev_send - me device send  (write)
 *
 * @cldev: me client device
 * @buf: buffer to send
 * @length: buffer length
 *
 * Return:
 *  * written size in bytes
 *  * < 0 on error
 */
ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
{
	return mei_cldev_send_vtag(cldev, buf, length, 0);
}
EXPORT_SYMBOL_GPL(mei_cldev_send);

/**
 * mei_cldev_recv - client receive (read)
@@ -252,12 +304,27 @@ EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
 */
ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
{
	struct mei_cl *cl = cldev->cl;

	return __mei_cl_recv(cl, buf, length, 0, 0);
	return mei_cldev_recv_vtag(cldev, buf, length, NULL);
}
EXPORT_SYMBOL_GPL(mei_cldev_recv);

/**
 * mei_cldev_recv_nonblock - non block client receive (read)
 *
 * @cldev: me client device
 * @buf: buffer to receive
 * @length: buffer length
 *
 * Return: read size in bytes of < 0 on error
 *         -EAGAIN if function will block.
 */
ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
				size_t length)
{
	return mei_cldev_recv_nonblock_vtag(cldev, buf, length, NULL);
}
EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);

/**
 * mei_cl_bus_rx_work - dispatch rx event for a bus device
 *
+4 −2
Original line number Diff line number Diff line
@@ -1306,7 +1306,7 @@ struct mei_cl_vtag *mei_cl_vtag_alloc(struct file *fp, u8 vtag)
 * mei_cl_fp_by_vtag - obtain the file pointer by vtag
 *
 * @cl: host client
 * @vtag: vm tag
 * @vtag: virtual tag
 *
 * Return:
 * * A file pointer - on success
@@ -1317,7 +1317,9 @@ const struct file *mei_cl_fp_by_vtag(const struct mei_cl *cl, u8 vtag)
	struct mei_cl_vtag *vtag_l;

	list_for_each_entry(vtag_l, &cl->vtag_map, list)
		if (vtag_l->vtag == vtag)
		/* The client on bus has one fixed fp */
		if ((cl->cldev && mei_cldev_enabled(cl->cldev)) ||
		    vtag_l->vtag == vtag)
			return vtag_l->fp;

	return ERR_PTR(-ENOENT);
+2 −2
Original line number Diff line number Diff line
@@ -340,9 +340,9 @@ struct mei_hw_ops {
/* MEI bus API*/
void mei_cl_bus_rescan_work(struct work_struct *work);
void mei_cl_bus_dev_fixup(struct mei_cl_device *dev);
ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, u8 vtag,
		      unsigned int mode);
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length, u8 *vtag,
		      unsigned int mode, unsigned long timeout);
bool mei_cl_bus_rx_event(struct mei_cl *cl);
bool mei_cl_bus_notify_event(struct mei_cl *cl);
+6 −0
Original line number Diff line number Diff line
@@ -95,6 +95,12 @@ ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length);
ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length);
ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
				size_t length);
ssize_t mei_cldev_send_vtag(struct mei_cl_device *cldev, u8 *buf, size_t length,
			    u8 vtag);
ssize_t mei_cldev_recv_vtag(struct mei_cl_device *cldev, u8 *buf, size_t length,
			    u8 *vtag);
ssize_t mei_cldev_recv_nonblock_vtag(struct mei_cl_device *cldev, u8 *buf,
				     size_t length, u8 *vtag);

int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb);
int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,