struct header {
u8 channel;
u8 status;
- u8 reserved[2];
+ u8 token;
+ u8 reserved;
} __packed;
struct cros_ish_out_msg {
* data exceeds this value, we log an error.
* @size: Actual size of data received from firmware.
* @error: 0 for success, negative error code for a failure in process_recv().
+ * @token: Expected token for response that we are waiting on.
* @received: Set to true on receiving a valid firmware response to host command
* @wait_queue: Wait queue for host to wait for firmware response.
*/
size_t max_size;
size_t size;
int error;
+ u8 token;
bool received;
wait_queue_head_t wait_queue;
};
u8 *out_msg, size_t out_size,
u8 *in_msg, size_t in_size)
{
+ static u8 next_token;
int rv;
struct header *out_hdr = (struct header *)out_msg;
struct ishtp_cl *cros_ish_cl = client_data->cros_ish_cl;
client_data->response.data = in_msg;
client_data->response.max_size = in_size;
client_data->response.error = 0;
+ client_data->response.token = next_token++;
client_data->response.received = false;
+ out_hdr->token = client_data->response.token;
+
rv = ishtp_cl_send(cros_ish_cl, out_msg, out_size);
if (rv) {
dev_err(cl_data_to_dev(client_data),
switch (in_msg->hdr.channel) {
case CROS_EC_COMMAND:
- /* Sanity check */
- if (!client_data->response.data) {
+ if (client_data->response.received) {
dev_err(dev,
- "Receiving buffer is null. Should be allocated by calling function\n");
- client_data->response.error = -EINVAL;
- goto error_wake_up;
+ "Previous firmware message not yet processed\n");
+ goto end_error;
}
- if (client_data->response.received) {
+ if (client_data->response.token != in_msg->hdr.token) {
+ dev_err_ratelimited(dev,
+ "Dropping old response token %d\n",
+ in_msg->hdr.token);
+ goto end_error;
+ }
+
+ /* Sanity check */
+ if (!client_data->response.data) {
dev_err(dev,
- "Previous firmware message not yet processed\n");
+ "Receiving buffer is null. Should be allocated by calling function\n");
client_data->response.error = -EINVAL;
goto error_wake_up;
}
memcpy(client_data->response.data,
rb_in_proc->buffer.data, data_len);
+error_wake_up:
/* Set flag before waking up the caller */
client_data->response.received = true;
-error_wake_up:
+
/* Wake the calling thread */
wake_up_interruptible(&client_data->response.wait_queue);