Skip to content

Commit 47ea0dd

Browse files
Lalith RajendranTzung-Bi Shih
Lalith Rajendran
authored and
Tzung-Bi Shih
committed
platform/chrome: cros_ec_lpc: Separate host command and irq disable
Both cros host command and irq disable were moved to suspend prepare stage from late suspend recently. This is causing EC to report MKBP event timeouts during suspend stress testing. When the MKBP event timeouts happen during suspend, subsequent wakeup of AP by EC using MKBP doesn't happen properly. Move the irq disabling part back to late suspend stage which is a general suggestion from the suspend kernel documentaiton to do irq disable as late as possible. Fixes: 4b9abbc ("platform/chrome: cros_ec_lpc: Move host command to prepare/complete") Signed-off-by: Lalith Rajendran <[email protected]> Link: https://lore.kernel.org/r/20231027160221.v4.1.I1725c3ed27eb7cd9836904e49e8bfa9fb0200a97@changeid Signed-off-by: Tzung-Bi Shih <[email protected]>
1 parent 466f70f commit 47ea0dd

File tree

3 files changed

+116
-26
lines changed

3 files changed

+116
-26
lines changed

drivers/platform/chrome/cros_ec.c

+94-22
Original file line numberDiff line numberDiff line change
@@ -321,17 +321,8 @@ void cros_ec_unregister(struct cros_ec_device *ec_dev)
321321
EXPORT_SYMBOL(cros_ec_unregister);
322322

323323
#ifdef CONFIG_PM_SLEEP
324-
/**
325-
* cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device.
326-
* @ec_dev: Device to suspend.
327-
*
328-
* This can be called by drivers to handle a suspend event.
329-
*
330-
* Return: 0 on success or negative error code.
331-
*/
332-
int cros_ec_suspend(struct cros_ec_device *ec_dev)
324+
static void cros_ec_send_suspend_event(struct cros_ec_device *ec_dev)
333325
{
334-
struct device *dev = ec_dev->dev;
335326
int ret;
336327
u8 sleep_event;
337328

@@ -343,15 +334,62 @@ int cros_ec_suspend(struct cros_ec_device *ec_dev)
343334
if (ret < 0)
344335
dev_dbg(ec_dev->dev, "Error %d sending suspend event to ec\n",
345336
ret);
337+
}
346338

339+
/**
340+
* cros_ec_suspend_prepare() - Handle a suspend prepare operation for the ChromeOS EC device.
341+
* @ec_dev: Device to suspend.
342+
*
343+
* This can be called by drivers to handle a suspend prepare stage of suspend.
344+
*
345+
* Return: 0 always.
346+
*/
347+
int cros_ec_suspend_prepare(struct cros_ec_device *ec_dev)
348+
{
349+
cros_ec_send_suspend_event(ec_dev);
350+
return 0;
351+
}
352+
EXPORT_SYMBOL(cros_ec_suspend_prepare);
353+
354+
static void cros_ec_disable_irq(struct cros_ec_device *ec_dev)
355+
{
356+
struct device *dev = ec_dev->dev;
347357
if (device_may_wakeup(dev))
348358
ec_dev->wake_enabled = !enable_irq_wake(ec_dev->irq);
349359
else
350360
ec_dev->wake_enabled = false;
351361

352362
disable_irq(ec_dev->irq);
353363
ec_dev->suspended = true;
364+
}
354365

366+
/**
367+
* cros_ec_suspend_late() - Handle a suspend late operation for the ChromeOS EC device.
368+
* @ec_dev: Device to suspend.
369+
*
370+
* This can be called by drivers to handle a suspend late stage of suspend.
371+
*
372+
* Return: 0 always.
373+
*/
374+
int cros_ec_suspend_late(struct cros_ec_device *ec_dev)
375+
{
376+
cros_ec_disable_irq(ec_dev);
377+
return 0;
378+
}
379+
EXPORT_SYMBOL(cros_ec_suspend_late);
380+
381+
/**
382+
* cros_ec_suspend() - Handle a suspend operation for the ChromeOS EC device.
383+
* @ec_dev: Device to suspend.
384+
*
385+
* This can be called by drivers to handle a suspend event.
386+
*
387+
* Return: 0 always.
388+
*/
389+
int cros_ec_suspend(struct cros_ec_device *ec_dev)
390+
{
391+
cros_ec_send_suspend_event(ec_dev);
392+
cros_ec_disable_irq(ec_dev);
355393
return 0;
356394
}
357395
EXPORT_SYMBOL(cros_ec_suspend);
@@ -370,22 +408,11 @@ static void cros_ec_report_events_during_suspend(struct cros_ec_device *ec_dev)
370408
}
371409
}
372410

