[PATCH linux dev-4.10] drivers/hwmon/occ: Switch to non-blocking for occ reads

Eddie James eajames at linux.vnet.ibm.com
Tue Sep 19 07:12:21 AEST 2017


From: Eddie James <eajames at us.ibm.com>

It's possible for the sbefifo ops to hang entirely if the system goes
down (checkstop, etc), meaning that the occ and occ-hwmon drivers may
hang during remove().

Signed-off-by: Eddie James <eajames at us.ibm.com>
---
 drivers/hwmon/occ/p9_sbe.c | 19 +++++++++++++++----
 1 file changed, 15 insertions(+), 4 deletions(-)

diff --git a/drivers/hwmon/occ/p9_sbe.c b/drivers/hwmon/occ/p9_sbe.c
index 2d50a94..a6aa4d2 100644
--- a/drivers/hwmon/occ/p9_sbe.c
+++ b/drivers/hwmon/occ/p9_sbe.c
@@ -16,7 +16,10 @@
 #include <linux/sched.h>
 #include <linux/workqueue.h>
 
+#define OCC_CMD_INCOMPLETE_MS		10
+
 struct p9_sbe_occ {
+	bool cancel;
 	struct occ occ;
 	struct device *sbe;
 };
@@ -34,7 +37,7 @@ static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd)
 	start = jiffies;
 
 retry:
-	client = occ_drv_open(p9_sbe_occ->sbe, 0);
+	client = occ_drv_open(p9_sbe_occ->sbe, O_NONBLOCK);
 	if (!client) {
 		rc = -ENODEV;
 		goto assign;
@@ -44,9 +47,14 @@ static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd)
 	if (rc < 0)
 		goto err;
 
-	rc = occ_drv_read(client, (char *)resp, sizeof(*resp));
-	if (rc < 0)
-		goto err;
+	do {
+		rc = occ_drv_read(client, (char *)resp, sizeof(*resp));
+		if (rc != -EAGAIN)
+			break;
+
+		set_current_state(TASK_INTERRUPTIBLE);
+		schedule_timeout(msecs_to_jiffies(OCC_CMD_INCOMPLETE_MS));
+	} while (!p9_sbe_occ->cancel);
 
 	occ_drv_release(client);
 
@@ -164,6 +172,9 @@ static int p9_sbe_occ_probe(struct platform_device *pdev)
 static int p9_sbe_occ_remove(struct platform_device *pdev)
 {
 	struct occ *occ = platform_get_drvdata(pdev);
+	struct p9_sbe_occ *p9_sbe_occ = to_p9_sbe_occ(occ);
+
+	p9_sbe_occ->cancel = true;
 
 	occ_remove_status_attrs(occ);
 
-- 
1.8.3.1



More information about the openbmc mailing list