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
