linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [RFC] [PATCH 1/3] powernv/opal: Introduce new opal_oppanel interface to expose the op_panel
@ 2016-08-02  7:48 Suraj Jitindar Singh
  2016-08-02  7:48 ` [RFC] [PATCH 2/3] powernv/setup: Initialise opal_oppanel and display information on boot Suraj Jitindar Singh
  2016-08-02  7:48 ` [RFC] [PATCH 3/3] powernv/oppanel: Update op_panel module to utilise opal_oppanel interface Suraj Jitindar Singh
  0 siblings, 2 replies; 3+ messages in thread
From: Suraj Jitindar Singh @ 2016-08-02  7:48 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: sjitindarsingh

IBM PowerNV machines with FSPs have an operator panel with a LCD display.
Currently this oppanel display can be accessed through the
powernv_op_panel kernel module. We would like to be able to access this
display easily from other places in the Kernel.

Add a new interface through which the operator panel display can be
accessed from within the kernel. The function opal_oppanel_write acts like
a print function and will respect newline and carriage return characters
while trying to print the input to the display. The function
opal_oppanel_read will provide access to what is currently in the display
buffer.

Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
---
 MAINTAINERS                                   |   1 +
 arch/powerpc/include/asm/opal.h               |   7 +
 arch/powerpc/platforms/powernv/Kconfig        |   4 +
 arch/powerpc/platforms/powernv/Makefile       |   1 +
 arch/powerpc/platforms/powernv/opal-oppanel.c | 292 ++++++++++++++++++++++++++
 drivers/char/Kconfig                          |   1 +
 6 files changed, 306 insertions(+)
 create mode 100644 arch/powerpc/platforms/powernv/opal-oppanel.c

diff --git a/MAINTAINERS b/MAINTAINERS
index b1703ca..95841e1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -9218,6 +9218,7 @@ M:	Suraj Jitindar Singh <sjitindarsingh@gmail.com>
 L:	linuxppc-dev@lists.ozlabs.org
 S:	Maintained
 F:	drivers/char/powernv-op-panel.c
+F:	arch/powerpc/platforms/powernv/opal-oppanel.c
 
 PNP SUPPORT
 M:	"Rafael J. Wysocki" <rafael.j.wysocki@intel.com>
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index ea9e7f4..2802e1f 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -286,6 +286,13 @@ static inline int opal_get_async_rc(struct opal_msg msg)
 		return be64_to_cpu(msg.params[1]);
 }
 
+#if defined(CONFIG_POWERNV_OP_PANEL) || defined(CONFIG_POWERNV_OP_PANEL_MODULE)
+extern int opal_oppanel_write(char *msg);
+extern void opal_oppanel_read(char *msg);
+extern void opal_oppanel_get_size(u32 *size);
+extern int opal_oppanel_init(void);
+#endif /* CONFIG_POWERNV_OP_PANEL */
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_OPAL_H */
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig
index 604190c..df325f7 100644
--- a/arch/powerpc/platforms/powernv/Kconfig
+++ b/arch/powerpc/platforms/powernv/Kconfig
@@ -26,3 +26,7 @@ config OPAL_PRD
 	help
 	  This enables the opal-prd driver, a facility to run processor
 	  recovery diagnostics on OpenPower machines
+
+config POWERNV_OP_PANEL_BASE
+	bool
+	default n
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile
index cd9711e..0565351 100644
--- a/arch/powerpc/platforms/powernv/Makefile
+++ b/arch/powerpc/platforms/powernv/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_PPC_SCOM)	+= opal-xscom.o
 obj-$(CONFIG_MEMORY_FAILURE)	+= opal-memory-errors.o
 obj-$(CONFIG_TRACEPOINTS)	+= opal-tracepoints.o
 obj-$(CONFIG_OPAL_PRD)	+= opal-prd.o
+obj-$(CONFIG_POWERNV_OP_PANEL_BASE)	+= opal-oppanel.o
diff --git a/arch/powerpc/platforms/powernv/opal-oppanel.c b/arch/powerpc/platforms/powernv/opal-oppanel.c
new file mode 100644
index 0000000..1ddf414
--- /dev/null
+++ b/arch/powerpc/platforms/powernv/opal-oppanel.c
@@ -0,0 +1,292 @@
+/*
+ * OPAL PowerNV Operator Panel Display Code
+ *
+ * Copyright 2016, Suraj Jitindar Singh, IBM Corporation.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include <asm/opal.h>
+
+enum {
+	MODE_LF,
+	MODE_CR,
+	MODE_NC,
+};
+
+static DEFINE_MUTEX(opal_oppanel_mutex);
+
+static u32		num_lines, line_len, buf_len;
+static char		*buf;
+static oppanel_line_t	*lines;
+static int		cursor;
+
+static inline int last_line_index(void)
+{
+	return buf_len - line_len;
+}
+
+/*
+ * oppanel_write_to_display
+ * Write the contents of buf to the physical operator panel LCD display
+ *
+ * @return:	OPAL_SUCCESS on successful write
+ *		else write failed
+ */
+static int oppanel_write_to_display(void)
+{
+	struct opal_msg msg;
+	int rc, token;
+
+	token = opal_async_get_token_interruptible();
+	if (token < 0) {
+		if (token != -ERESTARTSYS)
+			pr_debug("Couldn't get OPAL async token [token=%d]\n",
+				token);
+		return token;
+	}
+
+	rc = opal_write_oppanel_async(token, lines, num_lines);
+	switch (rc) {
+	case OPAL_ASYNC_COMPLETION:
+		rc = opal_async_wait_response(token, &msg);
+		if (rc) {
+			pr_debug("Failed to wait for async response [rc=%d]\n",
+				rc);
+			break;
+		}
+		rc = opal_get_async_rc(msg);
+		if (rc != OPAL_SUCCESS) {
+			pr_debug("OPAL async call returned failed [rc=%d]\n",
+				rc);
+			break;
+		}
+	case OPAL_SUCCESS:
+		break;
+	default:
+		pr_debug("OPAL write op-panel call failed [rc=%d]\n", rc);
+	}
+
+	opal_async_release_token(token);
+	return rc;
+}
+
+/*
+ * oppanel_shift_up
+ * Shift the lines in buf up by one
+ */
+static void oppanel_shift_up(void)
+{
+	int i;
+
+	/* Shift line lengths */
+	for (i = 0; i < (num_lines - 1); i++)
+		lines[i].line_len = lines[i+1].line_len;
+
+	/* i = num_lines - 1 -> last line */
+	lines[i].line_len = 0;
+	memcpy(buf, &buf[line_len], line_len * i);
+	memset(&buf[i*line_len], '\0', line_len);
+}
+
+/*
+ * oppanel_update_display
+ * Update the oppanel display based on the current buf and cursor values
+ *
+ * @param:	mode, operation to perform
+ * @return:	OPAL_SUCCESS on success
+ *		else update failed
+ */
+static int oppanel_update_display(int mode)
+{
+	int rc;
+
+	lines[num_lines-1].line_len = cpu_to_be64(cursor + line_len - buf_len);
+	rc = oppanel_write_to_display();
+	/* May still be busy from last write call, if so we should retry */
+	while (rc != OPAL_SUCCESS) {
+		if (rc == OPAL_BUSY_EVENT || rc == -ERESTARTSYS)
+			rc = oppanel_write_to_display();
+		else
+			break;
+	}
+	switch (mode) {
+	case MODE_LF:
+		oppanel_shift_up();
+	case MODE_CR:
+		cursor = last_line_index();
+		break;
+	default:
+		break;
+	}
+
+	return rc;
+}
+
+/*
+ * opal_oppanel_write
+ * Write a message (msg) to the operator panel LCD display present on IBM
+ * powernv machines
+ *
+ * @param:	msg, the message buffer to be written to the display
+ * @return:	0		Success
+ *		-EIO		Opal call failed
+ *		-EBUSY		Resource currently in use
+ *		-ENODEV		Required resources not initialised,
+ *				either init function not called yet
+ *				or init failed likely due to no oppanel
+ */
+int opal_oppanel_write(char *msg)
+{
+	int rc = OPAL_SUCCESS;
+
+	if (!msg || !*msg)
+		return 0;
+	if (!buf || !buf_len || !lines)
+		return -ENODEV;
+
+	if (mutex_trylock(&opal_oppanel_mutex)) {
+		int i, prev_cursor = cursor;
+		char prev_buf[buf_len];
+
+		memcpy(prev_buf, buf, buf_len);
+
+		for (i = 0; msg[i] && rc == OPAL_SUCCESS; i++) {
+			char c = msg[i];
+
+			switch (c) {
+			case '\n':
+				rc = oppanel_update_display(MODE_LF);
+				break;
+			case '\r':
+				if (cursor != last_line_index())
+					rc = oppanel_update_display(MODE_CR);
+				break;
+			default:
+				buf[cursor++] = c;
+				/* End of display line */
+				if (cursor >= buf_len)
+					rc = oppanel_update_display(MODE_LF);
+				/* End of input buffer */
+				else if (!msg[i+1])
+					rc = oppanel_update_display(MODE_NC);
+				break;
+			}
+		}
+
+		if (rc != OPAL_SUCCESS) {
+			cursor = prev_cursor;
+			memcpy(buf, prev_buf, buf_len);
+			rc = -EIO;
+		}
+		mutex_unlock(&opal_oppanel_mutex);
+	} else
+		rc = -EBUSY;
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(opal_oppanel_write);
+
+/*
+ * opal_oppanel_read
+ * Read the operator panel message buffer and copy it to msg
+ *
+ * @param:	msg, a char buffer of size atleast buf_len,
+ *		as obtained by calling opal_oppanel_get_size.
+ */
+void opal_oppanel_read(char *msg)
+{
+	memcpy(msg, buf, buf_len);
+}
+EXPORT_SYMBOL_GPL(opal_oppanel_read);
+
+/*
+ * opal_oppanel_get_size
+ * Get the size of the physical operator panel display
+ *
+ * @param:	size, u32 pointer to where the size value should be stored.
+ */
+void opal_oppanel_get_size(u32 *size)
+{
+	*size = buf_len;
+}
+EXPORT_SYMBOL_GPL(opal_oppanel_get_size);
+
+/*
+ * opal_oppanel_init
+ * Initalise the operator panel, this must be called before any other
+ * function in this file
+ */
+int __init opal_oppanel_init(void)
+{
+	struct platform_device *pdev;
+	struct device_node *np;
+	int rc, i;
+
+	np = of_find_node_by_path("/ibm,opal/oppanel");
+	if (!np) {
+		pr_err("Opal node 'oppanel' not found\n");
+		rc = -ENODEV;
+		goto np_put;
+	}
+
+	/* Read length and number of lines device tree properties */
+	rc = of_property_read_u32(np, "#length", &line_len);
+	if (rc) {
+		pr_err("Opal node 'oppanel', '#length' property not found\n");
+		goto np_put;
+	}
+	rc = of_property_read_u32(np, "#lines", &num_lines);
+	if (rc) {
+		pr_err("Opal node 'oppanel', '#lines' property not found\n");
+		goto np_put;
+	}
+	buf_len = line_len * num_lines;
+
+	/* Allocate Memory */
+	buf = kcalloc(buf_len, sizeof(*buf), GFP_KERNEL);
+	if (!buf) {
+		rc = -ENOMEM;
+		goto np_put;
+	}
+	lines = kcalloc(num_lines, sizeof(*lines), GFP_KERNEL);
+	if (!lines) {
+		rc = -ENOMEM;
+		goto free_buf;
+	}
+
+	/* Setup lines structure */
+	for (i = 0; i < num_lines; i++) {
+		lines[i].line_len = 0;
+		lines[i].line = cpu_to_be64(__pa(&buf[i * line_len]));
+	}
+	cursor = last_line_index();
+
+	/* Create platform device */
+	pdev = of_platform_device_create(np, NULL, NULL);
+	rc = PTR_ERR_OR_ZERO(pdev);
+	if (rc)
+		goto free_lines;
+
+	/* We still need to node_put on success */
+	rc = 0;
+	goto np_put;
+
+free_lines:
+	kfree(lines);
+free_buf:
+	kfree(buf);
+np_put:
+	of_node_put(np);
+	return rc;
+}
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 5fcb797..95f6885 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -181,6 +181,7 @@ config IBM_BSR
 config POWERNV_OP_PANEL
 	tristate "IBM POWERNV Operator Panel Display support"
 	depends on PPC_POWERNV
+	select POWERNV_OP_PANEL_BASE
 	help
 	  If you say Y here, a special character device node, /dev/op_panel,
 	  will be created which exposes the operator panel display on IBM
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [RFC] [PATCH 2/3] powernv/setup: Initialise opal_oppanel and display information on boot
  2016-08-02  7:48 [RFC] [PATCH 1/3] powernv/opal: Introduce new opal_oppanel interface to expose the op_panel Suraj Jitindar Singh
@ 2016-08-02  7:48 ` Suraj Jitindar Singh
  2016-08-02  7:48 ` [RFC] [PATCH 3/3] powernv/oppanel: Update op_panel module to utilise opal_oppanel interface Suraj Jitindar Singh
  1 sibling, 0 replies; 3+ messages in thread
From: Suraj Jitindar Singh @ 2016-08-02  7:48 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: sjitindarsingh

Now that we have the ability to access the operator panel display from
within the kernel print out some platform information on boot.

Update the opal initialisation function to call the init function for the
new oppanel interface, this also removes the need to explicitly create the
platform device as this is now handled in the oppanel init function.

Now that we are able to access the operator panel display from the kernel
update the powernv platform progress function to write to the display.
Add a function to print some platform information to the display on
boot.

Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
---
 arch/powerpc/platforms/powernv/opal.c  |  8 +++++---
 arch/powerpc/platforms/powernv/setup.c | 27 +++++++++++++++++++++++++++
 2 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index 228751a..62ea5e5 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -705,6 +705,11 @@ static int __init opal_init(void)
 	/* Initialise OPAL asynchronous completion interface */
 	opal_async_comp_init();
 
+#if defined(CONFIG_POWERNV_OP_PANEL) || defined(CONFIG_POWERNV_OP_PANEL_MODULE)
+	/* Initialise OPAL oppanel interface */
+	opal_oppanel_init();
+#endif /* CONFIG_POWERNV_OP_PANEL */
+
 	/* Initialise OPAL sensor interface */
 	opal_sensor_init();
 
@@ -751,9 +756,6 @@ static int __init opal_init(void)
 	opal_pdev_init(opal_node, "ibm,opal-flash");
 	opal_pdev_init(opal_node, "ibm,opal-prd");
 
-	/* Initialise platform device: oppanel interface */
-	opal_pdev_init(opal_node, "ibm,opal-oppanel");
-
 	/* Initialise OPAL kmsg dumper for flushing console on panic */
 	opal_kmsg_init();
 
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index ee6430b..0f0e557 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -27,6 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/bug.h>
 #include <linux/pci.h>
+#include <linux/utsname.h>
 #include <linux/cpufreq.h>
 
 #include <asm/machdep.h>
@@ -58,6 +59,29 @@ static void __init pnv_setup_arch(void)
 	/* XXX PMCS */
 }
 
+static int __init pnv_late_init(void)
+{
+#if defined(CONFIG_POWERNV_OP_PANEL) || defined(CONFIG_POWERNV_OP_PANEL_MODULE)
+	char msg[17] = {'\0'};
+#endif /* CONFIG_POWERNV_OP_PANEL */
+	/* Manually leave the kernel version on the panel */
+#ifdef __BIG_ENDIAN__
+	ppc_md.progress("Linux ppc64\n", 0);
+#else
+	ppc_md.progress("Linux ppc64le\n", 0);
+#endif
+#if defined(CONFIG_POWERNV_OP_PANEL) || defined(CONFIG_POWERNV_OP_PANEL_MODULE)
+	/* Limit what we print to 16 chars so the previous line remains */
+	memcpy(msg, init_utsname()->release, 16);
+	ppc_md.progress(msg, 0);
+#else
+	ppc_md.progress(init_utsname()->release, 0);
+#endif /* CONFIG_POWERNV_OP_PANEL */
+
+	return 0;
+}
+machine_late_initcall(powernv, pnv_late_init);
+
 static void __init pnv_init_early(void)
 {
 	/*
@@ -159,6 +183,9 @@ static void __noreturn pnv_halt(void)
 
 static void pnv_progress(char *s, unsigned short hex)
 {
+#if defined(CONFIG_POWERNV_OP_PANEL) || defined(CONFIG_POWERNV_OP_PANEL_MODULE)
+	opal_oppanel_write(s);
+#endif /* CONFIG_POWERNV_OP_PANEL */
 }
 
 static void pnv_shutdown(void)
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [RFC] [PATCH 3/3] powernv/oppanel: Update op_panel module to utilise opal_oppanel interface
  2016-08-02  7:48 [RFC] [PATCH 1/3] powernv/opal: Introduce new opal_oppanel interface to expose the op_panel Suraj Jitindar Singh
  2016-08-02  7:48 ` [RFC] [PATCH 2/3] powernv/setup: Initialise opal_oppanel and display information on boot Suraj Jitindar Singh
@ 2016-08-02  7:48 ` Suraj Jitindar Singh
  1 sibling, 0 replies; 3+ messages in thread
