clear-pkgs-linux-iot-lts2018/0990-mei-support-variable-e...

710 lines
19 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aviad Nissel <aviad.nissel@intel.com>
Date: Thu, 8 Nov 2018 15:17:42 +0200
Subject: [PATCH] mei: support variable extended heci header.
The HECI header was adjusted to support variable number of
extensions.
Change-Id: Ia8c076ea95d851e9aea3d462118dc84cb61c180d
Tracked-On: PKT-1711
Signed-off-by: Aviad Nissel <aviad.nissel@intel.com>
---
drivers/misc/mei/client.c | 150 ++++++++++++++++++++++-------------
drivers/misc/mei/hw.h | 97 +++++++++++++++++-----
drivers/misc/mei/interrupt.c | 112 +++++++++++++++++++++-----
drivers/misc/mei/mei_dev.h | 4 +-
4 files changed, 267 insertions(+), 96 deletions(-)
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index e6833acb81d5..0c3dc9581747 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -1664,31 +1664,53 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length, const struct file *fp)
/**
* mei_msg_hdr_init - initialize mei message header
*
- * @mei_hdr: mei message header
* @cb: message callback structure
*
- * Return: header length in bytes
+ * Return: initialized header
*/
-static size_t mei_msg_hdr_init(struct mei_msg_hdr *mei_hdr,
- struct mei_cl_cb *cb)
+static struct mei_msg_hdr *mei_msg_hdr_init(struct mei_cl_cb *cb)
{
- size_t hdr_len = sizeof(*mei_hdr);
- struct mei_msg_extd_hdr *ext_hdr;
+ size_t hdr_len;
+ struct mei_ext_meta_hdr *meta;
+ struct mei_ext_hdr *ext;
+ struct mei_msg_hdr *mei_hdr;
+ bool is_ext, is_vtag;
+
+ is_ext = (cb->vtag && cb->buf_idx == 0);
+ is_vtag = is_ext;
+
+ hdr_len = sizeof(*mei_hdr);
+ if (is_ext)
+ hdr_len += sizeof(*meta);
+
+ if (is_vtag)
+ hdr_len += sizeof(*ext);
+
+ mei_hdr = kzalloc(hdr_len, GFP_KERNEL);
+ if (!mei_hdr)
+ return ERR_PTR(-ENOMEM);
- memset(mei_hdr, 0, sizeof(*mei_hdr));
mei_hdr->host_addr = mei_cl_host_addr(cb->cl);
mei_hdr->me_addr = mei_cl_me_id(cb->cl);
mei_hdr->internal = cb->internal;
+ mei_hdr->extended = is_ext;
- if (cb->vtag && cb->buf_idx == 0) {
- ext_hdr = (struct mei_msg_extd_hdr *)mei_hdr->extension;
- memset(ext_hdr, 0, sizeof(*ext_hdr));
- mei_hdr->extended = 1;
- ext_hdr->vtag = cb->vtag;
- hdr_len += sizeof(*ext_hdr);
- }
+ if (!is_ext)
+ goto out;
- return hdr_len;
+ meta = (struct mei_ext_meta_hdr *)mei_hdr->extension;
+ if (is_vtag) {
+ meta->count++;
+ meta->size = mei_data2slots(sizeof(*ext));
+
+ ext = meta->hdrs;
+ ext->type = MEI_EXT_HDR_VTAG;
+ ext->ext_payload[0] = cb->vtag;
+ ext->length = mei_data2slots(sizeof(*ext));
+ }
+out:
+ mei_hdr->length = hdr_len - sizeof(*mei_hdr);
+ return mei_hdr;
}
/**
@@ -1706,11 +1728,11 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
{
struct mei_device *dev;
struct mei_msg_data *buf;
- u32 __hdr[MEI_MSG_HDR_MAX];
- struct mei_msg_hdr *mei_hdr = (void *)__hdr;
+ struct mei_msg_hdr *mei_hdr = NULL;
size_t hdr_len;
- size_t len;
size_t hbuf_len, dr_len;
+ size_t buf_len;
+ size_t data_len;
int hbuf_slots;
u32 dr_slots;
u32 dma_len;
@@ -1736,7 +1758,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
return 0;
}
- len = buf->size - cb->buf_idx;
+ buf_len = buf->size - cb->buf_idx;
data = buf->data + cb->buf_idx;
hbuf_slots = mei_hbuf_empty_slots(dev);
if (hbuf_slots < 0) {
@@ -1748,45 +1770,54 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
dr_slots = mei_dma_ring_empty_slots(dev);
dr_len = mei_slots2data(dr_slots);
- hdr_len = mei_msg_hdr_init(mei_hdr, cb);
+ mei_hdr = mei_msg_hdr_init(cb);
+ if (IS_ERR(mei_hdr)) {
+ rets = PTR_ERR(mei_hdr);
+ mei_hdr = NULL;
+ goto err;
+ }
cl_dbg(dev, cl, "Extend Header %d vtag = %d\n",
mei_hdr->extended, cb->vtag);
+ hdr_len = sizeof(*mei_hdr) + mei_hdr->length;
+
/**
* Split the message only if we can write the whole host buffer
* otherwise wait for next time the host buffer is empty.
*/
- if (len + hdr_len <= hbuf_len) {
- mei_hdr->length = len;
+ if (hdr_len + buf_len <= hbuf_len) {
+ data_len = buf_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;
+ if (buf_len > dr_len)
+ buf_len = dr_len;
else
mei_hdr->msg_complete = 1;
- mei_hdr->length = sizeof(dma_len);
- dma_len = len;
+ data_len = sizeof(dma_len);
+ dma_len = buf_len;
data = &dma_len;
} else if ((u32)hbuf_slots == mei_hbuf_depth(dev)) {
- len = hbuf_len - hdr_len;
- mei_hdr->length = len;
+ buf_len = hbuf_len - hdr_len;
+ data_len = buf_len;
} else {
+ kfree(mei_hdr);
return 0;
}
+ mei_hdr->length += data_len;
if (mei_hdr->dma_ring)
- mei_dma_ring_write(dev, buf->data + cb->buf_idx, len);
+ mei_dma_ring_write(dev, buf->data + cb->buf_idx, buf_len);
+ rets = mei_write_message(dev, mei_hdr, hdr_len, data, data_len);
- 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 += len;
+ cb->buf_idx += buf_len;
if (first_chunk) {
if (mei_cl_tx_flow_ctrl_creds_reduce(cl)) {
@@ -1798,9 +1829,11 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
if (mei_hdr->msg_complete)
list_move_tail(&cb->list, &dev->write_waiting_list);
+ kfree(mei_hdr);
return 0;
err:
+ kfree(mei_hdr);
cl->status = rets;
list_move_tail(&cb->list, cmpl_list);
return rets;
@@ -1819,10 +1852,11 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
{
struct mei_device *dev;
struct mei_msg_data *buf;
- u32 __hdr[MEI_MSG_HDR_MAX];
- struct mei_msg_hdr *mei_hdr = (void *)__hdr;
+ struct mei_msg_hdr *mei_hdr = NULL;
size_t hdr_len;
- size_t len, hbuf_len, dr_len;
+ size_t hbuf_len, dr_len;
+ size_t buf_len;
+ size_t data_len;
int hbuf_slots;
u32 dr_slots;
u32 dma_len;
@@ -1839,9 +1873,9 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
dev = cl->dev;
buf = &cb->buf;
- len = buf->size;
+ buf_len = buf->size;
- cl_dbg(dev, cl, "len=%zd\n", len);
+ cl_dbg(dev, cl, "buf_len=%zd\n", buf_len);
blocking = cb->blocking;
data = buf->data;
@@ -1861,20 +1895,27 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
if (rets < 0)
goto err;
- hdr_len = mei_msg_hdr_init(mei_hdr, cb);
+ mei_hdr = mei_msg_hdr_init(cb);
+ if (IS_ERR(mei_hdr)) {
+ rets = -PTR_ERR(mei_hdr);
+ mei_hdr = NULL;
+ goto err;
+ }
cl_dbg(dev, cl, "Extend Header %d vtag = %d\n",
mei_hdr->extended, cb->vtag);
+ hdr_len = sizeof(*mei_hdr) + mei_hdr->length;
+
if (rets == 0) {
cl_dbg(dev, cl, "No flow control credentials: not sending.\n");
- rets = len;
+ rets = buf_len;
goto out;
}
if (!mei_hbuf_acquire(dev)) {
cl_dbg(dev, cl, "Cannot acquire the host buffer: not sending.\n");
- rets = len;
+ rets = buf_len;
goto out;
}
@@ -1888,29 +1929,30 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
dr_slots = mei_dma_ring_empty_slots(dev);
dr_len = mei_slots2data(dr_slots);
- if (len + hdr_len <= hbuf_len) {
- mei_hdr->length = len;
+ if (hdr_len + buf_len <= hbuf_len) {
+ data_len = buf_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;
+ if (buf_len > dr_len)
+ buf_len = dr_len;
else
mei_hdr->msg_complete = 1;
- mei_hdr->length = sizeof(dma_len);
- dma_len = len;
+ data_len = sizeof(dma_len);
+ dma_len = buf_len;
data = &dma_len;
} else {
- len = hbuf_len - hdr_len;
- mei_hdr->length = len;
+ buf_len = hbuf_len - hdr_len;
+ data_len = buf_len;
}
+ mei_hdr->length += data_len;
+
if (mei_hdr->dma_ring)
- mei_dma_ring_write(dev, buf->data, len);
+ mei_dma_ring_write(dev, buf->data, buf_len);
+ rets = mei_write_message(dev, mei_hdr, hdr_len, data, data_len);
- rets = mei_write_message(dev, mei_hdr, hdr_len,
- data, mei_hdr->length);
if (rets)
goto err;
@@ -1919,9 +1961,9 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
goto err;
cl->writing_state = MEI_WRITING;
- cb->buf_idx = len;
+ cb->buf_idx = buf_len;
/* restore return value */
- len = buf->size;
+ buf_len = buf->size;
out:
if (mei_hdr->msg_complete)
@@ -1949,7 +1991,7 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
}
}
- rets = len;
+ rets = buf_len;
err:
cl_dbg(dev, cl, "rpm: autosuspend\n");
pm_runtime_mark_last_busy(dev->dev);
@@ -1957,6 +1999,8 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
free:
mei_io_cb_free(cb);
+ kfree(mei_hdr);
+
return rets;
}
diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
index 90d118ae8434..64f8a934cb7d 100644
--- a/drivers/misc/mei/hw.h
+++ b/drivers/misc/mei/hw.h
@@ -1,7 +1,6 @@
/*
- *
* Intel Management Engine Interface (Intel MEI) Linux driver
- * Copyright (c) 2003-2012, Intel Corporation.
+ * Copyright (c) 2003-2018, 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,
@@ -207,19 +206,79 @@ enum mei_cl_connect_status {
/*
* Client Disconnect Status
*/
-enum mei_cl_disconnect_status {
+enum mei_cl_disconnect_status {
MEI_CL_DISCONN_SUCCESS = MEI_HBMS_SUCCESS
};
+enum mei_ext_hdr_type {
+ MEI_EXT_HDR_NONE = 0,
+ MEI_EXT_HDR_VTAG = 1,
+ MEI_EXT_HDR_GSC = 2,
+};
+
/**
- * struct mei_msg_extd_hdr - mei extended header
- *
- * @vtag: virtual tag.
- * @reserved: reserved.
+ * struct mei_ext_hdr - extend header descriptor (TLV)
+ * @type: enum mei_ext_hdr_type
+ * @length: length exluding descriptor
+ * @ext_payload: payload of the specific extended header
+ * @hdr: place holder for actuall header
+ */
+struct mei_ext_hdr {
+ u8 type;
+ u8 length;
+ u8 ext_payload[2];
+ u8 hdr[0];
+};
+
+/**
+ * struct mei_ext_meta_hdr - extend header meta data
+ * @count: number of headers
+ * @size: total size of the extended header list excluding meta header
+ * @reserved: reserved
*/
-struct mei_msg_extd_hdr {
- u8 vtag;
- u8 reserved[3];
+struct mei_ext_meta_hdr {
+ u8 count;
+ u8 size;
+ u8 reserved[2];
+ struct mei_ext_hdr hdrs[0];
+};
+
+static inline struct mei_ext_hdr *mei_ext_begin(struct mei_ext_meta_hdr *meta)
+{
+ return meta->hdrs;
+}
+
+static inline struct mei_ext_hdr *mei_ext_next(struct mei_ext_hdr *ext)
+{
+ return (struct mei_ext_hdr *)(ext->hdr + (ext->length * 4));
+}
+
+static inline bool mei_ext_last(struct mei_ext_meta_hdr *meta,
+ struct mei_ext_hdr *ext)
+{
+ return (u8 *)ext >= (u8 *)meta + sizeof(*meta) + (meta->size * 4);
+}
+
+struct mei_gcs_sgl {
+ u32 low;
+ u32 high;
+ u32 length;
+} __packed;
+
+struct mei_ext_hdr_gcs_h2f {
+ u32 fence_id;
+ u32 addr_type;
+ u32 input_address_count;
+ u32 output_address_count;
+ struct mei_gcs_sgl input_buffer[0];
+ struct mei_gcs_sgl output_buffer[0];
+} __packed;
+
+struct mei_ext_hdr_gcs_f2h {
+ u8 client_id;
+ u8 reserved[3];
+ u32 fence_id;
+ u32 total_bytes_written;
} __packed;
/**
@@ -247,8 +306,6 @@ struct mei_msg_hdr {
u32 extension[0];
} __packed;
-#define MEI_MSG_HDR_MAX 3
-
struct mei_bus_message {
u8 hbm_cmd;
u8 data[0];
@@ -461,19 +518,17 @@ struct hbm_notification_request {
/**
* struct hbm_notification_response - start/stop notification response
- *
* @hbm_cmd: bus message command header
* @me_addr: address of the client in ME
- * @host_addr: - address of the client in the driver
+ * @host_addr: address of the client in the driver
* @status: (mei_hbm_status) response status for the request
- * - MEI_HBMS_SUCCESS: successful stop/start
- * - MEI_HBMS_CLIENT_NOT_FOUND: if the connection could not be found.
- * - MEI_HBMS_ALREADY_STARTED: for start requests for a previously
- * started notification.
- * - MEI_HBMS_NOT_STARTED: for stop request for a connected client for whom
+ * * MEI_HBMS_SUCCESS: successful stop/start
+ * * MEI_HBMS_CLIENT_NOT_FOUND: if the connection could not be found.
+ * * MEI_HBMS_ALREADY_STARTED: for start requests for a previously
+ * started notification.
+ * * MEI_HBMS_NOT_STARTED: for stop request for a connected client for whom
* asynchronous notifications are currently disabled.
- *
- * @start: start = 1 or stop = 0 asynchronous notifications
+ * @start: start = 1 or stop = 0 asynchronous notifications
* @reserved: reserved
*/
struct hbm_notification_response {
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index d215289edcb1..4c1c98b9637a 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -72,16 +72,21 @@ static inline int mei_cl_hbm_equal(struct mei_cl *cl,
*
* @dev: mei device
* @hdr: message header
+ * @discard_len: the length of the message to discard (excluding header)
*/
-static void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr)
+static void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr,
+ size_t discard_len)
{
- if (hdr->dma_ring)
- mei_dma_ring_read(dev, NULL, hdr->extension[0]);
+ if (hdr->dma_ring) {
+ mei_dma_ring_read(dev, NULL,
+ hdr->extension[dev->rd_msg_hdr_count - 2]);
+ discard_len = 0;
+ }
/*
* no need to check for size as it is guarantied
* that length fits into rd_msg_buf
*/
- mei_read_slots(dev, dev->rd_msg_buf, hdr->length);
+ mei_read_slots(dev, dev->rd_msg_buf, discard_len);
dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n",
MEI_HDR_PRM(hdr));
}
@@ -91,19 +96,29 @@ static void mei_irq_discard_msg(struct mei_device *dev, struct mei_msg_hdr *hdr)
*
* @cl: reading client
* @mei_hdr: header of mei client message
+ * @meta: extend meta header
* @cmpl_list: completion list
*
* Return: always 0
*/
static int mei_cl_irq_read_msg(struct mei_cl *cl,
struct mei_msg_hdr *mei_hdr,
+ struct mei_ext_meta_hdr *meta,
struct list_head *cmpl_list)
{
struct mei_device *dev = cl->dev;
struct mei_cl_cb *cb;
- struct mei_msg_extd_hdr *ext_hdr = (void *)mei_hdr->extension;
+
size_t buf_sz;
u32 length;
+ int ext_len;
+
+ length = mei_hdr->length;
+ ext_len = 0;
+ if (mei_hdr->extended) {
+ ext_len = sizeof(*meta) + mei_slots2data(meta->size);
+ length -= ext_len;
+ }
cb = list_first_entry_or_null(&cl->rd_pending, struct mei_cl_cb, list);
if (!cb) {
@@ -118,14 +133,40 @@ static int mei_cl_irq_read_msg(struct mei_cl *cl,
}
if (mei_hdr->extended) {
- cl_dbg(dev, cl, "vtag: %d\n", ext_hdr->vtag);
- if (cb->vtag && cb->vtag != ext_hdr->vtag) {
+ struct mei_ext_hdr *ext;
+ struct mei_ext_hdr *vtag = NULL;
+
+ ext = mei_ext_begin(meta);
+ do {
+ switch (ext->type) {
+ case MEI_EXT_HDR_VTAG:
+ vtag = ext;
+ break;
+ case MEI_EXT_HDR_GSC:
+ case MEI_EXT_HDR_NONE:
+ default:
+ cb->status = -EPROTO;
+ break;
+ }
+
+ ext = mei_ext_next(ext);
+ } while (!mei_ext_last(meta, ext));
+
+ if (!vtag) {
+ cl_dbg(dev, cl, "vtag not found in extended header.\n");
+ cb->status = -EPROTO;
+ goto discard;
+ }
+
+ cl_dbg(dev, cl, "vtag: %d\n", vtag->ext_payload[0]);
+ if (cb->vtag && cb->vtag != vtag->ext_payload[0]) {
cl_err(dev, cl, "mismatched tag: %d != %d\n",
- cb->vtag, ext_hdr->vtag);
+ cb->vtag, vtag->ext_payload[0]);
cb->status = -EPROTO;
goto discard;
}
- cb->vtag = ext_hdr->vtag;
+ cb->vtag = vtag->ext_payload[0];
+
}
if (!mei_cl_is_connected(cl)) {
@@ -134,7 +175,8 @@ static int mei_cl_irq_read_msg(struct mei_cl *cl,
goto discard;
}
- length = mei_hdr->dma_ring ? mei_hdr->extension[1] : mei_hdr->length;
+ if (mei_hdr->dma_ring)
+ length = mei_hdr->extension[mei_data2slots(ext_len)];
buf_sz = length + cb->buf_idx;
/* catch for integer overflow */
@@ -152,11 +194,13 @@ static int mei_cl_irq_read_msg(struct mei_cl *cl,
goto discard;
}
- if (mei_hdr->dma_ring)
+ if (mei_hdr->dma_ring) {
mei_dma_ring_read(dev, cb->buf.data + cb->buf_idx, length);
-
- /* for DMA read 0 length to generate an interrupt to the device */
- mei_read_slots(dev, cb->buf.data + cb->buf_idx, mei_hdr->length);
+ /* for DMA read 0 length to generate interrupt to the device */
+ mei_read_slots(dev, cb->buf.data + cb->buf_idx, 0);
+ } else {
+ mei_read_slots(dev, cb->buf.data + cb->buf_idx, length);
+ }
cb->buf_idx += length;
@@ -173,7 +217,7 @@ static int mei_cl_irq_read_msg(struct mei_cl *cl,
discard:
if (cb)
list_move_tail(&cb->list, cmpl_list);
- mei_irq_discard_msg(dev, mei_hdr);
+ mei_irq_discard_msg(dev, mei_hdr, length);
return 0;
}
@@ -291,11 +335,16 @@ int mei_irq_read_handler(struct mei_device *dev,
struct list_head *cmpl_list, s32 *slots)
{
struct mei_msg_hdr *mei_hdr;
+ struct mei_ext_meta_hdr *meta_hdr = NULL;
struct mei_cl *cl;
int ret;
+ u32 ext_meta_hdr_u32;
+ int i;
+ int ext_hdr_end;
if (!dev->rd_msg_hdr[0]) {
dev->rd_msg_hdr[0] = mei_read_hdr(dev);
+ dev->rd_msg_hdr_count = 1;
(*slots)--;
dev_dbg(dev->dev, "slots =%08x.\n", *slots);
@@ -318,14 +367,34 @@ int mei_irq_read_handler(struct mei_device *dev,
goto end;
}
+ ext_hdr_end = 1;
+
if (mei_hdr->extended) {
- dev->rd_msg_hdr[1] = mei_read_hdr(dev);
- (*slots)--;
+ if (!dev->rd_msg_hdr[1]) {
+ ext_meta_hdr_u32 = mei_read_hdr(dev);
+ dev->rd_msg_hdr[1] = ext_meta_hdr_u32;
+ dev->rd_msg_hdr_count++;
+ (*slots)--;
+ dev_dbg(dev->dev, "extended header is %08x\n",
+ ext_meta_hdr_u32);
+ }
+ meta_hdr = ((struct mei_ext_meta_hdr *)
+ dev->rd_msg_hdr + 1);
+ ext_hdr_end = meta_hdr->size + 2;
+ for (i = dev->rd_msg_hdr_count; i < ext_hdr_end; i++) {
+ dev->rd_msg_hdr[i] = mei_read_hdr(dev);
+ dev_dbg(dev->dev, "extended header %d is %08x\n", i,
+ dev->rd_msg_hdr[i]);
+ dev->rd_msg_hdr_count++;
+ (*slots)--;
+ }
}
+
if (mei_hdr->dma_ring) {
- dev->rd_msg_hdr[2] = mei_read_hdr(dev);
+ dev->rd_msg_hdr[ext_hdr_end] = mei_read_hdr(dev);
+ dev->rd_msg_hdr_count++;
(*slots)--;
- mei_hdr->length = 0;
+ mei_hdr->length -= sizeof(dev->rd_msg_hdr[ext_hdr_end]);
}
/* HBM message */
@@ -356,7 +425,7 @@ int mei_irq_read_handler(struct mei_device *dev,
*/
if (hdr_is_fixed(mei_hdr) ||
dev->dev_state == MEI_DEV_POWER_DOWN) {
- mei_irq_discard_msg(dev, mei_hdr);
+ mei_irq_discard_msg(dev, mei_hdr, mei_hdr->length);
ret = 0;
goto reset_slots;
}
@@ -366,12 +435,13 @@ int mei_irq_read_handler(struct mei_device *dev,
goto end;
}
- ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list);
+ ret = mei_cl_irq_read_msg(cl, mei_hdr, meta_hdr, cmpl_list);
reset_slots:
/* reset the number of slots and header */
memset(dev->rd_msg_hdr, 0, sizeof(dev->rd_msg_hdr));
+ dev->rd_msg_hdr_count = 0;
*slots = mei_count_full_read_slots(dev);
if (*slots == -EOVERFLOW) {
/* overflow - reset */
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 07147c31b102..237e15c70260 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -433,6 +433,7 @@ struct mei_fw_version {
*
* @rd_msg_buf : control messages buffer
* @rd_msg_hdr : read message header storage
+ * @rd_msg_hdr_count : how many dwords were already read from header
*
* @hbuf_is_ready : query if the host host/write buffer is ready
* @dr_dscr: DMA ring descriptors: TX, RX, and CTRL
@@ -516,7 +517,8 @@ struct mei_device {
#endif /* CONFIG_PM */
unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE];
- u32 rd_msg_hdr[MEI_MSG_HDR_MAX];
+ u32 rd_msg_hdr[MEI_RD_MSG_BUF_SIZE];
+ int rd_msg_hdr_count;
/* write buffer */
bool hbuf_is_ready;
--
https://clearlinux.org