>From 459a1f682d73988a1b4fb247b4db0ed8c3b7a095 Mon Sep 17 00:00:00 2001 From: Ken Mills <[email protected]> Date: Mon, 18 Oct 2010 18:48:27 -0700 Subject: [PATCH 4/4] Added new function to generate a PTI control header.
This header is sent with every PTI message and is used by the Mobile Platform Trace Analyzer. Signed-off-by: Ken Mills <[email protected]> --- drivers/misc/pti.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 70 insertions(+), 6 deletions(-) diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c index 8c0dff4..f9f33a2 100644 --- a/drivers/misc/pti.c +++ b/drivers/misc/pti.c @@ -28,8 +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> @@ -44,10 +46,12 @@ #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 72 /* base OS master ID address */ +#define OS_BASE_ID 74 /* base OS master ID address */ #define APP_BASE_ID 80 /* base App master ID address */ -#define USER_COPY_SIZE 8192 /* 8Kb buffer to copy data from user space */ +#define USER_COPY_SIZE 8192 /* 8Kb buffer to copy data from user space */ +#define CONTROL_FRAME_LEN 32 /* PTI control frame maximum size */ struct pti_tty { struct masterchannel *mc; @@ -76,6 +80,7 @@ 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 */ @@ -146,6 +151,61 @@ 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)]; + u8 control_frame[CONTROL_FRAME_LEN]; + + if (!in_interrupt()) + get_task_comm(comm, current); + else + strcpy(comm, "Interrupt"); + + 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: @@ -187,6 +247,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; } @@ -381,9 +443,10 @@ static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty) { int idx = tty->index; struct pti_tty *pti_tty_data; - int ret = tty_init_termios(tty); + pr_debug("%s(%d): Called.\n", __func__, __LINE__); + if (ret == 0) { tty_driver_kref_get(driver); tty->count++; @@ -491,8 +554,7 @@ int pti_char_release(struct inode *inode, struct file *filp) * @param data: trace data to be written. * @param len: # of byte to write. * @param ppose: Not used in this function implementation. - * @return int : # of bytes written, or error. -EMSGSIZE is - * returned if length is beyond 8k. + * @return int : # of bytes written, or error. */ ssize_t pti_char_write(struct file *filp, const char *data, size_t len, loff_t *ppose) @@ -567,7 +629,7 @@ static void pti_console_write(struct console *c, const char *buf, unsigned len) mc.channel = pti_console_channel; pti_console_channel = (pti_console_channel + 1) & 0x7f; - pti_write_to_aperture(&mc, (u8 *)buf, len); + pti_write_full_frame_to_aperture(&mc, buf, len); } static struct tty_driver *pti_console_device(struct console *c, int *index) @@ -579,6 +641,7 @@ static struct tty_driver *pti_console_device(struct console *c, int *index) static int pti_console_setup(struct console *c, char *opts) { pti_console_channel = 0; + pti_control_channel = 0; return 0; } @@ -640,6 +703,7 @@ 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. -- 1.7.0.4
From 459a1f682d73988a1b4fb247b4db0ed8c3b7a095 Mon Sep 17 00:00:00 2001 From: Ken Mills <[email protected]> Date: Mon, 18 Oct 2010 18:48:27 -0700 Subject: [PATCH 4/4] Added new function to generate a PTI control header. This header is sent with every PTI message and is used by the Mobile Platform Trace Analyzer. Signed-off-by: Ken Mills <[email protected]> --- drivers/misc/pti.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 70 insertions(+), 6 deletions(-) diff --git a/drivers/misc/pti.c b/drivers/misc/pti.c index 8c0dff4..f9f33a2 100644 --- a/drivers/misc/pti.c +++ b/drivers/misc/pti.c @@ -28,8 +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> @@ -44,10 +46,12 @@ #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 72 /* base OS master ID address */ +#define OS_BASE_ID 74 /* base OS master ID address */ #define APP_BASE_ID 80 /* base App master ID address */ -#define USER_COPY_SIZE 8192 /* 8Kb buffer to copy data from user space */ +#define USER_COPY_SIZE 8192 /* 8Kb buffer to copy data from user space */ +#define CONTROL_FRAME_LEN 32 /* PTI control frame maximum size */ struct pti_tty { struct masterchannel *mc; @@ -76,6 +80,7 @@ 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 */ @@ -146,6 +151,61 @@ 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)]; + u8 control_frame[CONTROL_FRAME_LEN]; + + if (!in_interrupt()) + get_task_comm(comm, current); + else + strcpy(comm, "Interrupt"); + + 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: @@ -187,6 +247,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; } @@ -381,9 +443,10 @@ static int pti_tty_install(struct tty_driver *driver, struct tty_struct *tty) { int idx = tty->index; struct pti_tty *pti_tty_data; - int ret = tty_init_termios(tty); + pr_debug("%s(%d): Called.\n", __func__, __LINE__); + if (ret == 0) { tty_driver_kref_get(driver); tty->count++; @@ -491,8 +554,7 @@ int pti_char_release(struct inode *inode, struct file *filp) * @param data: trace data to be written. * @param len: # of byte to write. * @param ppose: Not used in this function implementation. - * @return int : # of bytes written, or error. -EMSGSIZE is - * returned if length is beyond 8k. + * @return int : # of bytes written, or error. */ ssize_t pti_char_write(struct file *filp, const char *data, size_t len, loff_t *ppose) @@ -567,7 +629,7 @@ static void pti_console_write(struct console *c, const char *buf, unsigned len) mc.channel = pti_console_channel; pti_console_channel = (pti_console_channel + 1) & 0x7f; - pti_write_to_aperture(&mc, (u8 *)buf, len); + pti_write_full_frame_to_aperture(&mc, buf, len); } static struct tty_driver *pti_console_device(struct console *c, int *index) @@ -579,6 +641,7 @@ static struct tty_driver *pti_console_device(struct console *c, int *index) static int pti_console_setup(struct console *c, char *opts) { pti_console_channel = 0; + pti_control_channel = 0; return 0; } @@ -640,6 +703,7 @@ 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. -- 1.7.0.4
_______________________________________________ Meego-kernel mailing list [email protected] http://lists.meego.com/listinfo/meego-kernel
