Skip to content

Commit 2b5c4cb

Browse files
ausyskingregkh
authored andcommitted
mei: retry connect if interrupted by link reset
When device is in D3cold the connect message will wake device and cause link reset. Link reset flow cleans all queues and wakes all waiters. Retry the connect flow if connect is failed and link reset is detected. Signed-off-by: Alexander Usyskin <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent bb29fc3 commit 2b5c4cb

File tree

4 files changed

+32
-0
lines changed

4 files changed

+32
-0
lines changed

drivers/misc/mei/hw.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
#define MKHI_RCV_TIMEOUT 500 /* receive timeout in msec */
2828
#define MKHI_RCV_TIMEOUT_SLOW 10000 /* receive timeout in msec, slow FW */
2929

30+
#define MEI_LINK_RESET_WAIT_TIMEOUT_MSEC 500 /* Max wait timeout for link reset, in msec */
31+
3032
/*
3133
* FW page size for DMA allocations
3234
*/

drivers/misc/mei/init.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ void mei_device_init(struct mei_device *dev,
400400
init_waitqueue_head(&dev->wait_pg);
401401
init_waitqueue_head(&dev->wait_hbm_start);
402402
dev->dev_state = MEI_DEV_UNINITIALIZED;
403+
init_waitqueue_head(&dev->wait_dev_state);
403404
dev->reset_count = 0;
404405

405406
INIT_LIST_HEAD(&dev->write_list);
@@ -442,5 +443,6 @@ void mei_device_init(struct mei_device *dev,
442443
dev->timeouts.hbm = mei_secs_to_jiffies(MEI_HBM_TIMEOUT);
443444
dev->timeouts.mkhi_recv = msecs_to_jiffies(MKHI_RCV_TIMEOUT);
444445
}
446+
dev->timeouts.link_reset_wait = msecs_to_jiffies(MEI_LINK_RESET_WAIT_TIMEOUT_MSEC);
445447
}
446448
EXPORT_SYMBOL_GPL(mei_device_init);

drivers/misc/mei/main.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ static int mei_ioctl_connect_client(struct file *file,
423423
cl->state != MEI_FILE_DISCONNECTED)
424424
return -EBUSY;
425425

426+
retry:
426427
/* find ME client we're trying to connect to */
427428
me_cl = mei_me_cl_by_uuid(dev, in_client_uuid);
428429
if (!me_cl) {
@@ -454,6 +455,28 @@ static int mei_ioctl_connect_client(struct file *file,
454455

455456
rets = mei_cl_connect(cl, me_cl, file);
456457

458+
if (rets && cl->status == -EFAULT &&
459+
(dev->dev_state == MEI_DEV_RESETTING ||
460+
dev->dev_state == MEI_DEV_INIT_CLIENTS)) {
461+
/* in link reset, wait for it completion */
462+
mutex_unlock(&dev->device_lock);
463+
rets = wait_event_interruptible_timeout(dev->wait_dev_state,
464+
dev->dev_state == MEI_DEV_ENABLED,
465+
dev->timeouts.link_reset_wait);
466+
mutex_lock(&dev->device_lock);
467+
if (rets < 0) {
468+
if (signal_pending(current))
469+
rets = -EINTR;
470+
goto end;
471+
}
472+
if (dev->dev_state != MEI_DEV_ENABLED) {
473+
rets = -ETIME;
474+
goto end;
475+
}
476+
mei_me_cl_put(me_cl);
477+
goto retry;
478+
}
479+
457480
end:
458481
mei_me_cl_put(me_cl);
459482
return rets;
@@ -1120,6 +1143,8 @@ void mei_set_devstate(struct mei_device *dev, enum mei_dev_state state)
11201143

11211144
dev->dev_state = state;
11221145

1146+
wake_up_interruptible_all(&dev->wait_dev_state);
1147+
11231148
if (!dev->cdev)
11241149
return;
11251150

drivers/misc/mei/mei_dev.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ struct mei_dev_timeouts {
466466
unsigned int d0i3; /* D0i3 set/unset max response time, in jiffies */
467467
unsigned long hbm; /* HBM operation timeout, in jiffies */
468468
unsigned long mkhi_recv; /* receive timeout, in jiffies */
469+
unsigned long link_reset_wait; /* link reset wait timeout, in jiffies */
469470
};
470471

471472
/**
@@ -496,6 +497,7 @@ struct mei_dev_timeouts {
496497
*
497498
* @reset_count : number of consecutive resets
498499
* @dev_state : device state
500+
* @wait_dev_state: wait queue for device state change
499501
* @hbm_state : state of host bus message protocol
500502
* @pxp_mode : PXP device mode
501503
* @init_clients_timer : HBM init handshake timeout
@@ -588,6 +590,7 @@ struct mei_device {
588590
*/
589591
unsigned long reset_count;
590592
enum mei_dev_state dev_state;
593+
wait_queue_head_t wait_dev_state;
591594
enum mei_hbm_state hbm_state;
592595
enum mei_dev_pxp_mode pxp_mode;
593596
u16 init_clients_timer;

0 commit comments

Comments
 (0)