These patches were accepted by Alan and merged into his tree.

>From 7d71a5f4f89f02423ee11eaefe27d1ed356a02fe Mon Sep 17 00:00:00 2001
From: Ken Mills <[email protected]>
Date: Tue, 19 Oct 2010 18:17:25 -0700
Subject: [PATCH 1/2] Added two new functions
 1. Console device to capture kernel printk messages.
 2. Function to generate a PTI control header that is used by the
    Mobile Platform Trace Analyzer.

Signed-off-by: Ken Mills <[email protected]>
---
 drivers/misc/pti.c |  174 ++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 161 insertions(+), 13 deletions(-)

diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c
index f1b5e4b..696a59d 100644
--- a/drivers/misc/pti.c
+++ b/drivers/misc/pti.c
@@ -28,7 +28,10 @@
  */
 
 #include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/console.h>
 #include <linux/kernel.h>
+#include <linux/hardirq.h>
 #include <linux/module.h>
 #include <linux/tty.h>
 #include <linux/tty_driver.h>
@@ -37,14 +40,17 @@
 #include <linux/miscdevice.h>
 #include <linux/pti.h>
 
-#define DRIVERNAME                     "pti"
-#define PCINAME                                "pciPTI"
-#define TTYNAME                                "ttyPTI"
-#define CHARNAME                       "pti"
-#define MAX_APP_IDS                    256
-#define MAX_OS_IDS                     128
-#define OS_BASE_ID                     72   /* base OS master ID address */
-#define APP_BASE_ID                    80   /* base App master ID address */
+#define DRIVERNAME     "pti"
+#define PCINAME                "pciPTI"
+#define TTYNAME                "ttyPTI"
+#define CHARNAME       "pti"
+#define MAX_APP_IDS    256
+#define MAX_OS_IDS     128
+#define CONTROL_ID     72   /* control master ID address */
+#define CONSOLE_ID     73   /* console master ID address */
+#define OS_BASE_ID     74   /* base OS master ID address */
+#define APP_BASE_ID    80   /* base App master ID address */
+#define CONTROL_FRAME_LEN      32 /* PTI control frame maximum size */
 
 struct pti_tty {
        struct masterchannel *mc;
@@ -72,6 +78,8 @@ static struct tty_driver *pti_tty_driver;
 
 static struct pti_dev *drv_data;
 
+static unsigned int pti_console_channel;
+static unsigned int pti_control_channel;
 
 #define DTS 0x30               /* offset for last dword of a PTI message */
 
@@ -159,6 +167,63 @@ static void pti_write_to_aperture(struct masterchannel 
*mc, u8 *buf, int len)
 }
 
 /**
+ *  pti_control_frame_built_and_sent() - control frame build and send function.
+ *  @mc: The master / channel structure on which the function built a control
+ *  frame.
+ *
+ *  To be able to post process the PTI contents on host side, a control frame
+ *  is added before sending any PTI content. So the host side knows on
+ *  each PTI frame the name of the thread using a dedicated master / channel.
+ *  This function builds this frame and sends it to a master ID CONTROL_ID.
+ *  The overhead is only 32 bytes since the driver only writes to HW
+ *  in 32 byte chunks.
+ */
+
+static void pti_control_frame_built_and_sent(struct masterchannel *mc)
+{
+       struct masterchannel mccontrol = {.master = CONTROL_ID, .channel = 0};
+       const char *control_format = "%3d %3d %s";
+
+       char comm[sizeof(current->comm) + 1];
+       u8 control_frame[CONTROL_FRAME_LEN];
+
+       if (!in_interrupt())
+               get_task_comm(comm, current);
+       else
+               strcpy(comm, "Interrupt");
+               
+       /* Ensure our buffer is zero terminated */
+       comm[sizeof(current->comm)] = 0;
+
+       mccontrol.channel = pti_control_channel;
+       pti_control_channel = (pti_control_channel + 1) & 0x7f;
+
+       snprintf(control_frame, CONTROL_FRAME_LEN, control_format, mc->master,
+               mc->channel, comm);
+       pti_write_to_aperture(&mccontrol, control_frame, strlen(control_frame));
+}
+
+/**
+ *  pti_write_full_frame_to_aperture() - high level function to write to PTI
+ *  @mc: The 'aperture'. It's part of a write address that holds
+ *       a master and channel ID.
+ *  @buf: Data being written to the HW that will ultimately be seen
+ *        in a debugging tool (Fido, Lauterbach).
+ *  @len: Size of buffer.
+ *
+ *  All threads sending data (either console, user space application, ...)
+ *  are calling the high level function to write to PTI meaning that it is
+ *  possible to add a control frame before sending the content.
+ */
+static void pti_write_full_frame_to_aperture(struct masterchannel *mc,
+                                               const unsigned char *buf,
+                                               int len)
+{
+       pti_control_frame_built_and_sent(mc);
+       pti_write_to_aperture(mc, (u8 *)buf, len);
+}
+
+/**
  * getID(): Allocate a master and channel ID.
  *
  * @IDarray:
@@ -200,6 +265,8 @@ static struct masterchannel *getID(u8 *IDarray, int 
max_IDS, int baseID)
        IDarray[i] |= mask;
        mc->master = (i>>4)+baseID;
        mc->channel = ((i & 0xf)<<3) + j;
+       /* write new master Id / channel Id allocation to channel control */
+       pti_control_frame_built_and_sent(mc);
        return mc;
 }
 