From: Suraj Jitindar Singh @ 2016-08-02  7:48 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: sjitindarsingh

The powernv_op_panel kernel module is used to expose the operator panel
display present on IBM PowerNV machines with FSPs through the char device
/dev/op_panel.

The new interface opal_oppanel which has been added to allow access to the
operator panel display from within the kernel duplicates a lot of the
module code. Thus update the powernv_op_panel kernel module to access the
display through the opal_oppanel interface.

Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
---
 drivers/char/powernv-op-panel.c | 153 ++++++++++++++--------------------------
 1 file changed, 51 insertions(+), 102 deletions(-)

diff --git a/drivers/char/powernv-op-panel.c b/drivers/char/powernv-op-panel.c
index a45dabc..2d22cc4 100644
--- a/drivers/char/powernv-op-panel.c
+++ b/drivers/char/powernv-op-panel.c
@@ -17,7 +17,7 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/miscdevice.h>
-
+#include <linux/uaccess.h>
 #include <asm/opal.h>
 
 /*
@@ -28,106 +28,87 @@
  * operator panel.
  */
 
-static DEFINE_MUTEX(oppanel_mutex);
+static DEFINE_MUTEX(oppanel_driver_mutex);
 
-static u32		num_lines, oppanel_size;
-static oppanel_line_t	*oppanel_lines;
-static char		*oppanel_data;
-
-static loff_t oppanel_llseek(struct file *filp, loff_t offset, int whence)
-{
-	return fixed_size_llseek(filp, offset, whence, oppanel_size);
-}
+static u32 buf_size;
+char *oppanel_buf;
 
 static ssize_t oppanel_read(struct file *filp, char __user *userbuf, size_t len,
 			    loff_t *f_pos)
 {
-	return simple_read_from_buffer(userbuf, len, f_pos, oppanel_data,
-			oppanel_size);
-}
+	ssize_t ret;
 
