~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/tty/n_tracerouter.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  n_tracerouter.c - Trace data router through tty space
 
3
 *
 
4
 *  Copyright (C) Intel 2011
 
5
 *
 
6
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
7
 *
 
8
 *  This program is free software; you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU General Public License version 2
 
10
 *  as published by the Free Software Foundation.
 
11
 *
 
12
 *  This program is distributed in the hope that it will be useful,
 
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 *  GNU General Public License for more details.
 
16
 *
 
17
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
18
 *
 
19
 * This trace router uses the Linux line discipline framework to route
 
20
 * trace data coming from a HW Modem to a PTI (Parallel Trace Module) port.
 
21
 * The solution is not specific to a HW modem and this line disciple can
 
22
 * be used to route any stream of data in kernel space.
 
23
 * This is part of a solution for the P1149.7, compact JTAG, standard.
 
24
 */
 
25
 
 
26
#include <linux/init.h>
 
27
#include <linux/kernel.h>
 
28
#include <linux/module.h>
 
29
#include <linux/types.h>
 
30
#include <linux/ioctl.h>
 
31
#include <linux/tty.h>
 
32
#include <linux/tty_ldisc.h>
 
33
#include <linux/errno.h>
 
34
#include <linux/string.h>
 
35
#include <linux/mutex.h>
 
36
#include <linux/slab.h>
 
37
#include <asm-generic/bug.h>
 
38
#include "n_tracesink.h"
 
39
 
 
40
/*
 
41
 * Other ldisc drivers use 65536 which basically means,
 
42
 * 'I can always accept 64k' and flow control is off.
 
43
 * This number is deemed appropriate for this driver.
 
44
 */
 
45
#define RECEIVE_ROOM    65536
 
46
#define DRIVERNAME      "n_tracerouter"
 
47
 
 
48
/*
 
49
 * struct to hold private configuration data for this ldisc.
 
50
 * opencalled is used to hold if this ldisc has been opened.
 
51
 * kref_tty holds the tty reference the ldisc sits on top of.
 
52
 */
 
53
struct tracerouter_data {
 
54
        u8 opencalled;
 
55
        struct tty_struct *kref_tty;
 
56
};
 
57
static struct tracerouter_data *tr_data;
 
58
 
 
59
/* lock for when tty reference is being used */
 
60
static DEFINE_MUTEX(routelock);
 
61
 
 
62
/**
 
63
 * n_tracerouter_open() - Called when a tty is opened by a SW entity.
 
64
 * @tty: terminal device to the ldisc.
 
65
 *
 
66
 * Return:
 
67
 *      0 for success.
 
68
 *
 
69
 * Caveats: This should only be opened one time per SW entity.
 
70
 */
 
71
static int n_tracerouter_open(struct tty_struct *tty)
 
72
{
 
73
        int retval = -EEXIST;
 
74
 
 
75
        mutex_lock(&routelock);
 
76
        if (tr_data->opencalled == 0) {
 
77
 
 
78
                tr_data->kref_tty = tty_kref_get(tty);
 
79
                if (tr_data->kref_tty == NULL) {
 
80
                        retval = -EFAULT;
 
81
                } else {
 
82
                        tr_data->opencalled = 1;
 
83
                        tty->disc_data      = tr_data;
 
84
                        tty->receive_room   = RECEIVE_ROOM;
 
85
                        tty_driver_flush_buffer(tty);
 
86
                        retval = 0;
 
87
                }
 
88
        }
 
89
        mutex_unlock(&routelock);
 
90
        return retval;
 
91
}
 
92
 
 
93
/**
 
94
 * n_tracerouter_close() - close connection
 
95
 * @tty: terminal device to the ldisc.
 
96
 *
 
97
 * Called when a software entity wants to close a connection.
 
98
 */
 
99
static void n_tracerouter_close(struct tty_struct *tty)
 
100
{
 
101
        struct tracerouter_data *tptr = tty->disc_data;
 
102
 
 
103
        mutex_lock(&routelock);
 
104
        WARN_ON(tptr->kref_tty != tr_data->kref_tty);
 
105
        tty_driver_flush_buffer(tty);
 
106
        tty_kref_put(tr_data->kref_tty);
 
107
        tr_data->kref_tty = NULL;
 
108
        tr_data->opencalled = 0;
 
109
        tty->disc_data = NULL;
 
110
        mutex_unlock(&routelock);
 
111
}
 
112
 
 
113
/**
 
114
 * n_tracerouter_read() - read request from user space
 
115
 * @tty:  terminal device passed into the ldisc.
 
116
 * @file: pointer to open file object.
 
117
 * @buf:  pointer to the data buffer that gets eventually returned.
 
118
 * @nr:   number of bytes of the data buffer that is returned.
 
119
 *
 
120
 * function that allows read() functionality in userspace. By default if this
 
121
 * is not implemented it returns -EIO. This module is functioning like a
 
122
 * router via n_tracerouter_receivebuf(), and there is no real requirement
 
123
 * to implement this function. However, an error return value other than
 
124
 * -EIO should be used just to show that there was an intent not to have
 
125
 * this function implemented.  Return value based on read() man pages.
 
126
 *
 
127
 * Return:
 
128
 *       -EINVAL
 
129
 */
 
