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: Alexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Link: https://lore.kernel.org/r/20201116125612.1660971-1-tomas.winkler@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Alexander Usyskin 2020-11-16 14:56:11 +02:00 committed by Greg Kroah-Hartman
parent 6e559fe128
commit 85261c1ff1
5 changed files with 113 additions and 35 deletions

View File

@ -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;

View File

@ -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 @@ out:
* @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 @@ copy:
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);
@ -205,6 +210,72 @@ out:
return rets;
}
/**
* 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
* * < 0 on error
*/
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, vtag, MEI_CL_IO_TX_BLOCKING);
}
EXPORT_SYMBOL_GPL(mei_cldev_send_vtag);
/**
* 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
* * < 0 on error
*/
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, vtag, 0, 0);
}
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)
*
@ -212,16 +283,31 @@ out:
* @buf: buffer to send
* @length: buffer length
*
* 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)
{
struct mei_cl *cl = cldev->cl;
return __mei_cl_send(cl, buf, length, MEI_CL_IO_TX_BLOCKING);
return mei_cldev_send_vtag(cldev, buf, length, 0);
}
EXPORT_SYMBOL_GPL(mei_cldev_send);
/**
* mei_cldev_recv - client receive (read)
*
* @cldev: me client device
* @buf: buffer to receive
* @length: buffer length
*
* Return: read size in bytes of < 0 on error
*/
ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
{
return mei_cldev_recv_vtag(cldev, buf, length, NULL);
}
EXPORT_SYMBOL_GPL(mei_cldev_recv);
/**
* mei_cldev_recv_nonblock - non block client receive (read)
*
@ -235,29 +321,10 @@ EXPORT_SYMBOL_GPL(mei_cldev_send);
ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
size_t length)
{
struct mei_cl *cl = cldev->cl;
return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK, 0);
return mei_cldev_recv_nonblock_vtag(cldev, buf, length, NULL);
}
EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
/**
* mei_cldev_recv - client receive (read)
*
* @cldev: me client device
* @buf: buffer to receive
* @length: buffer length
*
* Return: read size in bytes of < 0 on error
*/
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);
}
EXPORT_SYMBOL_GPL(mei_cldev_recv);
/**
* mei_cl_bus_rx_work - dispatch rx event for a bus device
*

View File

@ -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);

View File

@ -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);

View File

@ -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,