-static int __op_panel_update_display(void)
-{
-	struct opal_msg msg;
-	int rc, token;
-
-	token = opal_async_get_token_interruptible();
-	if (token < 0) {
-		if (token != -ERESTARTSYS)
-			pr_debug("Couldn't get OPAL async token [token=%d]\n",
-				token);
-		return token;
-	}
+	if (*f_pos < 0)
+		return -EINVAL;
+	if (*f_pos >= (buf_size - 1) || !len)
+		return 0;
+	if (len > (buf_size - 1 - *f_pos))
+		len = buf_size - 1 - *f_pos;
 
-	rc = opal_write_oppanel_async(token, oppanel_lines, num_lines);
-	switch (rc) {
-	case OPAL_ASYNC_COMPLETION:
-		rc = opal_async_wait_response(token, &msg);
-		if (rc) {
-			pr_debug("Failed to wait for async response [rc=%d]\n",
-				rc);
-			break;
-		}
-		rc = opal_get_async_rc(msg);
-		if (rc != OPAL_SUCCESS) {
-			pr_debug("OPAL async call returned failed [rc=%d]\n",
-				rc);
-			break;
-		}
-	case OPAL_SUCCESS:
-		break;
-	default:
-		pr_debug("OPAL write op-panel call failed [rc=%d]\n", rc);
-	}
+	opal_oppanel_read(oppanel_buf);
+	ret = len - copy_to_user(userbuf, &oppanel_buf[*f_pos], len);
 
-	opal_async_release_token(token);
-	return rc;
+	/* Nothing was copied */
+	if (!ret)
+		return -EFAULT;
+
+	*f_pos += ret;
+
+	return ret;
 }
 
 static ssize_t oppanel_write(struct file *filp, const char __user *userbuf,
 			     size_t len, loff_t *f_pos)
 {
-	loff_t f_pos_prev = *f_pos;
 	ssize_t ret;
 	int rc;
 
-	if (!*f_pos)
-		memset(oppanel_data, ' ', oppanel_size);
-	else if (*f_pos >= oppanel_size)
-		return -EFBIG;
+	if (*f_pos < 0)
+		return -EINVAL;
+	if (!len)
+		return 0;
+	if (len >= buf_size)
+		len = buf_size - 1;
 
-	ret = simple_write_to_buffer(oppanel_data, oppanel_size, f_pos, userbuf,
-			len);
+	ret = len - copy_from_user(oppanel_buf, userbuf, len);
+	/* Something was copied */
 	if (ret > 0) {
-		rc = __op_panel_update_display();
+		/* Add null terminator */
+		oppanel_buf[ret] = '\0';
+		rc = opal_oppanel_write(oppanel_buf);
 		if (rc != OPAL_SUCCESS) {
 			pr_err_ratelimited("OPAL call failed to write to op panel display [rc=%d]\n",
 				rc);
-			*f_pos = f_pos_prev;
-			return -EIO;
+			return rc;
 		}
-	}
+	/* Nothing was copied */
+	} else if (!ret)
+		return -EFAULT;
+
+	*f_pos += ret;
+
 	return ret;
 }
 
 static int oppanel_open(struct inode *inode, struct file *filp)
 {
-	if (!mutex_trylock(&oppanel_mutex)) {
+	if (!mutex_trylock(&oppanel_driver_mutex)) {
 		pr_debug("Device Busy\n");
 		return -EBUSY;
 	}
+	nonseekable_open(inode, filp);
 	return 0;
 }
 
 static int oppanel_release(struct inode *inode, struct file *filp)
 {
-	mutex_unlock(&oppanel_mutex);
+	mutex_unlock(&oppanel_driver_mutex);
 	return 0;
 }
 
 static const struct file_operations oppanel_fops = {
 	.owner		= THIS_MODULE,
-	.llseek		= oppanel_llseek,
+	.llseek		= no_llseek,
 	.read		= oppanel_read,
 	.write		= oppanel_write,
 	.open		= oppanel_open,
@@ -142,62 +123,30 @@ static struct miscdevice oppanel_dev = {
 
 static int oppanel_probe(struct platform_device *pdev)
 {
-	struct device_node *np = pdev->dev.of_node;
-	u32 line_len;
-	int rc, i;
-
-	rc = of_property_read_u32(np, "#length", &line_len);
-	if (rc) {
-		pr_err_ratelimited("Operator panel length property not found\n");
-		return rc;
-	}
-	rc = of_property_read_u32(np, "#lines", &num_lines);
-	if (rc) {
-		pr_err_ratelimited("Operator panel lines property not found\n");
-		return rc;
-	}
-	oppanel_size = line_len * num_lines;
+	int rc;
 
-	pr_devel("Operator panel of size %u found with %u lines of length %u\n",
-			oppanel_size, num_lines, line_len);
+	opal_oppanel_get_size(&buf_size);
+	/* Add space for a null terminator */
+	buf_size += 1;
 
-	oppanel_data = kcalloc(oppanel_size, sizeof(*oppanel_data), GFP_KERNEL);
-	if (!oppanel_data)
+	oppanel_buf = kcalloc(buf_size, sizeof(*oppanel_buf), GFP_KERNEL);
+	if (!oppanel_buf)
 		return -ENOMEM;
-
-	oppanel_lines = kcalloc(num_lines, sizeof(oppanel_line_t), GFP_KERNEL);
-	if (!oppanel_lines) {
-		rc = -ENOMEM;
-		goto free_oppanel_data;
-	}
-
-	memset(oppanel_data, ' ', oppanel_size);
-	for (i = 0; i < num_lines; i++) {
-		oppanel_lines[i].line_len = cpu_to_be64(line_len);
-		oppanel_lines[i].line = cpu_to_be64(__pa(&oppanel_data[i *
-						line_len]));
-	}
+	memset(oppanel_buf, '\0', buf_size);
 
 	rc = misc_register(&oppanel_dev);
 	if (rc) {
 		pr_err_ratelimited("Failed to register as misc device\n");
-		goto free_oppanel;
+		kfree(oppanel_buf);
 	}
 
-	return 0;
-
-free_oppanel:
-	kfree(oppanel_lines);
-free_oppanel_data:
-	kfree(oppanel_data);
 	return rc;
 }
 
 static int oppanel_remove(struct platform_device *pdev)
 {
 	misc_deregister(&oppanel_dev);
-	kfree(oppanel_lines);
-	kfree(oppanel_data);
+	kfree(oppanel_buf);
 	return 0;
 }
 
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-08-02  7:48 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-02  7:48 [RFC] [PATCH 1/3] powernv/opal: Introduce new opal_oppanel interface to expose the op_panel Suraj Jitindar Singh
2016-08-02  7:48 ` [RFC] [PATCH 2/3] powernv/setup: Initialise opal_oppanel and display information on boot Suraj Jitindar Singh
2016-08-02  7:48 ` [RFC] [PATCH 3/3] powernv/oppanel: Update op_panel module to utilise opal_oppanel interface Suraj Jitindar Singh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).