|
@@ -465,13 +465,34 @@ static void xgene_hwmon_evt_work(struct work_struct *work)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int xgene_hwmon_rx_ready(struct xgene_hwmon_dev *ctx, void *msg)
|
|
|
|
+{
|
|
|
|
+ if (IS_ERR_OR_NULL(ctx->hwmon_dev) && !ctx->resp_pending) {
|
|
|
|
+ /* Enqueue to the FIFO */
|
|
|
|
+ kfifo_in_spinlocked(&ctx->async_msg_fifo, msg,
|
|
|
|
+ sizeof(struct slimpro_resp_msg),
|
|
|
|
+ &ctx->kfifo_lock);
|
|
|
|
+ return -ENODEV;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* This function is called when the SLIMpro Mailbox received a message
|
|
* This function is called when the SLIMpro Mailbox received a message
|
|
*/
|
|
*/
|
|
static void xgene_hwmon_rx_cb(struct mbox_client *cl, void *msg)
|
|
static void xgene_hwmon_rx_cb(struct mbox_client *cl, void *msg)
|
|
{
|
|
{
|
|
struct xgene_hwmon_dev *ctx = to_xgene_hwmon_dev(cl);
|
|
struct xgene_hwmon_dev *ctx = to_xgene_hwmon_dev(cl);
|
|
- struct slimpro_resp_msg amsg;
|
|
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * While the driver registers with the mailbox framework, an interrupt
|
|
|
|
+ * can be pending before the probe function completes its
|
|
|
|
+ * initialization. If such condition occurs, just queue up the message
|
|
|
|
+ * as the driver is not ready for servicing the callback.
|
|
|
|
+ */
|
|
|
|
+ if (xgene_hwmon_rx_ready(ctx, msg) < 0)
|
|
|
|
+ return;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Response message format:
|
|
* Response message format:
|
|
@@ -500,12 +521,8 @@ static void xgene_hwmon_rx_cb(struct mbox_client *cl, void *msg)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- amsg.msg = ((u32 *)msg)[0];
|
|
|
|
- amsg.param1 = ((u32 *)msg)[1];
|
|
|
|
- amsg.param2 = ((u32 *)msg)[2];
|
|
|
|
-
|
|
|
|
/* Enqueue to the FIFO */
|
|
/* Enqueue to the FIFO */
|
|
- kfifo_in_spinlocked(&ctx->async_msg_fifo, &amsg,
|
|
|
|
|
|
+ kfifo_in_spinlocked(&ctx->async_msg_fifo, msg,
|
|
sizeof(struct slimpro_resp_msg), &ctx->kfifo_lock);
|
|
sizeof(struct slimpro_resp_msg), &ctx->kfifo_lock);
|
|
/* Schedule the bottom handler */
|
|
/* Schedule the bottom handler */
|
|
schedule_work(&ctx->workq);
|
|
schedule_work(&ctx->workq);
|
|
@@ -520,6 +537,15 @@ static void xgene_hwmon_pcc_rx_cb(struct mbox_client *cl, void *msg)
|
|
struct acpi_pcct_shared_memory *generic_comm_base = ctx->pcc_comm_addr;
|
|
struct acpi_pcct_shared_memory *generic_comm_base = ctx->pcc_comm_addr;
|
|
struct slimpro_resp_msg amsg;
|
|
struct slimpro_resp_msg amsg;
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * While the driver registers with the mailbox framework, an interrupt
|
|
|
|
+ * can be pending before the probe function completes its
|
|
|
|
+ * initialization. If such condition occurs, just queue up the message
|
|
|
|
+ * as the driver is not ready for servicing the callback.
|
|
|
|
+ */
|
|
|
|
+ if (xgene_hwmon_rx_ready(ctx, &amsg) < 0)
|
|
|
|
+ return;
|
|
|
|
+
|
|
msg = generic_comm_base + 1;
|
|
msg = generic_comm_base + 1;
|
|
/* Check if platform sends interrupt */
|
|
/* Check if platform sends interrupt */
|
|
if (!xgene_word_tst_and_clr(&generic_comm_base->status,
|
|
if (!xgene_word_tst_and_clr(&generic_comm_base->status,
|
|
@@ -596,6 +622,17 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
|
|
platform_set_drvdata(pdev, ctx);
|
|
platform_set_drvdata(pdev, ctx);
|
|
cl = &ctx->mbox_client;
|
|
cl = &ctx->mbox_client;
|
|
|
|
|
|
|
|
+ spin_lock_init(&ctx->kfifo_lock);
|
|
|
|
+ mutex_init(&ctx->rd_mutex);
|
|
|
|
+
|
|
|
|
+ rc = kfifo_alloc(&ctx->async_msg_fifo,
|
|
|
|
+ sizeof(struct slimpro_resp_msg) * ASYNC_MSG_FIFO_SIZE,
|
|
|
|
+ GFP_KERNEL);
|
|
|
|
+ if (rc)
|
|
|
|
+ goto out_mbox_free;
|
|
|
|
+
|
|
|
|
+ INIT_WORK(&ctx->workq, xgene_hwmon_evt_work);
|
|
|
|
+
|
|
/* Request mailbox channel */
|
|
/* Request mailbox channel */
|
|
cl->dev = &pdev->dev;
|
|
cl->dev = &pdev->dev;
|
|
cl->tx_done = xgene_hwmon_tx_done;
|
|
cl->tx_done = xgene_hwmon_tx_done;
|
|
@@ -676,17 +713,6 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
|
|
ctx->usecs_lat = PCC_NUM_RETRIES * cppc_ss->latency;
|
|
ctx->usecs_lat = PCC_NUM_RETRIES * cppc_ss->latency;
|
|
}
|
|
}
|
|
|
|
|
|
- spin_lock_init(&ctx->kfifo_lock);
|
|
|
|
- mutex_init(&ctx->rd_mutex);
|
|
|
|
-
|
|
|
|
- rc = kfifo_alloc(&ctx->async_msg_fifo,
|
|
|
|
- sizeof(struct slimpro_resp_msg) * ASYNC_MSG_FIFO_SIZE,
|
|
|
|
- GFP_KERNEL);
|
|
|
|
- if (rc)
|
|
|
|
- goto out_mbox_free;
|
|
|
|
-
|
|
|
|
- INIT_WORK(&ctx->workq, xgene_hwmon_evt_work);
|
|
|
|
-
|
|
|
|
ctx->hwmon_dev = hwmon_device_register_with_groups(ctx->dev,
|
|
ctx->hwmon_dev = hwmon_device_register_with_groups(ctx->dev,
|
|
"apm_xgene",
|
|
"apm_xgene",
|
|
ctx,
|
|
ctx,
|
|
@@ -697,17 +723,22 @@ static int xgene_hwmon_probe(struct platform_device *pdev)
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * Schedule the bottom handler if there is a pending message.
|
|
|
|
+ */
|
|
|
|
+ schedule_work(&ctx->workq);
|
|
|
|
+
|
|
dev_info(&pdev->dev, "APM X-Gene SoC HW monitor driver registered\n");
|
|
dev_info(&pdev->dev, "APM X-Gene SoC HW monitor driver registered\n");
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
out:
|
|
out:
|
|
- kfifo_free(&ctx->async_msg_fifo);
|
|
|
|
-out_mbox_free:
|
|
|
|
if (acpi_disabled)
|
|
if (acpi_disabled)
|
|
mbox_free_channel(ctx->mbox_chan);
|
|
mbox_free_channel(ctx->mbox_chan);
|
|
else
|
|
else
|
|
pcc_mbox_free_channel(ctx->mbox_chan);
|
|
pcc_mbox_free_channel(ctx->mbox_chan);
|
|
|
|
+out_mbox_free:
|
|
|
|
+ kfifo_free(&ctx->async_msg_fifo);
|
|
|
|
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|