From: Tomas Winkler <tomas.winkler@intel.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Alexander Usyskin <alexander.usyskin@intel.com>,
linux-kernel@vger.kernel.org,
Tomas Winkler <tomas.winkler@intel.com>
Subject: [char-misc-next 01/12] mei: add support for variable length mei headers.
Date: Tue, 31 Jul 2018 09:35:33 +0300 [thread overview]
Message-ID: <20180731063544.25540-2-tomas.winkler@intel.com> (raw)
In-Reply-To: <20180731063544.25540-1-tomas.winkler@intel.com>
Remove header size knowledge from me and txe hw layers,
this requires to change the write handler to accept
header and its length as well as data and its length.
HBM messages are fixed to use basic header, hence we add mei_hbm2slots()
that converts HBM message length and mei message header,
while mei_data2slots() converts data length directly to the slots.
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
---
drivers/misc/mei/client.c | 31 ++++++++++++++++++-------------
drivers/misc/mei/hbm.c | 30 ++++++++++++++++++++++--------
drivers/misc/mei/hw-me.c | 34 ++++++++++++++++++++--------------
drivers/misc/mei/hw-txe.c | 42 +++++++++++++++++++++---------------------
drivers/misc/mei/interrupt.c | 4 ++--
drivers/misc/mei/mei_dev.h | 25 +++++++++++++++++++------
6 files changed, 102 insertions(+), 64 deletions(-)
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c
index 207d2f5d5702..0a9173827461 100644
--- a/drivers/misc/mei/client.c
+++ b/drivers/misc/mei/client.c
@@ -863,7 +863,7 @@ int mei_cl_irq_disconnect(struct mei_cl *cl, struct mei_cl_cb *cb,
int slots;
int ret;
- msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
+ msg_slots = mei_hbm2slots(sizeof(struct hbm_client_connect_request));
slots = mei_hbuf_empty_slots(dev);
if (slots < 0)
return -EOVERFLOW;
@@ -1055,11 +1055,10 @@ int mei_cl_irq_connect(struct mei_cl *cl, struct mei_cl_cb *cb,
int slots;
int rets;
- msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
-
if (mei_cl_is_other_connecting(cl))
return 0;
+ msg_slots = mei_hbm2slots(sizeof(struct hbm_client_connect_request));
slots = mei_hbuf_empty_slots(dev);
if (slots < 0)
return -EOVERFLOW;
@@ -1299,7 +1298,7 @@ int mei_cl_irq_notify(struct mei_cl *cl, struct mei_cl_cb *cb,
int ret;
bool request;
- msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_request));
+ msg_slots = mei_hbm2slots(sizeof(struct hbm_client_connect_request));
slots = mei_hbuf_empty_slots(dev);
if (slots < 0)
return -EOVERFLOW;
@@ -1571,6 +1570,7 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
struct mei_device *dev;
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;
int hbuf_slots;
@@ -1601,7 +1601,8 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
rets = -EOVERFLOW;
goto err;
}
- hbuf_len = mei_slots2data(hbuf_slots) - sizeof(struct mei_msg_hdr);
+
+ hbuf_len = mei_slots2data(hbuf_slots);
mei_msg_hdr_init(&mei_hdr, cb);
@@ -1609,11 +1610,11 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
* Split the message only if we can write the whole host buffer
* otherwise wait for next time the host buffer is empty.
*/
- if (hbuf_len >= len) {
+ if (len + hdr_len <= hbuf_len) {
mei_hdr.length = len;
mei_hdr.msg_complete = 1;
} else if ((u32)hbuf_slots == mei_hbuf_depth(dev)) {
- mei_hdr.length = hbuf_len;
+ mei_hdr.length = hbuf_len - hdr_len;
} else {
return 0;
}
@@ -1621,7 +1622,8 @@ int mei_cl_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb,
cl_dbg(dev, cl, "buf: size = %zu idx = %zu\n",
cb->buf.size, cb->buf_idx);
- rets = mei_write_message(dev, &mei_hdr, buf->data + cb->buf_idx);
+ rets = mei_write_message(dev, &mei_hdr, hdr_len,
+ buf->data + cb->buf_idx, mei_hdr.length);
if (rets)
goto err;
@@ -1661,6 +1663,7 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
struct mei_device *dev;
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;
int hbuf_slots;
@@ -1716,15 +1719,17 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
goto out;
}
- hbuf_len = mei_slots2data(hbuf_slots) - sizeof(struct mei_msg_hdr);
- if (hbuf_len >= len) {
+ hbuf_len = mei_slots2data(hbuf_slots);
+
+ if (len + hdr_len <= hbuf_len) {
mei_hdr.length = len;
mei_hdr.msg_complete = 1;
} else {
- mei_hdr.length = hbuf_len;
+ mei_hdr.length = hbuf_len - hdr_len;
}
- rets = mei_write_message(dev, &mei_hdr, buf->data);
+ rets = mei_write_message(dev, &mei_hdr, hdr_len,
+ buf->data, mei_hdr.length);
if (rets)
goto err;
@@ -1761,7 +1766,7 @@ ssize_t mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb)
}
}
- rets = len;
+ rets = buf->size;
err:
cl_dbg(dev, cl, "rpm: autosuspend\n");
pm_runtime_mark_last_busy(dev->dev);
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c
index fe6595fe94f1..8b3fd9ff6566 100644
--- a/drivers/misc/mei/hbm.c
+++ b/drivers/misc/mei/hbm.c
@@ -95,6 +95,20 @@ static int mei_cl_conn_status_to_errno(enum mei_cl_connect_status status)
}
}
+/**
+ * mei_hbm_write_message - wrapper for sending hbm messages.
+ *
+ * @dev: mei device
+ * @hdr: mei header
+ * @data: payload
+ */
+static inline int mei_hbm_write_message(struct mei_device *dev,
+ struct mei_msg_hdr *hdr,
+ const void *data)
+{
+ return mei_write_message(dev, hdr, sizeof(*hdr), data, hdr->length);
+}
+
/**
* mei_hbm_idle - set hbm to idle state
*
@@ -174,7 +188,7 @@ static inline int mei_hbm_cl_write(struct mei_device *dev, struct mei_cl *cl,
mei_hbm_hdr(&mei_hdr, len);
mei_hbm_cl_hdr(cl, hbm_cmd, buf, len);
- return mei_write_message(dev, &mei_hdr, buf);
+ return mei_hbm_write_message(dev, &mei_hdr, buf);
}
/**
@@ -267,7 +281,7 @@ int mei_hbm_start_req(struct mei_device *dev)
start_req.host_version.minor_version = HBM_MINOR_VERSION;
dev->hbm_state = MEI_HBM_IDLE;
- ret = mei_write_message(dev, &mei_hdr, &start_req);
+ ret = mei_hbm_write_message(dev, &mei_hdr, &start_req);
if (ret) {
dev_err(dev->dev, "version message write failed: ret = %d\n",
ret);
@@ -304,7 +318,7 @@ static int mei_hbm_enum_clients_req(struct mei_device *dev)
enum_req.flags |= dev->hbm_f_ie_supported ?
MEI_HBM_ENUM_F_IMMEDIATE_ENUM : 0;
- ret = mei_write_message(dev, &mei_hdr, &enum_req);
+ ret = mei_hbm_write_message(dev, &mei_hdr, &enum_req);
if (ret) {
dev_err(dev->dev, "enumeration request write failed: ret = %d.\n",
ret);
@@ -373,7 +387,7 @@ static int mei_hbm_add_cl_resp(struct mei_device *dev, u8 addr, u8 status)
resp.me_addr = addr;
resp.status = status;
- ret = mei_write_message(dev, &mei_hdr, &resp);
+ ret = mei_hbm_write_message(dev, &mei_hdr, &resp);
if (ret)
dev_err(dev->dev, "add client response write failed: ret = %d\n",
ret);
@@ -430,7 +444,7 @@ int mei_hbm_cl_notify_req(struct mei_device *dev,
req.start = start;
- ret = mei_write_message(dev, &mei_hdr, &req);
+ ret = mei_hbm_write_message(dev, &mei_hdr, &req);
if (ret)
dev_err(dev->dev, "notify request failed: ret = %d\n", ret);
@@ -555,7 +569,7 @@ static int mei_hbm_prop_req(struct mei_device *dev, unsigned long start_idx)
prop_req.hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
prop_req.me_addr = addr;
- ret = mei_write_message(dev, &mei_hdr, &prop_req);
+ ret = mei_hbm_write_message(dev, &mei_hdr, &prop_req);
if (ret) {
dev_err(dev->dev, "properties request write failed: ret = %d\n",
ret);
@@ -592,7 +606,7 @@ int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd)
memset(&req, 0, len);
req.hbm_cmd = pg_cmd;
- ret = mei_write_message(dev, &mei_hdr, &req);
+ ret = mei_hbm_write_message(dev, &mei_hdr, &req);
if (ret)
dev_err(dev->dev, "power gate command write failed.\n");
return ret;
@@ -618,7 +632,7 @@ static int mei_hbm_stop_req(struct mei_device *dev)
req.hbm_cmd = HOST_STOP_REQ_CMD;
req.reason = DRIVER_STOP_REQUEST;
- return mei_write_message(dev, &mei_hdr, &req);
+ return mei_hbm_write_message(dev, &mei_hdr, &req);
}
/**
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c
index c50671cf47eb..0e3c31595dda 100644
--- a/drivers/misc/mei/hw-me.c
+++ b/drivers/misc/mei/hw-me.c
@@ -517,28 +517,31 @@ static u32 mei_me_hbuf_depth(const struct mei_device *dev)
return hw->hbuf_depth;
}
-
/**
* mei_me_hbuf_write - writes a message to host hw buffer.
*
* @dev: the device structure
- * @header: mei HECI header of message
- * @buf: message payload will be written
+ * @hdr: header of message
+ * @hdr_len: header length in bytes: must be multiplication of a slot (4bytes)
+ * @data: payload
+ * @data_len: payload length in bytes
*
- * Return: -EIO if write has failed
+ * Return: 0 if success, < 0 - otherwise.
*/
static int mei_me_hbuf_write(struct mei_device *dev,
- struct mei_msg_hdr *header,
- const unsigned char *buf)
+ const void *hdr, size_t hdr_len,
+ const void *data, size_t data_len)
{
unsigned long rem;
- unsigned long length = header->length;
unsigned long i;
- u32 *reg_buf = (u32 *)buf;
+ const u32 *reg_buf;
u32 dw_cnt;
int empty_slots;
- dev_dbg(dev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header));
+ if (WARN_ON(!hdr || !data || hdr_len & 0x3))
+ return -EINVAL;
+
+ dev_dbg(dev->dev, MEI_HDR_FMT, MEI_HDR_PRM((struct mei_msg_hdr *)hdr));
empty_slots = mei_hbuf_empty_slots(dev);
dev_dbg(dev->dev, "empty slots = %hu.\n", empty_slots);
@@ -546,20 +549,23 @@ static int mei_me_hbuf_write(struct mei_device *dev,
if (empty_slots < 0)
return -EOVERFLOW;
- dw_cnt = mei_data2slots(length);
+ dw_cnt = mei_data2slots(hdr_len + data_len);
if (dw_cnt > (u32)empty_slots)
return -EMSGSIZE;
- mei_me_hcbww_write(dev, *((u32 *) header));
+ reg_buf = hdr;
+ for (i = 0; i < hdr_len / MEI_SLOT_SIZE; i++)
+ mei_me_hcbww_write(dev, reg_buf[i]);
- for (i = 0; i < length / MEI_SLOT_SIZE; i++)
+ reg_buf = data;
+ for (i = 0; i < data_len / MEI_SLOT_SIZE; i++)
mei_me_hcbww_write(dev, reg_buf[i]);
- rem = length & 0x3;
+ rem = data_len & 0x3;
if (rem > 0) {
u32 reg = 0;
- memcpy(®, &buf[length - rem], rem);
+ memcpy(®, (const u8 *)data + data_len - rem, rem);
mei_me_hcbww_write(dev, reg);
}
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c
index 7e2026894e9f..8449fe0367ff 100644
--- a/drivers/misc/mei/hw-txe.c
+++ b/drivers/misc/mei/hw-txe.c
@@ -689,37 +689,34 @@ static void mei_txe_hw_config(struct mei_device *dev)
hw->aliveness, hw->readiness);
}
-
/**
* mei_txe_write - writes a message to device.
*
* @dev: the device structure
- * @header: header of message
- * @buf: message buffer will be written
+ * @hdr: header of message
+ * @hdr_len: header length in bytes - must multiplication of a slot (4bytes)
+ * @data: payload
+ * @data_len: paylead length in bytes
*
- * Return: 0 if success, <0 - otherwise.
+ * Return: 0 if success, < 0 - otherwise.
*/
-
static int mei_txe_write(struct mei_device *dev,
- struct mei_msg_hdr *header,
- const unsigned char *buf)
+ const void *hdr, size_t hdr_len,
+ const void *data, size_t data_len)
{
struct mei_txe_hw *hw = to_txe_hw(dev);
unsigned long rem;
- unsigned long length;
- unsigned long i;
+ const u32 *reg_buf;
u32 slots = TXE_HBUF_DEPTH;
- u32 *reg_buf = (u32 *)buf;
u32 dw_cnt;
+ unsigned long i, j;
- if (WARN_ON(!header || !buf))
+ if (WARN_ON(!hdr || !data || hdr_len & 0x3))
return -EINVAL;
- length = header->length;
-
- dev_dbg(dev->dev, MEI_HDR_FMT, MEI_HDR_PRM(header));
+ dev_dbg(dev->dev, MEI_HDR_FMT, MEI_HDR_PRM((struct mei_msg_hdr *)hdr));
- dw_cnt = mei_data2slots(length);
+ dw_cnt = mei_data2slots(hdr_len + data_len);
if (dw_cnt > slots)
return -EMSGSIZE;
@@ -737,17 +734,20 @@ static int mei_txe_write(struct mei_device *dev,
return -EAGAIN;
}
- mei_txe_input_payload_write(dev, 0, *((u32 *)header));
+ reg_buf = hdr;
+ for (i = 0; i < hdr_len / MEI_SLOT_SIZE; i++)
+ mei_txe_input_payload_write(dev, i, reg_buf[i]);
- for (i = 0; i < length / 4; i++)
- mei_txe_input_payload_write(dev, i + 1, reg_buf[i]);
+ reg_buf = data;
+ for (j = 0; j < data_len / MEI_SLOT_SIZE; j++)
+ mei_txe_input_payload_write(dev, i + j, reg_buf[j]);
- rem = length & 0x3;
+ rem = data_len & 0x3;
if (rem > 0) {
u32 reg = 0;
- memcpy(®, &buf[length - rem], rem);
- mei_txe_input_payload_write(dev, i + 1, reg);
+ memcpy(®, (const u8 *)data + data_len - rem, rem);
+ mei_txe_input_payload_write(dev, i + j, reg);
}
/* after each write the whole buffer is consumed */
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
index 6217cebcad3d..5a661cbdf2ae 100644
--- a/drivers/misc/mei/interrupt.c
+++ b/drivers/misc/mei/interrupt.c
@@ -173,7 +173,7 @@ static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb,
int slots;
int ret;
- msg_slots = mei_data2slots(sizeof(struct hbm_client_connect_response));
+ msg_slots = mei_hbm2slots(sizeof(struct hbm_client_connect_response));
slots = mei_hbuf_empty_slots(dev);
if (slots < 0)
return -EOVERFLOW;
@@ -208,7 +208,7 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
if (!list_empty(&cl->rd_pending))
return 0;
- msg_slots = mei_data2slots(sizeof(struct hbm_flow_control));
+ msg_slots = mei_hbm2slots(sizeof(struct hbm_flow_control));
slots = mei_hbuf_empty_slots(dev);
if (slots < 0)
return -EOVERFLOW;
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index e9f37085a628..06fb5fc67fe9 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -300,8 +300,8 @@ struct mei_hw_ops {
bool (*hbuf_is_ready)(struct mei_device *dev);
u32 (*hbuf_depth)(const struct mei_device *dev);
int (*write)(struct mei_device *dev,
- struct mei_msg_hdr *hdr,
- const unsigned char *buf);
+ const void *hdr, size_t hdr_len,
+ const void *data, size_t data_len);
int (*rdbuf_full_slots)(struct mei_device *dev);
@@ -528,14 +528,26 @@ static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
}
/**
- * mei_data2slots - get slots - number of (dwords) from a message length
- * + size of the mei header
+ * mei_data2slots - get slots number from a message length
*
* @length: size of the messages in bytes
*
* Return: number of slots
*/
static inline u32 mei_data2slots(size_t length)
+{
+ return DIV_ROUND_UP(length, MEI_SLOT_SIZE);
+}
+
+/**
+ * mei_hbm2slots - get slots number from a hbm message length
+ * length + size of the mei message header
+ *
+ * @length: size of the messages in bytes
+ *
+ * Return: number of slots
+ */
+static inline u32 mei_hbm2slots(size_t length)
{
return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, MEI_SLOT_SIZE);
}
@@ -656,9 +668,10 @@ static inline u32 mei_hbuf_depth(const struct mei_device *dev)
}
static inline int mei_write_message(struct mei_device *dev,
- struct mei_msg_hdr *hdr, const void *buf)
+ const void *hdr, size_t hdr_len,
+ const void *data, size_t data_len)
{
- return dev->ops->write(dev, hdr, buf);
+ return dev->ops->write(dev, hdr, hdr_len, data, data_len);
}
static inline u32 mei_read_hdr(const struct mei_device *dev)
--
2.14.4
next prev parent reply other threads:[~2018-07-31 6:37 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-31 6:35 [char-misc-next 00/12] mei: Add DMA ring Tomas Winkler
2018-07-31 6:35 ` Tomas Winkler [this message]
2018-07-31 6:35 ` [char-misc-next 02/12] mei: hbm: define dma ring setup protocol Tomas Winkler
2018-07-31 6:35 ` [char-misc-next 03/12] mei: hbm: introduce dma bit in the message header Tomas Winkler
2018-07-31 6:35 ` [char-misc-next 04/12] mei: restrict dma ring support to hbm version 2.1 Tomas Winkler
2018-07-31 6:35 ` [char-misc-next 05/12] mei: define dma ring buffer sizes for PCH12 HW and newer Tomas Winkler
2018-07-31 6:35 ` [char-misc-next 06/12] mei: dma ring buffers allocation Tomas Winkler
2018-08-02 8:18 ` Greg Kroah-Hartman
2018-08-02 8:20 ` Winkler, Tomas
2018-08-05 20:38 ` Winkler, Tomas
2018-09-12 7:13 ` Greg Kroah-Hartman
2018-07-31 6:35 ` [char-misc-next 07/12] mei: hbm: setup dma ring Tomas Winkler
2018-07-31 6:35 ` [char-misc-next 08/12] mei: hw: add dma ring control block Tomas Winkler
2018-07-31 6:35 ` [char-misc-next 09/12] mei: dma ring: implement rx circular buffer logic Tomas Winkler
2018-07-31 6:35 ` [char-misc-next 10/12] mei: dma ring: implement transmit flow Tomas Winkler
2018-07-31 6:35 ` [char-misc-next 11/12] mei: bump hbm version to 2.1 Tomas Winkler
2018-07-31 6:35 ` [char-misc-next 12/12] mei: me: mark CNP devices as having dma support Tomas Winkler
2018-08-02 8:19 ` [char-misc-next 00/12] mei: Add DMA ring Greg Kroah-Hartman
2018-08-08 16:11 ` Winkler, Tomas
2018-08-19 5:34 ` Winkler, Tomas
2018-08-19 6:12 ` 'Greg Kroah-Hartman'
2018-09-12 7:12 ` Greg Kroah-Hartman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180731063544.25540-2-tomas.winkler@intel.com \
--to=tomas.winkler@intel.com \
--cc=alexander.usyskin@intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome