aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-08-01 19:45:02 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-08-01 19:45:02 -0400
commit1871e845e564c4e17f561ec4e5e4bb6bb8578685 (patch)
treebcfb62936710321f48bee64153e05f313dc371d0 /arch/um/drivers
parenta6dc77254b3c3eb0307b372b77b861d5cd2ead08 (diff)
parentb070989aeb47ccdfe56d95e046bd317baa47f4fa (diff)
Merge branch 'for-linus-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml
Pull UML fixes from Richard Weinberger: "This patch set contains mostly fixes and cleanups. The UML tty driver uses now tty_port and is no longer broken like hell :-)" * 'for-linus-3.6-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: um: Add arch/x86/um to MAINTAINERS um: pass siginfo to guest process um: fix ubd_file_size for read-only files um: pull interrupt_end() into userspace() um: split syscall_trace(), pass pt_regs to it um: switch UPT_SET_RETURN_VALUE and regs_return_value to pt_regs um: set BLK_CGROUP=y in defconfig um: remove count_lock um: fully use tty_port um: Remove dead code um: remove line_ioctl() TTY: um/line, use tty from tty_port TTY: um/line, add tty_port
Diffstat (limited to 'arch/um/drivers')
-rw-r--r--arch/um/drivers/chan_kern.c4
-rw-r--r--arch/um/drivers/line.c218
-rw-r--r--arch/um/drivers/line.h12
-rw-r--r--arch/um/drivers/ssl.c42
-rw-r--r--arch/um/drivers/stdio_console.c21
-rw-r--r--arch/um/drivers/ubd_kern.c2
6 files changed, 88 insertions, 211 deletions
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 45e248c2f43c..87eebfe03c61 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -150,9 +150,11 @@ void chan_enable_winch(struct chan *chan, struct tty_struct *tty)
150static void line_timer_cb(struct work_struct *work) 150static void line_timer_cb(struct work_struct *work)
151{ 151{
152 struct line *line = container_of(work, struct line, task.work); 152 struct line *line = container_of(work, struct line, task.work);
153 struct tty_struct *tty = tty_port_tty_get(&line->port);
153 154
154 if (!line->throttled) 155 if (!line->throttled)
155 chan_interrupt(line, line->tty, line->driver->read_irq); 156 chan_interrupt(line, tty, line->driver->read_irq);
157 tty_kref_put(tty);
156} 158}
157 159
158int enable_chan(struct line *line) 160int enable_chan(struct line *line)
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index ac9d25c8dc01..bbaf2c59830a 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -19,9 +19,11 @@ static irqreturn_t line_interrupt(int irq, void *data)
19{ 19{
20 struct chan *chan = data; 20 struct chan *chan = data;
21 struct line *line = chan->line; 21 struct line *line = chan->line;
22 struct tty_struct *tty = tty_port_tty_get(&line->port);
22 23
23 if (line) 24 if (line)
24 chan_interrupt(line, line->tty, irq); 25 chan_interrupt(line, tty, irq);
26 tty_kref_put(tty);
25 return IRQ_HANDLED; 27 return IRQ_HANDLED;
26} 28}
27 29
@@ -219,92 +221,6 @@ void line_set_termios(struct tty_struct *tty, struct ktermios * old)
219 /* nothing */ 221 /* nothing */
220} 222}
221 223
222static const struct {
223 int cmd;
224 char *level;
225 char *name;
226} tty_ioctls[] = {
227 /* don't print these, they flood the log ... */
228 { TCGETS, NULL, "TCGETS" },
229 { TCSETS, NULL, "TCSETS" },
230 { TCSETSW, NULL, "TCSETSW" },
231 { TCFLSH, NULL, "TCFLSH" },
232 { TCSBRK, NULL, "TCSBRK" },
233
234 /* general tty stuff */
235 { TCSETSF, KERN_DEBUG, "TCSETSF" },
236 { TCGETA, KERN_DEBUG, "TCGETA" },
237 { TIOCMGET, KERN_DEBUG, "TIOCMGET" },
238 { TCSBRKP, KERN_DEBUG, "TCSBRKP" },
239 { TIOCMSET, KERN_DEBUG, "TIOCMSET" },
240
241 /* linux-specific ones */
242 { TIOCLINUX, KERN_INFO, "TIOCLINUX" },
243 { KDGKBMODE, KERN_INFO, "KDGKBMODE" },
244 { KDGKBTYPE, KERN_INFO, "KDGKBTYPE" },
245 { KDSIGACCEPT, KERN_INFO, "KDSIGACCEPT" },
246};
247
248int line_ioctl(struct tty_struct *tty, unsigned int cmd,
249 unsigned long arg)
250{
251 int ret;
252 int i;
253
254 ret = 0;
255 switch(cmd) {
256#ifdef TIOCGETP
257 case TIOCGETP:
258 case TIOCSETP:
259 case TIOCSETN:
260#endif
261#ifdef TIOCGETC
262 case TIOCGETC:
263 case TIOCSETC:
264#endif
265#ifdef TIOCGLTC
266 case TIOCGLTC:
267 case TIOCSLTC:
268#endif
269 /* Note: these are out of date as we now have TCGETS2 etc but this
270 whole lot should probably go away */
271 case TCGETS:
272 case TCSETSF:
273 case TCSETSW:
274 case TCSETS:
275 case TCGETA:
276 case TCSETAF:
277 case TCSETAW:
278 case TCSETA:
279 case TCXONC:
280 case TCFLSH:
281 case TIOCOUTQ:
282 case TIOCINQ:
283 case TIOCGLCKTRMIOS:
284 case TIOCSLCKTRMIOS:
285 case TIOCPKT:
286 case TIOCGSOFTCAR:
287 case TIOCSSOFTCAR:
288 return -ENOIOCTLCMD;
289#if 0
290 case TCwhatever:
291 /* do something */
292 break;
293#endif
294 default:
295 for (i = 0; i < ARRAY_SIZE(tty_ioctls); i++)
296 if (cmd == tty_ioctls[i].cmd)
297 break;
298 if (i == ARRAY_SIZE(tty_ioctls)) {
299 printk(KERN_ERR "%s: %s: unknown ioctl: 0x%x\n",
300 __func__, tty->name, cmd);
301 }
302 ret = -ENOIOCTLCMD;
303 break;
304 }
305 return ret;
306}
307
308void line_throttle(struct tty_struct *tty) 224void line_throttle(struct tty_struct *tty)
309{ 225{
310 struct line *line = tty->driver_data; 226 struct line *line = tty->driver_data;
@@ -333,7 +249,7 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
333{ 249{
334 struct chan *chan = data; 250 struct chan *chan = data;
335 struct line *line = chan->line; 251 struct line *line = chan->line;
336 struct tty_struct *tty = line->tty; 252 struct tty_struct *tty;
337 int err; 253 int err;
338 254
339 /* 255 /*
@@ -352,10 +268,13 @@ static irqreturn_t line_write_interrupt(int irq, void *data)
352 } 268 }
353 spin_unlock(&line->lock); 269 spin_unlock(&line->lock);
354 270
271 tty = tty_port_tty_get(&line->port);
355 if (tty == NULL) 272 if (tty == NULL)
356 return IRQ_NONE; 273 return IRQ_NONE;
357 274
358 tty_wakeup(tty); 275 tty_wakeup(tty);
276 tty_kref_put(tty);
277
359 return IRQ_HANDLED; 278 return IRQ_HANDLED;
360} 279}
361 280
@@ -377,43 +296,14 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
377 return err; 296 return err;
378} 297}
379 298
380/* 299static int line_activate(struct tty_port *port, struct tty_struct *tty)
381 * Normally, a driver like this can rely mostly on the tty layer
382 * locking, particularly when it comes to the driver structure.
383 * However, in this case, mconsole requests can come in "from the
384 * side", and race with opens and closes.
385 *
386 * mconsole config requests will want to be sure the device isn't in
387 * use, and get_config, open, and close will want a stable
388 * configuration. The checking and modification of the configuration
389 * is done under a spinlock. Checking whether the device is in use is
390 * line->tty->count > 1, also under the spinlock.
391 *
392 * line->count serves to decide whether the device should be enabled or
393 * disabled on the host. If it's equal to 0, then we are doing the
394 * first open or last close. Otherwise, open and close just return.
395 */
396
397int line_open(struct line *lines, struct tty_struct *tty)
398{ 300{
399 struct line *line = &lines[tty->index]; 301 int ret;
400 int err = -ENODEV; 302 struct line *line = tty->driver_data;
401
402 mutex_lock(&line->count_lock);
403 if (!line->valid)
404 goto out_unlock;
405
406 err = 0;
407 if (line->count++)
408 goto out_unlock;
409
410 BUG_ON(tty->driver_data);
411 tty->driver_data = line;
412 line->tty = tty;
413 303
414 err = enable_chan(line); 304 ret = enable_chan(line);
415 if (err) /* line_close() will be called by our caller */ 305 if (ret)
416 goto out_unlock; 306 return ret;
417 307
418 if (!line->sigio) { 308 if (!line->sigio) {
419 chan_enable_winch(line->chan_out, tty); 309 chan_enable_winch(line->chan_out, tty);
@@ -421,44 +311,60 @@ int line_open(struct line *lines, struct tty_struct *tty)
421 } 311 }
422 312
423 chan_window_size(line, &tty->winsize.ws_row, 313 chan_window_size(line, &tty->winsize.ws_row,
424 &tty->winsize.ws_col); 314 &tty->winsize.ws_col);
425out_unlock: 315
426 mutex_unlock(&line->count_lock); 316 return 0;
427 return err;
428} 317}
429 318
430static void unregister_winch(struct tty_struct *tty); 319static const struct tty_port_operations line_port_ops = {
320 .activate = line_activate,
321};
431 322
432void line_close(struct tty_struct *tty, struct file * filp) 323int line_open(struct tty_struct *tty, struct file *filp)
433{ 324{
434 struct line *line = tty->driver_data; 325 struct line *line = tty->driver_data;
435 326
436 /* 327 return tty_port_open(&line->port, tty, filp);
437 * If line_open fails (and tty->driver_data is never set), 328}
438 * tty_open will call line_close. So just return in this case.
439 */
440 if (line == NULL)
441 return;
442 329
443 /* We ignore the error anyway! */ 330int line_install(struct tty_driver *driver, struct tty_struct *tty,
444 flush_buffer(line); 331 struct line *line)
332{
333 int ret;
445 334
446 mutex_lock(&line->count_lock); 335 ret = tty_standard_install(driver, tty);
447 BUG_ON(!line->valid); 336 if (ret)
337 return ret;
448 338
449 if (--line->count) 339 tty->driver_data = line;
450 goto out_unlock;
451 340
452 line->tty = NULL; 341 return 0;
453 tty->driver_data = NULL; 342}
343
344static void unregister_winch(struct tty_struct *tty);
345
346void line_cleanup(struct tty_struct *tty)
347{
348 struct line *line = tty->driver_data;
454 349
455 if (line->sigio) { 350 if (line->sigio) {
456 unregister_winch(tty); 351 unregister_winch(tty);
457 line->sigio = 0; 352 line->sigio = 0;
458 } 353 }
354}
355
356void line_close(struct tty_struct *tty, struct file * filp)
357{
358 struct line *line = tty->driver_data;
459 359
460out_unlock: 360 tty_port_close(&line->port, tty, filp);
461 mutex_unlock(&line->count_lock); 361}
362
363void line_hangup(struct tty_struct *tty)
364{
365 struct line *line = tty->driver_data;
366
367 tty_port_hangup(&line->port);
462} 368}
463 369
464void close_lines(struct line *lines, int nlines) 370void close_lines(struct line *lines, int nlines)
@@ -476,9 +382,7 @@ int setup_one_line(struct line *lines, int n, char *init,
476 struct tty_driver *driver = line->driver->driver; 382 struct tty_driver *driver = line->driver->driver;
477 int err = -EINVAL; 383 int err = -EINVAL;
478 384
479 mutex_lock(&line->count_lock); 385 if (line->port.count) {
480
481 if (line->count) {
482 *error_out = "Device is already open"; 386 *error_out = "Device is already open";
483 goto out; 387 goto out;
484 } 388 }
@@ -519,7 +423,6 @@ int setup_one_line(struct line *lines, int n, char *init,
519 } 423 }
520 } 424 }
521out: 425out:
522 mutex_unlock(&line->count_lock);
523 return err; 426 return err;
524} 427}
525 428
@@ -607,13 +510,17 @@ int line_get_config(char *name, struct line *lines, unsigned int num, char *str,
607 510
608 line = &lines[dev]; 511 line = &lines[dev];
609 512
610 mutex_lock(&line->count_lock);
611 if (!line->valid) 513 if (!line->valid)
612 CONFIG_CHUNK(str, size, n, "none", 1); 514 CONFIG_CHUNK(str, size, n, "none", 1);
613 else if (line->tty == NULL) 515 else {
614 CONFIG_CHUNK(str, size, n, line->init_str, 1); 516 struct tty_struct *tty = tty_port_tty_get(&line->port);
615 else n = chan_config_string(line, str, size, error_out); 517 if (tty == NULL) {
616 mutex_unlock(&line->count_lock); 518 CONFIG_CHUNK(str, size, n, line->init_str, 1);
519 } else {
520 n = chan_config_string(line, str, size, error_out);
521 tty_kref_put(tty);
522 }
523 }
617 524
618 return n; 525 return n;
619} 526}
@@ -663,8 +570,9 @@ int register_lines(struct line_driver *line_driver,
663 driver->init_termios = tty_std_termios; 570 driver->init_termios = tty_std_termios;
664 571
665 for (i = 0; i < nlines; i++) { 572 for (i = 0; i < nlines; i++) {
573 tty_port_init(&lines[i].port);
574 lines[i].port.ops = &line_port_ops;
666 spin_lock_init(&lines[i].lock); 575 spin_lock_init(&lines[i].lock);
667 mutex_init(&lines[i].count_lock);
668 lines[i].driver = line_driver; 576 lines[i].driver = line_driver;
669 INIT_LIST_HEAD(&lines[i].chan_list); 577 INIT_LIST_HEAD(&lines[i].chan_list);
670 } 578 }
diff --git a/arch/um/drivers/line.h b/arch/um/drivers/line.h
index 0a1834719dba..bae95611e7ab 100644
--- a/arch/um/drivers/line.h
+++ b/arch/um/drivers/line.h
@@ -32,9 +32,7 @@ struct line_driver {
32}; 32};
33 33
34struct line { 34struct line {
35 struct tty_struct *tty; 35 struct tty_port port;
36 struct mutex count_lock;
37 unsigned long count;
38 int valid; 36 int valid;
39 37
40 char *init_str; 38 char *init_str;
@@ -59,7 +57,11 @@ struct line {
59}; 57};
60 58
61extern void line_close(struct tty_struct *tty, struct file * filp); 59extern void line_close(struct tty_struct *tty, struct file * filp);
62extern int line_open(struct line *lines, struct tty_struct *tty); 60extern int line_open(struct tty_struct *tty, struct file *filp);
61extern int line_install(struct tty_driver *driver, struct tty_struct *tty,
62 struct line *line);
63extern void line_cleanup(struct tty_struct *tty);
64extern void line_hangup(struct tty_struct *tty);
63extern int line_setup(char **conf, unsigned nlines, char **def, 65extern int line_setup(char **conf, unsigned nlines, char **def,
64 char *init, char *name); 66 char *init, char *name);
65extern int line_write(struct tty_struct *tty, const unsigned char *buf, 67extern int line_write(struct tty_struct *tty, const unsigned char *buf,
@@ -70,8 +72,6 @@ extern int line_chars_in_buffer(struct tty_struct *tty);
70extern void line_flush_buffer(struct tty_struct *tty); 72extern void line_flush_buffer(struct tty_struct *tty);
71extern void line_flush_chars(struct tty_struct *tty); 73extern void line_flush_chars(struct tty_struct *tty);
72extern int line_write_room(struct tty_struct *tty); 74extern int line_write_room(struct tty_struct *tty);
73extern int line_ioctl(struct tty_struct *tty, unsigned int cmd,
74 unsigned long arg);
75extern void line_throttle(struct tty_struct *tty); 75extern void line_throttle(struct tty_struct *tty);
76extern void line_unthrottle(struct tty_struct *tty); 76extern void line_unthrottle(struct tty_struct *tty);
77 77
diff --git a/arch/um/drivers/ssl.c b/arch/um/drivers/ssl.c
index e09801a1327b..7e86f0070123 100644
--- a/arch/um/drivers/ssl.c
+++ b/arch/um/drivers/ssl.c
@@ -87,40 +87,13 @@ static int ssl_remove(int n, char **error_out)
87 error_out); 87 error_out);
88} 88}
89 89
90static int ssl_open(struct tty_struct *tty, struct file *filp) 90static int ssl_install(struct tty_driver *driver, struct tty_struct *tty)
91{
92 int err = line_open(serial_lines, tty);
93
94 if (err)
95 printk(KERN_ERR "Failed to open serial line %d, err = %d\n",
96 tty->index, err);
97
98 return err;
99}
100
101#if 0
102static void ssl_flush_buffer(struct tty_struct *tty)
103{
104 return;
105}
106
107static void ssl_stop(struct tty_struct *tty)
108{
109 printk(KERN_ERR "Someone should implement ssl_stop\n");
110}
111
112static void ssl_start(struct tty_struct *tty)
113{
114 printk(KERN_ERR "Someone should implement ssl_start\n");
115}
116
117void ssl_hangup(struct tty_struct *tty)
118{ 91{
92 return line_install(driver, tty, &serial_lines[tty->index]);
119} 93}
120#endif
121 94
122static const struct tty_operations ssl_ops = { 95static const struct tty_operations ssl_ops = {
123 .open = ssl_open, 96 .open = line_open,
124 .close = line_close, 97 .close = line_close,
125 .write = line_write, 98 .write = line_write,
126 .put_char = line_put_char, 99 .put_char = line_put_char,
@@ -129,14 +102,11 @@ static const struct tty_operations ssl_ops = {
129 .flush_buffer = line_flush_buffer, 102 .flush_buffer = line_flush_buffer,
130 .flush_chars = line_flush_chars, 103 .flush_chars = line_flush_chars,
131 .set_termios = line_set_termios, 104 .set_termios = line_set_termios,
132 .ioctl = line_ioctl,
133 .throttle = line_throttle, 105 .throttle = line_throttle,
134 .unthrottle = line_unthrottle, 106 .unthrottle = line_unthrottle,
135#if 0 107 .install = ssl_install,
136 .stop = ssl_stop, 108 .cleanup = line_cleanup,
137 .start = ssl_start, 109 .hangup = line_hangup,
138 .hangup = ssl_hangup,
139#endif
140}; 110};
141 111
142/* Changed by ssl_init and referenced by ssl_exit, which are both serialized 112/* Changed by ssl_init and referenced by ssl_exit, which are both serialized
diff --git a/arch/um/drivers/stdio_console.c b/arch/um/drivers/stdio_console.c
index 7663541c372e..929b99a261f3 100644
--- a/arch/um/drivers/stdio_console.c
+++ b/arch/um/drivers/stdio_console.c
@@ -89,21 +89,17 @@ static int con_remove(int n, char **error_out)
89 return line_remove(vts, ARRAY_SIZE(vts), n, error_out); 89 return line_remove(vts, ARRAY_SIZE(vts), n, error_out);
90} 90}
91 91
92static int con_open(struct tty_struct *tty, struct file *filp)
93{
94 int err = line_open(vts, tty);
95 if (err)
96 printk(KERN_ERR "Failed to open console %d, err = %d\n",
97 tty->index, err);
98
99 return err;
100}
101
102/* Set in an initcall, checked in an exitcall */ 92/* Set in an initcall, checked in an exitcall */
103static int con_init_done = 0; 93static int con_init_done = 0;
104 94
95static int con_install(struct tty_driver *driver, struct tty_struct *tty)
96{
97 return line_install(driver, tty, &vts[tty->index]);
98}
99
105static const struct tty_operations console_ops = { 100static const struct tty_operations console_ops = {
106 .open = con_open, 101 .open = line_open,
102 .install = con_install,
107 .close = line_close, 103 .close = line_close,
108 .write = line_write, 104 .write = line_write,
109 .put_char = line_put_char, 105 .put_char = line_put_char,
@@ -112,9 +108,10 @@ static const struct tty_operations console_ops = {
112 .flush_buffer = line_flush_buffer, 108 .flush_buffer = line_flush_buffer,
113 .flush_chars = line_flush_chars, 109 .flush_chars = line_flush_chars,
114 .set_termios = line_set_termios, 110 .set_termios = line_set_termios,
115 .ioctl = line_ioctl,
116 .throttle = line_throttle, 111 .throttle = line_throttle,
117 .unthrottle = line_unthrottle, 112 .unthrottle = line_unthrottle,
113 .cleanup = line_cleanup,
114 .hangup = line_hangup,
118}; 115};
119 116
120static void uml_console_write(struct console *console, const char *string, 117static void uml_console_write(struct console *console, const char *string,
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 20505cafa299..0643e5bc9f41 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -514,7 +514,7 @@ static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
514 goto out; 514 goto out;
515 } 515 }
516 516
517 fd = os_open_file(ubd_dev->file, global_openflags, 0); 517 fd = os_open_file(ubd_dev->file, of_read(OPENFLAGS()), 0);
518 if (fd < 0) 518 if (fd < 0)
519 return fd; 519 return fd;
520 520