aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers/line.c
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2007-02-10 04:43:53 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-11 13:51:21 -0500
commitf28169d2000177e8b72ccc6d72887be779dceca8 (patch)
tree0ef842014c67d8a136cc26c99113b69e2ede87ea /arch/um/drivers/line.c
parentd79a580936396bbcd2f4fae2c6215f9cf81e3c0d (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.c66
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
552static void setup_one_line(struct line *lines, int n, char *init, int init_prio) 552static 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;
572out: 575out:
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
581int line_setup(struct line *lines, unsigned int num, char *init) 586int 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
616int line_config(struct line *lines, unsigned int num, char *str, 627int 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
642int line_get_config(char *name, struct line *lines, unsigned int num, char *str, 652int 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
688int line_remove(struct line *lines, unsigned int num, int n) 698int 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);
740void lines_init(struct line *lines, int nlines, struct chan_opts *opts) 750void 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 }