diff options
author | Jeff Dike <jdike@addtoit.com> | 2007-02-10 04:43:53 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-11 13:51:21 -0500 |
commit | f28169d2000177e8b72ccc6d72887be779dceca8 (patch) | |
tree | 0ef842014c67d8a136cc26c99113b69e2ede87ea /arch/um/drivers/line.c | |
parent | d79a580936396bbcd2f4fae2c6215f9cf81e3c0d (diff) |
[PATCH] uml: return hotplug errors to host
I noticed that errors happening while hotplugging devices from the host were
never returned back to the mconsole client. In some cases, success was
returned instead of even an information-free error.
This patch cleans that up by having the low-level configuration code pass back
an error string along with an error code. At the top level, which knows
whether it is early boot time or responding to an mconsole request, the string
is printk'd or returned to the mconsole client.
There are also whitespace and trivial code cleanups in the surrounding code.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/um/drivers/line.c')
-rw-r--r-- | arch/um/drivers/line.c | 66 |
1 files changed, 39 insertions, 27 deletions
diff --git a/arch/um/drivers/line.c b/arch/um/drivers/line.c index 799fca3644e9..e620ed46ed3f 100644 --- a/arch/um/drivers/line.c +++ b/arch/um/drivers/line.c | |||
@@ -549,14 +549,16 @@ void close_lines(struct line *lines, int nlines) | |||
549 | close_chan(&lines[i].chan_list, 0); | 549 | close_chan(&lines[i].chan_list, 0); |
550 | } | 550 | } |
551 | 551 | ||
552 | static void setup_one_line(struct line *lines, int n, char *init, int init_prio) | 552 | static int setup_one_line(struct line *lines, int n, char *init, int init_prio, |
553 | char **error_out) | ||
553 | { | 554 | { |
554 | struct line *line = &lines[n]; | 555 | struct line *line = &lines[n]; |
556 | int err = -EINVAL; | ||
555 | 557 | ||
556 | spin_lock(&line->count_lock); | 558 | spin_lock(&line->count_lock); |
557 | 559 | ||
558 | if(line->tty != NULL){ | 560 | if(line->tty != NULL){ |
559 | printk("line_setup - device %d is open\n", n); | 561 | *error_out = "Device is already open"; |
560 | goto out; | 562 | goto out; |
561 | } | 563 | } |
562 | 564 | ||
@@ -569,18 +571,22 @@ static void setup_one_line(struct line *lines, int n, char *init, int init_prio) | |||
569 | line->valid = 1; | 571 | line->valid = 1; |
570 | } | 572 | } |
571 | } | 573 | } |
574 | err = 0; | ||
572 | out: | 575 | out: |
573 | spin_unlock(&line->count_lock); | 576 | spin_unlock(&line->count_lock); |
577 | return err; | ||
574 | } | 578 | } |
575 | 579 | ||
576 | /* Common setup code for both startup command line and mconsole initialization. | 580 | /* Common setup code for both startup command line and mconsole initialization. |
577 | * @lines contains the array (of size @num) to modify; | 581 | * @lines contains the array (of size @num) to modify; |
578 | * @init is the setup string; | 582 | * @init is the setup string; |
583 | * @error_out is an error string in the case of failure; | ||
579 | */ | 584 | */ |
580 | 585 | ||
581 | int line_setup(struct line *lines, unsigned int num, char *init) | 586 | int line_setup(struct line *lines, unsigned int num, char *init, |
587 | char **error_out) | ||
582 | { | 588 | { |
583 | int i, n; | 589 | int i, n, err; |
584 | char *end; | 590 | char *end; |
585 | 591 | ||
586 | if(*init == '=') { | 592 | if(*init == '=') { |
@@ -591,52 +597,56 @@ int line_setup(struct line *lines, unsigned int num, char *init) | |||
591 | else { | 597 | else { |
592 | n = simple_strtoul(init, &end, 0); | 598 | n = simple_strtoul(init, &end, 0); |
593 | if(*end != '='){ | 599 | if(*end != '='){ |
594 | printk(KERN_ERR "line_setup failed to parse \"%s\"\n", | 600 | *error_out = "Couldn't parse device number"; |
595 | init); | 601 | return -EINVAL; |
596 | return 0; | ||
597 | } | 602 | } |
598 | init = end; | 603 | init = end; |
599 | } | 604 | } |
600 | init++; | 605 | init++; |
601 | 606 | ||
602 | if (n >= (signed int) num) { | 607 | if (n >= (signed int) num) { |
603 | printk("line_setup - %d out of range ((0 ... %d) allowed)\n", | 608 | *error_out = "Device number out of range"; |
604 | n, num - 1); | 609 | return -EINVAL; |
605 | return 0; | 610 | } |
611 | else if (n >= 0){ | ||
612 | err = setup_one_line(lines, n, init, INIT_ONE, error_out); | ||
613 | if(err) | ||
614 | return err; | ||
606 | } | 615 | } |
607 | else if (n >= 0) | ||
608 | setup_one_line(lines, n, init, INIT_ONE); | ||
609 | else { | 616 | else { |
610 | for(i = 0; i < num; i++) | 617 | for(i = 0; i < num; i++){ |
611 | setup_one_line(lines, i, init, INIT_ALL); | 618 | err = setup_one_line(lines, i, init, INIT_ALL, |
619 | error_out); | ||
620 | if(err) | ||
621 | return err; | ||
622 | } | ||
612 | } | 623 | } |
613 | return n == -1 ? num : n; | 624 | return n == -1 ? num : n; |
614 | } | 625 | } |
615 | 626 | ||
616 | int line_config(struct line *lines, unsigned int num, char *str, | 627 | int line_config(struct line *lines, unsigned int num, char *str, |
617 | const struct chan_opts *opts) | 628 | const struct chan_opts *opts, char **error_out) |
618 | { | 629 | { |
619 | struct line *line; | 630 | struct line *line; |
620 | char *new; | 631 | char *new; |
621 | int n; | 632 | int n; |
622 | 633 | ||
623 | if(*str == '='){ | 634 | if(*str == '='){ |
624 | printk("line_config - can't configure all devices from " | 635 | *error_out = "Can't configure all devices from mconsole"; |
625 | "mconsole\n"); | 636 | return -EINVAL; |
626 | return 1; | ||
627 | } | 637 | } |
628 | 638 | ||
629 | new = kstrdup(str, GFP_KERNEL); | 639 | new = kstrdup(str, GFP_KERNEL); |
630 | if(new == NULL){ | 640 | if(new == NULL){ |
631 | printk("line_config - kstrdup failed\n"); | 641 | *error_out = "Failed to allocate memory"; |
632 | return 1; | 642 | return -ENOMEM; |
633 | } | 643 | } |
634 | n = line_setup(lines, num, new); | 644 | n = line_setup(lines, num, new, error_out); |
635 | if(n < 0) | 645 | if(n < 0) |
636 | return 1; | 646 | return n; |
637 | 647 | ||
638 | line = &lines[n]; | 648 | line = &lines[n]; |
639 | return parse_chan_pair(line->init_str, line, n, opts); | 649 | return parse_chan_pair(line->init_str, line, n, opts, error_out); |
640 | } | 650 | } |
641 | 651 | ||
642 | int line_get_config(char *name, struct line *lines, unsigned int num, char *str, | 652 | int line_get_config(char *name, struct line *lines, unsigned int num, char *str, |
@@ -685,13 +695,13 @@ int line_id(char **str, int *start_out, int *end_out) | |||
685 | return n; | 695 | return n; |
686 | } | 696 | } |
687 | 697 | ||
688 | int line_remove(struct line *lines, unsigned int num, int n) | 698 | int line_remove(struct line *lines, unsigned int num, int n, char **error_out) |
689 | { | 699 | { |
690 | int err; | 700 | int err; |
691 | char config[sizeof("conxxxx=none\0")]; | 701 | char config[sizeof("conxxxx=none\0")]; |
692 | 702 | ||
693 | sprintf(config, "%d=none", n); | 703 | sprintf(config, "%d=none", n); |
694 | err = line_setup(lines, num, config); | 704 | err = line_setup(lines, num, config, error_out); |
695 | if(err >= 0) | 705 | if(err >= 0) |
696 | err = 0; | 706 | err = 0; |
697 | return err; | 707 | return err; |
@@ -740,6 +750,7 @@ static LIST_HEAD(winch_handlers); | |||
740 | void lines_init(struct line *lines, int nlines, struct chan_opts *opts) | 750 | void lines_init(struct line *lines, int nlines, struct chan_opts *opts) |
741 | { | 751 | { |
742 | struct line *line; | 752 | struct line *line; |
753 | char *error; | ||
743 | int i; | 754 | int i; |
744 | 755 | ||
745 | for(i = 0; i < nlines; i++){ | 756 | for(i = 0; i < nlines; i++){ |
@@ -754,8 +765,9 @@ void lines_init(struct line *lines, int nlines, struct chan_opts *opts) | |||
754 | if(line->init_str == NULL) | 765 | if(line->init_str == NULL) |
755 | printk("lines_init - kstrdup returned NULL\n"); | 766 | printk("lines_init - kstrdup returned NULL\n"); |
756 | 767 | ||
757 | if(parse_chan_pair(line->init_str, line, i, opts)){ | 768 | if(parse_chan_pair(line->init_str, line, i, opts, &error)){ |
758 | printk("parse_chan_pair failed for device %d\n", i); | 769 | printk("parse_chan_pair failed for device %d : %s\n", |
770 | i, error); | ||
759 | line->valid = 0; | 771 | line->valid = 0; |
760 | } | 772 | } |
761 | } | 773 | } |