130
static ssize_t n_tracerouter_read(struct tty_struct *tty, struct file *file,
 
131
                                  unsigned char __user *buf, size_t nr) {
 
132
        return -EINVAL;
 
133
}
 
134
 
 
135
/**
 
136
 * n_tracerouter_write() - Function that allows write() in userspace.
 
137
 * @tty:  terminal device passed into the ldisc.
 
138
 * @file: pointer to open file object.
 
139
 * @buf:  pointer to the data buffer that gets eventually returned.
 
140
 * @nr:   number of bytes of the data buffer that is returned.
 
141
 *
 
142
 * By default if this is not implemented, it returns -EIO.
 
143
 * This should not be implemented, ever, because
 
144
 * 1. this driver is functioning like a router via
 
145
 *    n_tracerouter_receivebuf()
 
146
 * 2. No writes to HW will ever go through this line discpline driver.
 
147
 * However, an error return value other than -EIO should be used
 
148
 * just to show that there was an intent not to have this function
 
149
 * implemented.  Return value based on write() man pages.
 
150
 *
 
151
 * Return:
 
152
 *      -EINVAL
 
153
 */
 
154
static ssize_t n_tracerouter_write(struct tty_struct *tty, struct file *file,
 
155
                                   const unsigned char *buf, size_t nr) {
 
156
        return -EINVAL;
 
157
}
 
158
 
 
159
/**
 
160
 * n_tracerouter_receivebuf() - Routing function for driver.
 
161
 * @tty: terminal device passed into the ldisc.  It's assumed
 
162
 *       tty will never be NULL.
 
163
 * @cp:  buffer, block of characters to be eventually read by
 
164
 *       someone, somewhere (user read() call or some kernel function).
 
165
 * @fp:  flag buffer.
 
166
 * @count: number of characters (aka, bytes) in cp.
 
167
 *
 
168
 * This function takes the input buffer, cp, and passes it to
 
169
 * an external API function for processing.
 
170
 */
 
171
static void n_tracerouter_receivebuf(struct tty_struct *tty,
 
172
                                        const unsigned char *cp,
 
173
                                        char *fp, int count)
 
174
{
 
175
        mutex_lock(&routelock);
 
176
        n_tracesink_datadrain((u8 *) cp, count);
 
177
        mutex_unlock(&routelock);
 
178
}
 
179
 
 
180
/*
 
181
 * Flush buffer is not impelemented as the ldisc has no internal buffering
 
182
 * so the tty_driver_flush_buffer() is sufficient for this driver's needs.
 
183
 */
 
184
 
 
185
static struct tty_ldisc_ops tty_ptirouter_ldisc = {
 
186
        .owner          = THIS_MODULE,
 
187
        .magic          = TTY_LDISC_MAGIC,
 
188
        .name           = DRIVERNAME,
 
189
        .open           = n_tracerouter_open,
 
190
        .close          = n_tracerouter_close,
 
191
        .read           = n_tracerouter_read,
 
192
        .write          = n_tracerouter_write,
 
193
        .receive_buf    = n_tracerouter_receivebuf
 
194
};
 
195
 
 
196
/**
 
197
 * n_tracerouter_init - module initialisation
 
198
 *
 
199
 * Registers this module as a line discipline driver.
 
200
 *
 
201
 * Return:
 
202
 *      0 for success, any other value error.
 
203
 */
 
204
static int __init n_tracerouter_init(void)
 
205
{
 
206
        int retval;
 
207
 
 
208
        tr_data = kzalloc(sizeof(struct tracerouter_data), GFP_KERNEL);
 
209
        if (tr_data == NULL)
 
210
                return -ENOMEM;
 
211
 
 
212
 
 
213
        /* Note N_TRACEROUTER is defined in linux/tty.h */
 
214
        retval = tty_register_ldisc(N_TRACEROUTER, &tty_ptirouter_ldisc);
 
215
        if (retval < 0) {
 
216
                pr_err("%s: Registration failed: %d\n", __func__, retval);
 
217
                kfree(tr_data);
 
218
        }
 
219
        return retval;
 
220
}
 
221
 
 
222
/**
 
223
 * n_tracerouter_exit - module unload
 
224
 *
 
225
 * Removes this module as a line discipline driver.
 
226
 */
 
227
static void __exit n_tracerouter_exit(void)
 
228
{
 
229
        int retval = tty_unregister_ldisc(N_TRACEROUTER);
 
230
 
 
231
        if (retval < 0)
 
232
                pr_err("%s: Unregistration failed: %d\n", __func__,  retval);
 
233
        else
 
234
                kfree(tr_data);
 
235
}
 
236
 
 
237
module_init(n_tracerouter_init);
 
238
module_exit(n_tracerouter_exit);
 
239
 
 
240
MODULE_LICENSE("GPL");
 
241
MODULE_AUTHOR("Jay Freyensee");
 
242
MODULE_ALIAS_LDISC(N_TRACEROUTER);
 
243
MODULE_DESCRIPTION("Trace router ldisc driver");