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;
        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;
        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;
        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;
                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);
 
         * 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;
        }
        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;
 
        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;
                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;
 
                }
        }
 
-       rets = len;
+       rets = buf->size;
 err:
        cl_dbg(dev, cl, "rpm: autosuspend\n");
        pm_runtime_mark_last_busy(dev->dev);
 
        }
 }
 
+/**
+ * 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
  *
        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);
 }
 
 /**
        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);
        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);
        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);
 
        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);
 
        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);
        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;
        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);
 }
 
 /**
 
        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);
        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);
        }
 
 
                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;
 
                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 */
 
        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;
        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;
 
        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);
 
 }
 
 /**
- * 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);
 }
 }
 
 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)