Skip to content

Commit 0f706b4

Browse files
Jett RinkEnric Balletbo i Serra
authored andcommitted
platform/chrome: cros_ec_ishtp: skip old cros_ec responses
The ISHTP layer can give us old responses that we already gave up on. We do not want to interpret these old responses as the current response we are waiting for. The cros_ish should only have one request in flight at a time. We send the request and wait for the response from the ISH. If the ISH is too slow to respond we give up on that request and we can send a new request. The ISH may still send the response to the request that timed out and without this we treat the old response as the response to the current command. This is a condition that should not normally happen but it has been observed with a bad ISH image. So add a token to the request header which is copied into the response header when the ISH processes the message to ensure that response is for the current request. Signed-off-by: Jett Rink <[email protected]> Signed-off-by: Mathew King <[email protected]> Signed-off-by: Enric Balletbo i Serra <[email protected]>
1 parent ad35da9 commit 0f706b4

File tree

1 file changed

+23
-9
lines changed

1 file changed

+23
-9
lines changed

drivers/platform/chrome/cros_ec_ishtp.c

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ static const guid_t cros_ish_guid =
4848
struct header {
4949
u8 channel;
5050
u8 status;
51-
u8 reserved[2];
51+
u8 token;
52+
u8 reserved;
5253
} __packed;
5354

5455
struct cros_ish_out_msg {
@@ -90,6 +91,7 @@ static DECLARE_RWSEM(init_lock);
9091
* data exceeds this value, we log an error.
9192
* @size: Actual size of data received from firmware.
9293
* @error: 0 for success, negative error code for a failure in process_recv().
94+
* @token: Expected token for response that we are waiting on.
9395
* @received: Set to true on receiving a valid firmware response to host command
9496
* @wait_queue: Wait queue for host to wait for firmware response.
9597
*/
@@ -98,6 +100,7 @@ struct response_info {
98100
size_t max_size;
99101
size_t size;
100102
int error;
103+
u8 token;
101104
bool received;
102105
wait_queue_head_t wait_queue;
103106
};
@@ -162,6 +165,7 @@ static int ish_send(struct ishtp_cl_data *client_data,
162165
u8 *out_msg, size_t out_size,
163166
u8 *in_msg, size_t in_size)
164167
{
168+
static u8 next_token;
165169
int rv;
166170
struct header *out_hdr = (struct header *)out_msg;
167171
struct ishtp_cl *cros_ish_cl = client_data->cros_ish_cl;
@@ -174,8 +178,11 @@ static int ish_send(struct ishtp_cl_data *client_data,
174178
client_data->response.data = in_msg;
175179
client_data->response.max_size = in_size;
176180
client_data->response.error = 0;
181+
client_data->response.token = next_token++;
177182
client_data->response.received = false;
178183

184+
out_hdr->token = client_data->response.token;
185+
179186
rv = ishtp_cl_send(cros_ish_cl, out_msg, out_size);
180187
if (rv) {
181188
dev_err(cl_data_to_dev(client_data),
@@ -249,17 +256,23 @@ static void process_recv(struct ishtp_cl *cros_ish_cl,
249256

250257
switch (in_msg->hdr.channel) {
251258
case CROS_EC_COMMAND:
252-
/* Sanity check */
253-
if (!client_data->response.data) {
259+
if (client_data->response.received) {
254260
dev_err(dev,
255-
"Receiving buffer is null. Should be allocated by calling function\n");
256-
client_data->response.error = -EINVAL;
257-
goto error_wake_up;
261+
"Previous firmware message not yet processed\n");
262+
goto end_error;
258263
}
259264

260-
if (client_data->response.received) {
265+
if (client_data->response.token != in_msg->hdr.token) {
266+
dev_err_ratelimited(dev,
267+
"Dropping old response token %d\n",
268+
in_msg->hdr.token);
269+
goto end_error;
270+
}
271+
272+
/* Sanity check */
273+
if (!client_data->response.data) {
261274
dev_err(dev,
262-
"Previous firmware message not yet processed\n");
275+
"Receiving buffer is null. Should be allocated by calling function\n");
263276
client_data->response.error = -EINVAL;
264277
goto error_wake_up;
265278
}
@@ -289,9 +302,10 @@ static void process_recv(struct ishtp_cl *cros_ish_cl,
289302
memcpy(client_data->response.data,
290303
rb_in_proc->buffer.data, data_len);
291304

305+
error_wake_up:
292306
/* Set flag before waking up the caller */
293307
client_data->response.received = true;
294-
error_wake_up:
308+
295309
/* Wake the calling thread */
296310
wake_up_interruptible(&client_data->response.wait_queue);
297311

0 commit comments

Comments
 (0)