@@ -301,9 +368,6 @@ void mipi_pti_writedata(struct masterchannel *mc, u8 *buf, 
int count)
 }
 EXPORT_SYMBOL(mipi_pti_writedata);
 
-static const struct tty_port_operations tty_port_ops = {
-};
-
 static void __devexit pti_pci_remove(struct pci_dev *pdev)
 {
        struct pti_dev *drv_data;
@@ -542,7 +606,7 @@ ssize_t pti_char_write(struct file *filp, const char *data, 
size_t len,
        return len;
 }
 
-const struct tty_operations pti_tty_driver_ops = {
+static const struct tty_operations pti_tty_driver_ops = {
        .open           = pti_tty_driver_open,
        .close          = pti_tty_driver_close,
        .write          = pti_tty_driver_write,
@@ -551,7 +615,7 @@ const struct tty_operations pti_tty_driver_ops = {
        .cleanup        = pti_tty_cleanup
 };
 
-const struct file_operations pti_char_driver_ops = {
+static const struct file_operations pti_char_driver_ops = {
        .owner          = THIS_MODULE,
        .open           = pti_char_open,
        .release        = pti_char_release,
@@ -564,6 +628,88 @@ static struct miscdevice pti_char_driver = {
        .fops           = &pti_char_driver_ops
 };
 
+static void pti_console_write(struct console *c, const char *buf, unsigned len)
+{
+       static struct masterchannel mc = {.master = CONSOLE_ID, .channel = 0};
+
+       mc.channel = pti_console_channel;
+       pti_console_channel = (pti_console_channel + 1) & 0x7f;
+
+       pti_write_full_frame_to_aperture(&mc, buf, len);
+}
+
+static struct tty_driver *pti_console_device(struct console *c, int *index)
+{
+       *index = c->index;
+       return pti_tty_driver;
+}
+
+static int pti_console_setup(struct console *c, char *opts)
+{
+       pti_console_channel = 0;
+       pti_control_channel = 0;
+       return 0;
+}
+
+/* pti_console struct, used to capture OS printk()'s and shift
+ * out to the PTI device for debugging.  This cannot be
+ * enabled upon boot because of the possibility of eating
+ * any serial console printk's (race condition discovered).
+ * The console should be enabled upon when the tty port is
+ * used for the first time.  Since the primary purpose for
+ * the tty port is to hook up syslog to it, the tty port
+ * will be open for a really long time.
+ */
+static struct console pti_console = {
+       .name           = TTYNAME,
+       .write          = pti_console_write,
+       .device         = pti_console_device,
+       .setup          = pti_console_setup,
+       .flags          = CON_PRINTBUFFER | CON_BOOT,
+       .index          = 0,
+};
+
+/**
+ * pti_port_activate(): Used to start/initialize any items upon
+ * first opening of tty_port().
+ *
+ * @param port
+ * @param tty
+ *
+ * @return int - Always returns 0.
+ *
+ * Notes: The primary purpose of the PTI tty port is to hook the
+ * syslog daemon to it; thus this port will be open for a very
+ * long time.
+ */
+int pti_port_activate(struct tty_port *port, struct tty_struct *tty)
+{
+       pr_debug("%s(%d): Called.\n", __func__, __LINE__);
+       console_start(&pti_console);
+       return 0;
+}
+
+/**
+ * pti_port_shutdown(): Used to stop/shutdown any items upon the
+ * last tty port close.
+ *
+ * @param port
+ *
+ * Notes: The primary purpose of the PTI tty port is to hook the
+ * syslog daemon to it; thus this port will be open for a very
+ * long time.
+ */
+void pti_port_shutdown(struct tty_port *port)
+{
+       pr_debug("%s(%d): Called.\n", __func__, __LINE__);
+       console_stop(&pti_console);
+}
+
+static const struct tty_port_operations tty_port_ops = {
+       .activate = pti_port_activate,
+       .shutdown = pti_port_shutdown,
+};
+
 /*
    Note the _probe() call sets everything up and ties the char and tty
    to successfully detecting the PTI device on the pci bus.
@@ -624,6 +770,8 @@ static int __devinit pti_pci_probe(struct pci_dev *pdev,
 
        tty_register_device(pti_tty_driver, 0, NULL);
 
+       register_console(&pti_console);
+
        retval = misc_register(&pti_char_driver);
        if (retval) {
                pr_err("%s(%d): CHAR registration failed of pti driver\n",
-- 
1.7.0.4
_______________________________________________
Meego-kernel mailing list
[email protected]
http://lists.meego.com/listinfo/meego-kernel

Reply via email to