373-
/**
374-
* cros_ec_resume() - Handle a resume operation for the ChromeOS EC device.
375-
* @ec_dev: Device to resume.
376-
*
377-
* This can be called by drivers to handle a resume event.
378-
*
379-
* Return: 0 on success or negative error code.
380-
*/
381-
int cros_ec_resume(struct cros_ec_device *ec_dev)
411+
static void cros_ec_send_resume_event(struct cros_ec_device *ec_dev)
382412
{
383413
int ret;
384414
u8 sleep_event;
385415

386-
ec_dev->suspended = false;
387-
enable_irq(ec_dev->irq);
388-
389416
sleep_event = (!IS_ENABLED(CONFIG_ACPI) || pm_suspend_via_firmware()) ?
390417
HOST_SLEEP_EVENT_S3_RESUME :
391418
HOST_SLEEP_EVENT_S0IX_RESUME;
@@ -394,6 +421,24 @@ int cros_ec_resume(struct cros_ec_device *ec_dev)
394421
if (ret < 0)
395422
dev_dbg(ec_dev->dev, "Error %d sending resume event to ec\n",
396423
ret);
424+
}
425+
426+
/**
427+
* cros_ec_resume_complete() - Handle a resume complete operation for the ChromeOS EC device.
428+
* @ec_dev: Device to resume.
429+
*
430+
* This can be called by drivers to handle a resume complete stage of resume.
431+
*/
432+
void cros_ec_resume_complete(struct cros_ec_device *ec_dev)
433+
{
434+
cros_ec_send_resume_event(ec_dev);
435+
}
436+
EXPORT_SYMBOL(cros_ec_resume_complete);
437+
438+
static void cros_ec_enable_irq(struct cros_ec_device *ec_dev)
439+
{
440+
ec_dev->suspended = false;
441+
enable_irq(ec_dev->irq);
397442

398443
if (ec_dev->wake_enabled)
399444
disable_irq_wake(ec_dev->irq);
@@ -403,8 +448,35 @@ int cros_ec_resume(struct cros_ec_device *ec_dev)
403448
* suspend. This way the clients know what to do with them.
404449
*/
405450
cros_ec_report_events_during_suspend(ec_dev);
451+
}
406452

453+
/**
454+
* cros_ec_resume_early() - Handle a resume early operation for the ChromeOS EC device.
455+
* @ec_dev: Device to resume.
456+
*
457+
* This can be called by drivers to handle a resume early stage of resume.
458+
*
459+
* Return: 0 always.
460+
*/
461+
int cros_ec_resume_early(struct cros_ec_device *ec_dev)
462+
{
463+
cros_ec_enable_irq(ec_dev);
464+
return 0;
465+
}
466+
EXPORT_SYMBOL(cros_ec_resume_early);
407467

468+
/**
469+
* cros_ec_resume() - Handle a resume operation for the ChromeOS EC device.
470+
* @ec_dev: Device to resume.
471+
*
472+
* This can be called by drivers to handle a resume event.
473+
*
474+
* Return: 0 always.
475+
*/
476+
int cros_ec_resume(struct cros_ec_device *ec_dev)
477+
{
478+
cros_ec_enable_irq(ec_dev);
479+
cros_ec_send_resume_event(ec_dev);
408480
return 0;
409481
}
410482
EXPORT_SYMBOL(cros_ec_resume);

drivers/platform/chrome/cros_ec.h

+4
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,11 @@ int cros_ec_register(struct cros_ec_device *ec_dev);
1616
void cros_ec_unregister(struct cros_ec_device *ec_dev);
1717

1818
int cros_ec_suspend(struct cros_ec_device *ec_dev);
19+
int cros_ec_suspend_late(struct cros_ec_device *ec_dev);
20+
int cros_ec_suspend_prepare(struct cros_ec_device *ec_dev);
1921
int cros_ec_resume(struct cros_ec_device *ec_dev);
22+
int cros_ec_resume_early(struct cros_ec_device *ec_dev);
23+
void cros_ec_resume_complete(struct cros_ec_device *ec_dev);
2024

2125
irqreturn_t cros_ec_irq_thread(int irq, void *data);
2226

drivers/platform/chrome/cros_ec_lpc.c

+18-4
Original file line numberDiff line numberDiff line change
@@ -547,22 +547,36 @@ MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
547547
static int cros_ec_lpc_prepare(struct device *dev)
548548
{
549549
struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
550-
551-
return cros_ec_suspend(ec_dev);
550+
return cros_ec_suspend_prepare(ec_dev);
552551
}
553552

554553
static void cros_ec_lpc_complete(struct device *dev)
555554
{
556555
struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
557-
cros_ec_resume(ec_dev);
556+
cros_ec_resume_complete(ec_dev);
557+
}
558+
559+
static int cros_ec_lpc_suspend_late(struct device *dev)
560+
{
561+
struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
562+
563+
return cros_ec_suspend_late(ec_dev);
564+
}
565+
566+
static int cros_ec_lpc_resume_early(struct device *dev)
567+
{
568+
struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
569+
570+
return cros_ec_resume_early(ec_dev);
558571
}
559572
#endif
560573

561574
static const struct dev_pm_ops cros_ec_lpc_pm_ops = {
562575
#ifdef CONFIG_PM_SLEEP
563576
.prepare = cros_ec_lpc_prepare,
564-
.complete = cros_ec_lpc_complete
577+
.complete = cros_ec_lpc_complete,
565578
#endif
579+
SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_lpc_suspend_late, cros_ec_lpc_resume_early)
566580
};
567581

568582
static struct platform_driver cros_ec_lpc_driver = {

0 commit comments

Comments
 (0)