diff options
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 | } |