Skip to content

Commit 2105e8e

Browse files
basuamdJiri Kosina
authored andcommitted
HID: amd_sfh: Improve boot time when SFH is available
AMD SFH load takes longer time in initialization. Hence split and defer initialization code to improve SFH module load time and boot time of the system when SFH is available. Signed-off-by: Basavaraj Natikar <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent c1db007 commit 2105e8e

File tree

2 files changed

+64
-13
lines changed

2 files changed

+64
-13
lines changed

drivers/hid/amd-sfh-hid/amd_sfh_common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ struct amd_mp2_dev {
5353
/* mp2 active control status */
5454
u32 mp2_acs;
5555
struct sfh_dev_status dev_en;
56+
struct work_struct work;
57+
u8 init_done;
5658
};
5759

5860
struct amd_mp2_ops {

drivers/hid/amd-sfh-hid/amd_sfh_pcie.c

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <linux/bitops.h>
1212
#include <linux/delay.h>
13+
#include <linux/devm-helpers.h>
1314
#include <linux/dma-mapping.h>
1415
#include <linux/dmi.h>
1516
#include <linux/interrupt.h>
@@ -329,6 +330,48 @@ static const struct dmi_system_id dmi_nodevs[] = {
329330
{ }
330331
};
331332

333+
static void sfh1_1_init_work(struct work_struct *work)
334+
{
335+
struct amd_mp2_dev *mp2 = container_of(work, struct amd_mp2_dev, work);
336+
struct pci_dev *pdev = mp2->pdev;
337+
int rc;
338+
339+
rc = mp2->sfh1_1_ops->init(mp2);
340+
if (rc) {
341+
dev_err(&pdev->dev, "sfh1_1_init failed err %d\n", rc);
342+
return;
343+
}
344+
345+
amd_sfh_clear_intr(mp2);
346+
mp2->init_done = 1;
347+
}
348+
349+
static void sfh_init_work(struct work_struct *work)
350+
{
351+
struct amd_mp2_dev *mp2 = container_of(work, struct amd_mp2_dev, work);
352+
struct pci_dev *pdev = mp2->pdev;
353+
int rc;
354+
355+
rc = amd_sfh_hid_client_init(mp2);
356+
if (rc) {
357+
amd_sfh_clear_intr(mp2);
358+
dev_err(&pdev->dev, "amd_sfh_hid_client_init failed err %d\n", rc);
359+
return;
360+
}
361+
362+
amd_sfh_clear_intr(mp2);
363+
mp2->init_done = 1;
364+
}
365+
366+
static void amd_sfh_remove(struct pci_dev *pdev)
367+
{
368+
struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev);
369+
370+
flush_work(&mp2->work);
371+
if (mp2->init_done)
372+
mp2->mp2_ops->remove(mp2);
373+
}
374+
332375
static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
333376
{
334377
struct amd_mp2_dev *privdata;
@@ -367,10 +410,12 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
367410

368411
privdata->sfh1_1_ops = (const struct amd_sfh1_1_ops *)id->driver_data;
369412
if (privdata->sfh1_1_ops) {
370-
rc = privdata->sfh1_1_ops->init(privdata);
413+
rc = devm_work_autocancel(&pdev->dev, &privdata->work, sfh1_1_init_work);
371414
if (rc)
372415
return rc;
373-
goto init_done;
416+
417+
schedule_work(&privdata->work);
418+
return 0;
374419
}
375420

376421
mp2_select_ops(privdata);
@@ -381,33 +426,34 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
381426
return rc;
382427
}
383428

384-
rc = amd_sfh_hid_client_init(privdata);
429+
rc = devm_work_autocancel(&pdev->dev, &privdata->work, sfh_init_work);
385430
if (rc) {
386431
amd_sfh_clear_intr(privdata);
387-
if (rc != -EOPNOTSUPP)
388-
dev_err(&pdev->dev, "amd_sfh_hid_client_init failed\n");
389432
return rc;
390433
}
391434

392-
init_done:
393-
amd_sfh_clear_intr(privdata);
394-
395-
return devm_add_action_or_reset(&pdev->dev, privdata->mp2_ops->remove, privdata);
435+
schedule_work(&privdata->work);
436+
return 0;
396437
}
397438

398439
static void amd_sfh_shutdown(struct pci_dev *pdev)
399440
{
400441
struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev);
401442

402-
if (mp2 && mp2->mp2_ops)
403-
mp2->mp2_ops->stop_all(mp2);
443+
if (mp2) {
444+
flush_work(&mp2->work);
445+
if (mp2->init_done)
446+
mp2->mp2_ops->stop_all(mp2);
447+
}
404448
}
405449

406450
static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
407451
{
408452
struct amd_mp2_dev *mp2 = dev_get_drvdata(dev);
409453

410-
mp2->mp2_ops->resume(mp2);
454+
flush_work(&mp2->work);
455+
if (mp2->init_done)
456+
mp2->mp2_ops->resume(mp2);
411457

412458
return 0;
413459
}
@@ -416,7 +462,9 @@ static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
416462
{
417463
struct amd_mp2_dev *mp2 = dev_get_drvdata(dev);
418464

419-
mp2->mp2_ops->suspend(mp2);
465+
flush_work(&mp2->work);
466+
if (mp2->init_done)
467+
mp2->mp2_ops->suspend(mp2);
420468

421469
return 0;
422470
}
@@ -438,6 +486,7 @@ static struct pci_driver amd_mp2_pci_driver = {
438486
.probe = amd_mp2_pci_probe,
439487
.driver.pm = &amd_mp2_pm_ops,
440488
.shutdown = amd_sfh_shutdown,
489+
.remove = amd_sfh_remove,
441490
};
442491
module_pci_driver(amd_mp2_pci_driver);
443492

0 commit comments

Comments
 (0)