Update Linux to v5.4.2
Change-Id: Idf6911045d9d382da2cfe01b1edff026404ac8fd
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index ebdcf0b..1e3edbb 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -1,17 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
/*
- *
+ * Copyright (c) 2003-2019, Intel Corporation. All rights reserved.
* Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2003-2012, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
*/
#include <linux/sched/signal.h>
@@ -318,23 +308,6 @@
}
/**
- * mei_cl_cmp_id - tells if the clients are the same
- *
- * @cl1: host client 1
- * @cl2: host client 2
- *
- * Return: true - if the clients has same host and me ids
- * false - otherwise
- */
-static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
- const struct mei_cl *cl2)
-{
- return cl1 && cl2 &&
- (cl1->host_client_id == cl2->host_client_id) &&
- (mei_cl_me_id(cl1) == mei_cl_me_id(cl2));
-}
-
-/**
* mei_io_cb_free - free mei_cb_private related memory
*
* @cb: mei callback struct
@@ -418,8 +391,11 @@
struct mei_cl_cb *cb, *next;
list_for_each_entry_safe(cb, next, head, list) {
- if (mei_cl_cmp_id(cl, cb->cl))
+ if (cl == cb->cl) {
list_del_init(&cb->list);
+ if (cb->fop_type == MEI_FOP_READ)
+ mei_io_cb_free(cb);
+ }
}
}
@@ -435,7 +411,7 @@
struct mei_cl_cb *cb, *next;
list_for_each_entry_safe(cb, next, head, list) {
- if (mei_cl_cmp_id(cl, cb->cl))
+ if (cl == cb->cl)
mei_tx_cb_dequeue(cb);
}
}
@@ -478,7 +454,7 @@
if (length == 0)
return cb;
- cb->buf.data = kmalloc(length, GFP_KERNEL);
+ cb->buf.data = kmalloc(roundup(length, MEI_SLOT_SIZE), GFP_KERNEL);
if (!cb->buf.data) {
mei_io_cb_free(cb);
return NULL;
@@ -693,7 +669,7 @@
void mei_host_client_init(struct mei_device *dev)
{
- dev->dev_state = MEI_DEV_ENABLED;
+ mei_set_devstate(dev, MEI_DEV_ENABLED);
dev->reset_count = 0;
schedule_work(&dev->bus_rescan_work);
@@ -1374,7 +1350,9 @@
mutex_unlock(&dev->device_lock);
wait_event_timeout(cl->wait,
- cl->notify_en == request || !mei_cl_is_connected(cl),
+ cl->notify_en == request ||
+ cl->status ||
+ !mei_cl_is_connected(cl),
mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT));
mutex_lock(&dev->device_lock);
@@ -1573,10 +1551,13 @@
struct mei_msg_hdr mei_hdr;
size_t hdr_len = sizeof(mei_hdr);
size_t len;
- size_t hbuf_len;
+ size_t hbuf_len, dr_len;
int hbuf_slots;
+ u32 dr_slots;
+ u32 dma_len;
int rets;
bool first_chunk;
+ const void *data;
if (WARN_ON(!cl || !cl->dev))
return -ENODEV;
@@ -1597,6 +1578,7 @@
}
len = buf->size - cb->buf_idx;
+ data = buf->data + cb->buf_idx;
hbuf_slots = mei_hbuf_empty_slots(dev);
if (hbuf_slots < 0) {
rets = -EOVERFLOW;
@@ -1604,6 +1586,8 @@
}
hbuf_len = mei_slots2data(hbuf_slots);
+ dr_slots = mei_dma_ring_empty_slots(dev);
+ dr_len = mei_slots2data(dr_slots);
mei_msg_hdr_init(&mei_hdr, cb);
@@ -1614,23 +1598,33 @@
if (len + hdr_len <= hbuf_len) {
mei_hdr.length = len;
mei_hdr.msg_complete = 1;
+ } else if (dr_slots && hbuf_len >= hdr_len + sizeof(dma_len)) {
+ mei_hdr.dma_ring = 1;
+ if (len > dr_len)
+ len = dr_len;
+ else
+ mei_hdr.msg_complete = 1;
+
+ mei_hdr.length = sizeof(dma_len);
+ dma_len = len;
+ data = &dma_len;
} else if ((u32)hbuf_slots == mei_hbuf_depth(dev)) {
- mei_hdr.length = hbuf_len - hdr_len;
+ len = hbuf_len - hdr_len;
+ mei_hdr.length = len;
} else {
return 0;
}
- cl_dbg(dev, cl, "buf: size = %zu idx = %zu\n",
- cb->buf.size, cb->buf_idx);
+ if (mei_hdr.dma_ring)
+ mei_dma_ring_write(dev, buf->data + cb->buf_idx, len);
- rets = mei_write_message(dev, &mei_hdr, hdr_len,
- buf->data + cb->buf_idx, mei_hdr.length);
+ rets = mei_write_message(dev, &mei_hdr, hdr_len, data, mei_hdr.length);
if (rets)
goto err;
cl->status = 0;
cl->writing_state = MEI_WRITING;
- cb->buf_idx += mei_hdr.length;
+ cb->buf_idx += len;
if (first_chunk) {
if (mei_cl_tx_flow_ctrl_creds_reduce(cl)) {
@@ -1665,11 +1659,13 @@
struct mei_msg_data *buf;
struct mei_msg_hdr mei_hdr;
size_t hdr_len = sizeof(mei_hdr);
- size_t len;
- size_t hbuf_len;
+ size_t len, hbuf_len, dr_len;
int hbuf_slots;
+ u32 dr_slots;
+ u32 dma_len;
ssize_t rets;
bool blocking;
+ const void *data;
if (WARN_ON(!cl || !cl->dev))
return -ENODEV;
@@ -1681,10 +1677,12 @@
buf = &cb->buf;
len = buf->size;
- blocking = cb->blocking;
cl_dbg(dev, cl, "len=%zd\n", len);
+ blocking = cb->blocking;
+ data = buf->data;
+
rets = pm_runtime_get(dev->dev);
if (rets < 0 && rets != -EINPROGRESS) {
pm_runtime_put_noidle(dev->dev);
@@ -1721,16 +1719,32 @@
}
hbuf_len = mei_slots2data(hbuf_slots);
+ dr_slots = mei_dma_ring_empty_slots(dev);
+ dr_len = mei_slots2data(dr_slots);
if (len + hdr_len <= hbuf_len) {
mei_hdr.length = len;
mei_hdr.msg_complete = 1;
+ } else if (dr_slots && hbuf_len >= hdr_len + sizeof(dma_len)) {
+ mei_hdr.dma_ring = 1;
+ if (len > dr_len)
+ len = dr_len;
+ else
+ mei_hdr.msg_complete = 1;
+
+ mei_hdr.length = sizeof(dma_len);
+ dma_len = len;
+ data = &dma_len;
} else {
- mei_hdr.length = hbuf_len - hdr_len;
+ len = hbuf_len - hdr_len;
+ mei_hdr.length = len;
}
+ if (mei_hdr.dma_ring)
+ mei_dma_ring_write(dev, buf->data, len);
+
rets = mei_write_message(dev, &mei_hdr, hdr_len,
- buf->data, mei_hdr.length);
+ data, mei_hdr.length);
if (rets)
goto err;
@@ -1739,7 +1753,9 @@
goto err;
cl->writing_state = MEI_WRITING;
- cb->buf_idx = mei_hdr.length;
+ cb->buf_idx = len;
+ /* restore return value */
+ len = buf->size;
out:
if (mei_hdr.msg_complete)