Skip to content

Commit b212caa

Browse files
committed
Error out MRPC execution when no more GAS access
It was observed that after a firmware hard reset, the MRPC execution will hang indefinitely. This is because after the reset, the host will get all 1s for any BAR read, in which case the driver won't get a valid MRPC status. Add a read check to GAS access when a MRPC command execution don't response timely, error out if the check fails.
1 parent cbf1061 commit b212caa

File tree

1 file changed

+51
-6
lines changed

1 file changed

+51
-6
lines changed

switchtec.c

Lines changed: 51 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ enum mrpc_state {
5252
MRPC_QUEUED,
5353
MRPC_RUNNING,
5454
MRPC_DONE,
55+
MRPC_IO_ERROR,
5556
};
5657

5758
struct switchtec_user {
@@ -72,6 +73,13 @@ struct switchtec_user {
7273
int event_cnt;
7374
};
7475

76+
static int check_access(struct switchtec_dev *stdev)
77+
{
78+
u32 device = ioread32(&stdev->mmio_sys_info->device_id);
79+
80+
return stdev->pdev->device == device;
81+
}
82+
7583
static struct switchtec_user *stuser_create(struct switchtec_dev *stdev)
7684
{
7785
struct switchtec_user *stuser;
@@ -119,6 +127,7 @@ static void stuser_set_state(struct switchtec_user *stuser,
119127
[MRPC_QUEUED] = "QUEUED",
120128
[MRPC_RUNNING] = "RUNNING",
121129
[MRPC_DONE] = "DONE",
130+
[MRPC_IO_ERROR] = "IO_ERROR",
122131
};
123132

124133
stuser->state = state;
@@ -186,6 +195,20 @@ static int mrpc_queue_cmd(struct switchtec_user *stuser)
186195
return 0;
187196
}
188197

198+
static void mrpc_cleanup_cmd(struct switchtec_dev *stdev)
199+
{
200+
/* requires the mrpc_mutex to already be held when called */
201+
struct switchtec_user *stuser = list_entry(stdev->mrpc_queue.next,
202+
struct switchtec_user, list);
203+
204+
complete_all(&stuser->comp);
205+
list_del_init(&stuser->list);
206+
stuser_put(stuser);
207+
stdev->mrpc_busy = 0;
208+
209+
mrpc_cmd_submit(stdev);
210+
}
211+
189212
static void mrpc_complete_cmd(struct switchtec_dev *stdev)
190213
{
191214
/* requires the mrpc_mutex to already be held when called */
@@ -226,12 +249,7 @@ static void mrpc_complete_cmd(struct switchtec_dev *stdev)
226249
memcpy_fromio(stuser->data, &stdev->mmio_mrpc->output_data,
227250
stuser->read_len);
228251
out:
229-
complete_all(&stuser->comp);
230-
list_del_init(&stuser->list);
231-
stuser_put(stuser);
232-
stdev->mrpc_busy = 0;
233-
234-
mrpc_cmd_submit(stdev);
252+
mrpc_cleanup_cmd(stdev);
235253
}
236254

237255
static void mrpc_event_work(struct work_struct *work)
@@ -248,6 +266,23 @@ static void mrpc_event_work(struct work_struct *work)
248266
mutex_unlock(&stdev->mrpc_mutex);
249267
}
250268

269+
static void mrpc_error_complete_cmd(struct switchtec_dev *stdev)
270+
{
271+
/* requires the mrpc_mutex to already be held when called */
272+
273+
struct switchtec_user *stuser;
274+
275+
if (list_empty(&stdev->mrpc_queue))
276+
return;
277+
278+
stuser = list_entry(stdev->mrpc_queue.next,
279+
struct switchtec_user, list);
280+
281+
stuser_set_state(stuser, MRPC_IO_ERROR);
282+
283+
mrpc_cleanup_cmd(stdev);
284+
}
285+
251286
static void mrpc_timeout_work(struct work_struct *work)
252287
{
253288
struct switchtec_dev *stdev;
@@ -259,6 +294,11 @@ static void mrpc_timeout_work(struct work_struct *work)
259294

260295
mutex_lock(&stdev->mrpc_mutex);
261296

297+
if (!check_access(stdev)) {
298+
mrpc_error_complete_cmd(stdev);
299+
goto out;
300+
}
301+
262302
if (stdev->dma_mrpc)
263303
status = stdev->dma_mrpc->status;
264304
else
@@ -544,6 +584,11 @@ static ssize_t switchtec_dev_read(struct file *filp, char __user *data,
544584
if (rc)
545585
return rc;
546586

587+
if (stuser->state == MRPC_IO_ERROR) {
588+
mutex_unlock(&stdev->mrpc_mutex);
589+
return -EIO;
590+
}
591+
547592
if (stuser->state != MRPC_DONE) {
548593
mutex_unlock(&stdev->mrpc_mutex);
549594
return -EBADE;

0 commit comments

Comments
 (0)