aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhotran <hotran@apm.com>2016-09-08 12:33:10 -0400
committerGuenter Roeck <linux@roeck-us.net>2016-09-09 00:34:17 -0400
commit2ca492e22cb70a001749377506bd22eb06f60ecc (patch)
tree60a85d8ac28f2b04f54e36bcd04345a1db6383bc
parent9417fefe6f6ec2005ff302fba33038f58ed766e3 (diff)
hwmon: (xgene) Fix crash when alarm occurs before driver probe
The system crashes during probing xgene-hwmon driver when temperature alarm interrupt occurs before. It's because - xgene_hwmon_probe() requests mailbox channel which also enables the mailbox interrupt. - As temperature alarm interrupt is pending, ISR runs and crashes when accesses into invalid resourse as unmapped PCC shared memory. This patch fixes this issue by saving this alarm message and scheduling a bottom handler after xgene_hwmon_probe() finish. Signed-off-by: Hoan Tran <hotran@apm.com> Reported-by: Itaru Kitayama <itaru.kitayama@riken.jp> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r--drivers/hwmon/xgene-hwmon.c69
1 files changed, 50 insertions, 19 deletions
diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c
index bc78a5d10182..aa44579a1e5a 100644
--- a/drivers/hwmon/xgene-hwmon.c
+++ b/drivers/hwmon/xgene-hwmon.c
@@ -465,13 +465,34 @@ static void xgene_hwmon_evt_work(struct work_struct *work)
465 } 465 }
466} 466}
467 467
468static int xgene_hwmon_rx_ready(struct xgene_hwmon_dev *ctx, void *msg)
469{
470 if (IS_ERR_OR_NULL(ctx->hwmon_dev) && !ctx->resp_pending) {
471 /* Enqueue to the FIFO */
472 kfifo_in_spinlocked(&ctx->async_msg_fifo, msg,
473 sizeof(struct slimpro_resp_msg),
474 &ctx->kfifo_lock);
475 return -ENODEV;
476 }
477
478 return 0;
479}
480
468/* 481/*
469 * This function is called when the SLIMpro Mailbox received a message 482 * This function is called when the SLIMpro Mailbox received a message
470 */ 483 */
471static void xgene_hwmon_rx_cb(struct mbox_client *cl, void *msg) 484static void xgene_hwmon_rx_cb(struct mbox_client *cl, void *msg)
472{ 485{
473 struct xgene_hwmon_dev *ctx = to_xgene_hwmon_dev(cl); 486 struct xgene_hwmon_dev *ctx = to_xgene_hwmon_dev(cl);
474 struct slimpro_resp_msg amsg; 487
488 /*
489 * While the driver registers with the mailbox framework, an interrupt
490 * can be pending before the probe function completes its
491 * initialization. If such condition occurs, just queue up the message
492 * as the driver is not ready for servicing the callback.
493 */
494 if (xgene_hwmon_rx_ready(ctx, msg) < 0)
495 return;
475 496
476 /* 497 /*
477 * Response message format: 498 * Response message format:
@@ -500,12 +521,8 @@ static void xgene_hwmon_rx_cb(struct mbox_client *cl, void *msg)
500 return; 521 return;
501 } 522 }
502 523
503 amsg.msg = ((u32 *)msg)[0];
504 amsg.param1 = ((u32 *)msg)[1];
505 amsg.param2 = ((u32 *)msg)[2];
506
507 /* Enqueue to the FIFO */ 524 /* Enqueue to the FIFO */
508 kfifo_in_spinlocked(&ctx->async_msg_fifo, &amsg, 525 kfifo_in_spinlocked(&ctx->async_msg_fifo, msg,
509 sizeof(struct slimpro_resp_msg), &ctx->kfifo_lock); 526 sizeof(struct slimpro_resp_msg), &ctx->kfifo_lock);
510 /* Schedule the bottom handler */ 527 /* Schedule the bottom handler */
511 schedule_work(&ctx->workq); 528 schedule_work(&ctx->workq);
@@ -520,6 +537,15 @@ static void xgene_hwmon_pcc_rx_cb(struct mbox_client *cl, void *msg)
520 struct acpi_pcct_shared_memory *generic_comm_base = ctx->pcc_comm_addr; 537 struct acpi_pcct_shared_memory *generic_comm_base = ctx->pcc_comm_addr;
521 struct slimpro_resp_msg amsg; 538 struct slimpro_resp_msg amsg;
522 539
540 /*
541 * While the driver registers with the mailbox framework, an interrupt
542 * can be pending before the probe function completes its
543 * initialization. If such condition occurs, just queue up the message
544 * as the driver is not ready for servicing the callback.
545 */
546 if (xgene_hwmon_rx_ready(ctx, &amsg) < 0)
547 return;
548
523 msg = generic_comm_base + 1; 549 msg = generic_comm_base + 1;
524 /* Check if platform sends interrupt */ 550 /* Check if platform sends interrupt */
525 if (!xgene_word_tst_and_clr(&generic_comm_base->status, 551 if (!xgene_word_tst_and_clr(&generic_comm_base->status,
@@ -596,6 +622,17 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
596 platform_set_drvdata(pdev, ctx); 622 platform_set_drvdata(pdev, ctx);
597 cl = &ctx->mbox_client; 623 cl = &ctx->mbox_client;
598 624
625 spin_lock_init(&ctx->kfifo_lock);
626 mutex_init(&ctx->rd_mutex);
627
628 rc = kfifo_alloc(&ctx->async_msg_fifo,
629 sizeof(struct slimpro_resp_msg) * ASYNC_MSG_FIFO_SIZE,
630 GFP_KERNEL);
631 if (rc)
632 goto out_mbox_free;
633
634 INIT_WORK(&ctx->workq, xgene_hwmon_evt_work);
635
599 /* Request mailbox channel */ 636 /* Request mailbox channel */
600 cl->dev = &pdev->dev; 637 cl->dev = &pdev->dev;
601 cl->tx_done = xgene_hwmon_tx_done; 638 cl->tx_done = xgene_hwmon_tx_done;
@@ -676,17 +713,6 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
676 ctx->usecs_lat = PCC_NUM_RETRIES * cppc_ss->latency; 713 ctx->usecs_lat = PCC_NUM_RETRIES * cppc_ss->latency;
677 } 714 }
678 715
679 spin_lock_init(&ctx->kfifo_lock);
680 mutex_init(&ctx->rd_mutex);
681
682 rc = kfifo_alloc(&ctx->async_msg_fifo,
683 sizeof(struct slimpro_resp_msg) * ASYNC_MSG_FIFO_SIZE,
684 GFP_KERNEL);
685 if (rc)
686 goto out_mbox_free;
687
688 INIT_WORK(&ctx->workq, xgene_hwmon_evt_work);
689
690 ctx->hwmon_dev = hwmon_device_register_with_groups(ctx->dev, 716 ctx->hwmon_dev = hwmon_device_register_with_groups(ctx->dev,
691 "apm_xgene", 717 "apm_xgene",
692 ctx, 718 ctx,
@@ -697,17 +723,22 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
697 goto out; 723 goto out;
698 } 724 }
699 725
726 /*
727 * Schedule the bottom handler if there is a pending message.
728 */
729 schedule_work(&ctx->workq);
730
700 dev_info(&pdev->dev, "APM X-Gene SoC HW monitor driver registered\n"); 731 dev_info(&pdev->dev, "APM X-Gene SoC HW monitor driver registered\n");
701 732
702 return 0; 733 return 0;
703 734
704out: 735out:
705 kfifo_free(&ctx->async_msg_fifo);
706out_mbox_free:
707 if (acpi_disabled) 736 if (acpi_disabled)
708 mbox_free_channel(ctx->mbox_chan); 737 mbox_free_channel(ctx->mbox_chan);
709 else 738 else
710 pcc_mbox_free_channel(ctx->mbox_chan); 739 pcc_mbox_free_channel(ctx->mbox_chan);
740out_mbox_free:
741 kfifo_free(&ctx->async_msg_fifo);
711 742
712 return rc; 743 return rc;
713} 744}