aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/drivers')
-rw-r--r--arch/um/drivers/chan_kern.c3
-rw-r--r--arch/um/drivers/cow_user.c6
-rw-r--r--arch/um/drivers/harddog_user.c2
-rw-r--r--arch/um/drivers/line.c64
-rw-r--r--arch/um/drivers/net_kern.c12
-rw-r--r--arch/um/drivers/net_user.c5
-rw-r--r--arch/um/drivers/slip_user.c3
-rw-r--r--arch/um/drivers/ubd_kern.c31
-rw-r--r--arch/um/drivers/xterm.c1
9 files changed, 92 insertions, 35 deletions
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 25e1965df7c..d4191fe1ced 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -543,11 +543,10 @@ int parse_chan_pair(char *str, struct line *line, int device,
543 const struct chan_opts *opts, char **error_out) 543 const struct chan_opts *opts, char **error_out)
544{ 544{
545 struct list_head *chans = &line->chan_list; 545 struct list_head *chans = &line->chan_list;
546 struct chan *new, *chan; 546 struct chan *new;
547 char *in, *out; 547 char *in, *out;
548 548
549 if (!list_empty(chans)) { 549 if (!list_empty(chans)) {
550 chan = list_entry(chans->next, struct chan, list);
551 free_chan(chans, 0); 550 free_chan(chans, 0);
552 INIT_LIST_HEAD(chans); 551 INIT_LIST_HEAD(chans);
553 } 552 }
diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c
index 93f227a25ba..9cbb426c0b9 100644
--- a/arch/um/drivers/cow_user.c
+++ b/arch/um/drivers/cow_user.c
@@ -186,7 +186,11 @@ static int absolutize(char *to, int size, char *from)
186 strcat(to, "/"); 186 strcat(to, "/");
187 strcat(to, from); 187 strcat(to, from);
188 } 188 }
189 chdir(save_cwd); 189 if (chdir(save_cwd)) {
190 cow_printf("absolutize : Can't cd to '%s' - "
191 "errno = %d\n", save_cwd, errno);
192 return -1;
193 }
190 return 0; 194 return 0;
191} 195}
192 196
diff --git a/arch/um/drivers/harddog_user.c b/arch/um/drivers/harddog_user.c
index b56f8e0196a..84dce3fc590 100644
--- a/arch/um/drivers/harddog_user.c
+++ b/arch/um/drivers/harddog_user.c
@@ -32,7 +32,7 @@ int start_watchdog(int *in_fd_ret, int *out_fd_ret, char *sock)
32{ 32{
33 struct dog_data data; 33 struct dog_data data;
34 int in_fds[2], out_fds[2], pid, n, err; 34 int in_fds[2], out_fds[2], pid, n, err;
35 char pid_buf[sizeof("nnnnn\0")], c; 35 char pid_buf[sizeof("nnnnnnn\0")], c;
36 char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL }; 36 char *pid_args[] = { "/usr/bin/uml_watchdog", "-pid", pid_buf, NULL };
37 char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL, 37 char *mconsole_args[] = { "/usr/bin/uml_watchdog", "-mconsole", NULL,
38 NULL }; 38 NULL };
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c
index 35dd0b86401..364c8a15c4c 100644
--- a/arch/um/drivers/line.c
+++ b/arch/um/drivers/line.c
@@ -176,10 +176,9 @@ void line_flush_buffer(struct tty_struct *tty)
176{ 176{
177 struct line *line = tty->driver_data; 177 struct line *line = tty->driver_data;
178 unsigned long flags; 178 unsigned long flags;
179 int err;
180 179
181 spin_lock_irqsave(&line->lock, flags); 180 spin_lock_irqsave(&line->lock, flags);
182 err = flush_buffer(line); 181 flush_buffer(line);
183 spin_unlock_irqrestore(&line->lock, flags); 182 spin_unlock_irqrestore(&line->lock, flags);
184} 183}
185 184
@@ -400,8 +399,8 @@ int line_setup_irq(int fd, int input, int output, struct line *line, void *data)
400 * is done under a spinlock. Checking whether the device is in use is 399 * is done under a spinlock. Checking whether the device is in use is
401 * line->tty->count > 1, also under the spinlock. 400 * line->tty->count > 1, also under the spinlock.
402 * 401 *
403 * tty->count serves to decide whether the device should be enabled or 402 * line->count serves to decide whether the device should be enabled or
404 * disabled on the host. If it's equal to 1, then we are doing the 403 * disabled on the host. If it's equal to 0, then we are doing the
405 * first open or last close. Otherwise, open and close just return. 404 * first open or last close. Otherwise, open and close just return.
406 */ 405 */
407 406
@@ -415,16 +414,16 @@ int line_open(struct line *lines, struct tty_struct *tty)
415 goto out_unlock; 414 goto out_unlock;
416 415
417 err = 0; 416 err = 0;
418 if (tty->count > 1) 417 if (line->count++)
419 goto out_unlock; 418 goto out_unlock;
420 419
421 spin_unlock(&line->count_lock); 420 BUG_ON(tty->driver_data);
422
423 tty->driver_data = line; 421 tty->driver_data = line;
424 line->tty = tty; 422 line->tty = tty;
425 423
424 spin_unlock(&line->count_lock);
426 err = enable_chan(line); 425 err = enable_chan(line);
427 if (err) 426 if (err) /* line_close() will be called by our caller */
428 return err; 427 return err;
429 428
430 INIT_DELAYED_WORK(&line->task, line_timer_cb); 429 INIT_DELAYED_WORK(&line->task, line_timer_cb);
@@ -437,7 +436,7 @@ int line_open(struct line *lines, struct tty_struct *tty)
437 chan_window_size(&line->chan_list, &tty->winsize.ws_row, 436 chan_window_size(&line->chan_list, &tty->winsize.ws_row,
438 &tty->winsize.ws_col); 437 &tty->winsize.ws_col);
439 438
440 return err; 439 return 0;
441 440
442out_unlock: 441out_unlock:
443 spin_unlock(&line->count_lock); 442 spin_unlock(&line->count_lock);
@@ -461,17 +460,16 @@ void line_close(struct tty_struct *tty, struct file * filp)
461 flush_buffer(line); 460 flush_buffer(line);
462 461
463 spin_lock(&line->count_lock); 462 spin_lock(&line->count_lock);
464 if (!line->valid) 463 BUG_ON(!line->valid);
465 goto out_unlock;
466 464
467 if (tty->count > 1) 465 if (--line->count)
468 goto out_unlock; 466 goto out_unlock;
469 467
470 spin_unlock(&line->count_lock);
471
472 line->tty = NULL; 468 line->tty = NULL;
473 tty->driver_data = NULL; 469 tty->driver_data = NULL;
474 470
471 spin_unlock(&line->count_lock);
472
475 if (line->sigio) { 473 if (line->sigio) {
476 unregister_winch(tty); 474 unregister_winch(tty);
477 line->sigio = 0; 475 line->sigio = 0;
@@ -499,7 +497,7 @@ static int setup_one_line(struct line *lines, int n, char *init, int init_prio,
499 497
500 spin_lock(&line->count_lock); 498 spin_lock(&line->count_lock);
501 499
502 if (line->tty != NULL) { 500 if (line->count) {
503 *error_out = "Device is already open"; 501 *error_out = "Device is already open";
504 goto out; 502 goto out;
505 } 503 }
@@ -723,41 +721,53 @@ struct winch {
723 int pid; 721 int pid;
724 struct tty_struct *tty; 722 struct tty_struct *tty;
725 unsigned long stack; 723 unsigned long stack;
724 struct work_struct work;
726}; 725};
727 726
728static void free_winch(struct winch *winch, int free_irq_ok) 727static void __free_winch(struct work_struct *work)
729{ 728{
730 if (free_irq_ok) 729 struct winch *winch = container_of(work, struct winch, work);
731 free_irq(WINCH_IRQ, winch); 730 free_irq(WINCH_IRQ, winch);
732
733 list_del(&winch->list);
734 731
735 if (winch->pid != -1) 732 if (winch->pid != -1)
736 os_kill_process(winch->pid, 1); 733 os_kill_process(winch->pid, 1);
737 if (winch->fd != -1)
738 os_close_file(winch->fd);
739 if (winch->stack != 0) 734 if (winch->stack != 0)
740 free_stack(winch->stack, 0); 735 free_stack(winch->stack, 0);
741 kfree(winch); 736 kfree(winch);
742} 737}
743 738
739static void free_winch(struct winch *winch)
740{
741 int fd = winch->fd;
742 winch->fd = -1;
743 if (fd != -1)
744 os_close_file(fd);
745 list_del(&winch->list);
746 __free_winch(&winch->work);
747}
748
744static irqreturn_t winch_interrupt(int irq, void *data) 749static irqreturn_t winch_interrupt(int irq, void *data)
745{ 750{
746 struct winch *winch = data; 751 struct winch *winch = data;
747 struct tty_struct *tty; 752 struct tty_struct *tty;
748 struct line *line; 753 struct line *line;
754 int fd = winch->fd;
749 int err; 755 int err;
750 char c; 756 char c;
751 757
752 if (winch->fd != -1) { 758 if (fd != -1) {
753 err = generic_read(winch->fd, &c, NULL); 759 err = generic_read(fd, &c, NULL);
754 if (err < 0) { 760 if (err < 0) {
755 if (err != -EAGAIN) { 761 if (err != -EAGAIN) {
762 winch->fd = -1;
763 list_del(&winch->list);
764 os_close_file(fd);
756 printk(KERN_ERR "winch_interrupt : " 765 printk(KERN_ERR "winch_interrupt : "
757 "read failed, errno = %d\n", -err); 766 "read failed, errno = %d\n", -err);
758 printk(KERN_ERR "fd %d is losing SIGWINCH " 767 printk(KERN_ERR "fd %d is losing SIGWINCH "
759 "support\n", winch->tty_fd); 768 "support\n", winch->tty_fd);
760 free_winch(winch, 0); 769 INIT_WORK(&winch->work, __free_winch);
770 schedule_work(&winch->work);
761 return IRQ_HANDLED; 771 return IRQ_HANDLED;
762 } 772 }
763 goto out; 773 goto out;
@@ -829,7 +839,7 @@ static void unregister_winch(struct tty_struct *tty)
829 list_for_each_safe(ele, next, &winch_handlers) { 839 list_for_each_safe(ele, next, &winch_handlers) {
830 winch = list_entry(ele, struct winch, list); 840 winch = list_entry(ele, struct winch, list);
831 if (winch->tty == tty) { 841 if (winch->tty == tty) {
832 free_winch(winch, 1); 842 free_winch(winch);
833 break; 843 break;
834 } 844 }
835 } 845 }
@@ -845,7 +855,7 @@ static void winch_cleanup(void)
845 855
846 list_for_each_safe(ele, next, &winch_handlers) { 856 list_for_each_safe(ele, next, &winch_handlers) {
847 winch = list_entry(ele, struct winch, list); 857 winch = list_entry(ele, struct winch, list);
848 free_winch(winch, 1); 858 free_winch(winch);
849 } 859 }
850 860
851 spin_unlock(&winch_handler_lock); 861 spin_unlock(&winch_handler_lock);
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 47d0c37897d..22745b47c82 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -262,6 +262,15 @@ static int uml_net_change_mtu(struct net_device *dev, int new_mtu)
262 return 0; 262 return 0;
263} 263}
264 264
265#ifdef CONFIG_NET_POLL_CONTROLLER
266static void uml_net_poll_controller(struct net_device *dev)
267{
268 disable_irq(dev->irq);
269 uml_net_interrupt(dev->irq, dev);
270 enable_irq(dev->irq);
271}
272#endif
273
265static void uml_net_get_drvinfo(struct net_device *dev, 274static void uml_net_get_drvinfo(struct net_device *dev,
266 struct ethtool_drvinfo *info) 275 struct ethtool_drvinfo *info)
267{ 276{
@@ -364,6 +373,9 @@ static const struct net_device_ops uml_netdev_ops = {
364 .ndo_set_mac_address = eth_mac_addr, 373 .ndo_set_mac_address = eth_mac_addr,
365 .ndo_change_mtu = uml_net_change_mtu, 374 .ndo_change_mtu = uml_net_change_mtu,
366 .ndo_validate_addr = eth_validate_addr, 375 .ndo_validate_addr = eth_validate_addr,
376#ifdef CONFIG_NET_POLL_CONTROLLER
377 .ndo_poll_controller = uml_net_poll_controller,
378#endif
367}; 379};
368 380
369/* 381/*
diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c
index 9415dd9e63e..520118888f1 100644
--- a/arch/um/drivers/net_user.c
+++ b/arch/um/drivers/net_user.c
@@ -228,7 +228,10 @@ static void change(char *dev, char *what, unsigned char *addr,
228 "buffer\n"); 228 "buffer\n");
229 229
230 pid = change_tramp(argv, output, output_len); 230 pid = change_tramp(argv, output, output_len);
231 if (pid < 0) return; 231 if (pid < 0) {
232 kfree(output);
233 return;
234 }
232 235
233 if (output != NULL) { 236 if (output != NULL) {
234 printk("%s", output); 237 printk("%s", output);
diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c
index a1c2d2c98a9..cbacfc4e63e 100644
--- a/arch/um/drivers/slip_user.c
+++ b/arch/um/drivers/slip_user.c
@@ -102,7 +102,7 @@ static int slip_tramp(char **argv, int fd)
102 "buffer\n"); 102 "buffer\n");
103 os_kill_process(pid, 1); 103 os_kill_process(pid, 1);
104 err = -ENOMEM; 104 err = -ENOMEM;
105 goto out_free; 105 goto out_close;
106 } 106 }
107 107
108 close(fds[1]); 108 close(fds[1]);
@@ -112,7 +112,6 @@ static int slip_tramp(char **argv, int fd)
112 err = helper_wait(pid); 112 err = helper_wait(pid);
113 close(fds[0]); 113 close(fds[0]);
114 114
115out_free:
116 kfree(output); 115 kfree(output);
117 return err; 116 return err;
118 117
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 620f5b70957..0491e40d696 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -513,8 +513,37 @@ __uml_exitcall(kill_io_thread);
513static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) 513static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out)
514{ 514{
515 char *file; 515 char *file;
516 int fd;
517 int err;
518
519 __u32 version;
520 __u32 align;
521 char *backing_file;
522 time_t mtime;
523 unsigned long long size;
524 int sector_size;
525 int bitmap_offset;
526
527 if (ubd_dev->file && ubd_dev->cow.file) {
528 file = ubd_dev->cow.file;
529
530 goto out;
531 }
516 532
517 file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file; 533 fd = os_open_file(ubd_dev->file, global_openflags, 0);
534 if (fd < 0)
535 return fd;
536
537 err = read_cow_header(file_reader, &fd, &version, &backing_file, \
538 &mtime, &size, &sector_size, &align, &bitmap_offset);
539 os_close_file(fd);
540
541 if(err == -EINVAL)
542 file = ubd_dev->file;
543 else
544 file = backing_file;
545
546out:
518 return os_file_size(file, size_out); 547 return os_file_size(file, size_out);
519} 548}
520 549
diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c
index 8ac7146c237..2e1de572860 100644
--- a/arch/um/drivers/xterm.c
+++ b/arch/um/drivers/xterm.c
@@ -123,6 +123,7 @@ static int xterm_open(int input, int output, int primary, void *d,
123 err = -errno; 123 err = -errno;
124 printk(UM_KERN_ERR "xterm_open : unlink failed, errno = %d\n", 124 printk(UM_KERN_ERR "xterm_open : unlink failed, errno = %d\n",
125 errno); 125 errno);
126 close(fd);
126 return err; 127 return err;
127 } 128 }
128 close(fd); 129 close(fd);