diff options
Diffstat (limited to 'arch/um/drivers/net_kern.c')
-rw-r--r-- | arch/um/drivers/net_kern.c | 97 |
1 files changed, 46 insertions, 51 deletions
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index afe3d427ddfa..07e839e387db 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and | 2 | * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and |
3 | * James Leu (jleu@mindspring.net). | 3 | * James Leu (jleu@mindspring.net). |
4 | * Copyright (C) 2001 by various other people who didn't put their name here. | 4 | * Copyright (C) 2001 by various other people who didn't put their name here. |
5 | * Licensed under the GPL. | 5 | * Licensed under the GPL. |
@@ -91,8 +91,8 @@ irqreturn_t uml_net_interrupt(int irq, void *dev_id) | |||
91 | spin_lock(&lp->lock); | 91 | spin_lock(&lp->lock); |
92 | while((err = uml_net_rx(dev)) > 0) ; | 92 | while((err = uml_net_rx(dev)) > 0) ; |
93 | if(err < 0) { | 93 | if(err < 0) { |
94 | printk(KERN_ERR | 94 | printk(KERN_ERR |
95 | "Device '%s' read returned %d, shutting it down\n", | 95 | "Device '%s' read returned %d, shutting it down\n", |
96 | dev->name, err); | 96 | dev->name, err); |
97 | /* dev_close can't be called in interrupt context, and takes | 97 | /* dev_close can't be called in interrupt context, and takes |
98 | * again lp->lock. | 98 | * again lp->lock. |
@@ -159,7 +159,7 @@ out: | |||
159 | static int uml_net_close(struct net_device *dev) | 159 | static int uml_net_close(struct net_device *dev) |
160 | { | 160 | { |
161 | struct uml_net_private *lp = dev->priv; | 161 | struct uml_net_private *lp = dev->priv; |
162 | 162 | ||
163 | netif_stop_queue(dev); | 163 | netif_stop_queue(dev); |
164 | 164 | ||
165 | free_irq(dev->irq, dev); | 165 | free_irq(dev->irq, dev); |
@@ -194,7 +194,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
194 | 194 | ||
195 | /* this is normally done in the interrupt when tx finishes */ | 195 | /* this is normally done in the interrupt when tx finishes */ |
196 | netif_wake_queue(dev); | 196 | netif_wake_queue(dev); |
197 | } | 197 | } |
198 | else if(len == 0){ | 198 | else if(len == 0){ |
199 | netif_start_queue(dev); | 199 | netif_start_queue(dev); |
200 | lp->stats.tx_dropped++; | 200 | lp->stats.tx_dropped++; |
@@ -333,7 +333,7 @@ static int eth_configure(int n, void *init, char *mac, | |||
333 | struct uml_net_private *lp; | 333 | struct uml_net_private *lp; |
334 | int save, err, size; | 334 | int save, err, size; |
335 | 335 | ||
336 | size = transport->private_size + sizeof(struct uml_net_private) + | 336 | size = transport->private_size + sizeof(struct uml_net_private) + |
337 | sizeof(((struct uml_net_private *) 0)->user); | 337 | sizeof(((struct uml_net_private *) 0)->user); |
338 | 338 | ||
339 | device = kzalloc(sizeof(*device), GFP_KERNEL); | 339 | device = kzalloc(sizeof(*device), GFP_KERNEL); |
@@ -438,7 +438,7 @@ static int eth_configure(int n, void *init, char *mac, | |||
438 | lp->tl.function = uml_net_user_timer_expire; | 438 | lp->tl.function = uml_net_user_timer_expire; |
439 | memcpy(lp->mac, device->mac, sizeof(lp->mac)); | 439 | memcpy(lp->mac, device->mac, sizeof(lp->mac)); |
440 | 440 | ||
441 | if (transport->user->init) | 441 | if (transport->user->init) |
442 | (*transport->user->init)(&lp->user, dev); | 442 | (*transport->user->init)(&lp->user, dev); |
443 | 443 | ||
444 | set_ether_mac(dev, device->mac); | 444 | set_ether_mac(dev, device->mac); |
@@ -463,35 +463,33 @@ static struct uml_net *find_device(int n) | |||
463 | return(device); | 463 | return(device); |
464 | } | 464 | } |
465 | 465 | ||
466 | static int eth_parse(char *str, int *index_out, char **str_out) | 466 | static int eth_parse(char *str, int *index_out, char **str_out, |
467 | char **error_out) | ||
467 | { | 468 | { |
468 | char *end; | 469 | char *end; |
469 | int n; | 470 | int n, err = -EINVAL;; |
470 | 471 | ||
471 | n = simple_strtoul(str, &end, 0); | 472 | n = simple_strtoul(str, &end, 0); |
472 | if(end == str){ | 473 | if(end == str){ |
473 | printk(KERN_ERR "eth_setup: Failed to parse '%s'\n", str); | 474 | *error_out = "Bad device number"; |
474 | return(1); | 475 | return err; |
475 | } | ||
476 | if(n < 0){ | ||
477 | printk(KERN_ERR "eth_setup: device %d is negative\n", n); | ||
478 | return(1); | ||
479 | } | 476 | } |
477 | |||
480 | str = end; | 478 | str = end; |
481 | if(*str != '='){ | 479 | if(*str != '='){ |
482 | printk(KERN_ERR | 480 | *error_out = "Expected '=' after device number"; |
483 | "eth_setup: expected '=' after device number\n"); | 481 | return err; |
484 | return(1); | ||
485 | } | 482 | } |
483 | |||
486 | str++; | 484 | str++; |
487 | if(find_device(n)){ | 485 | if(find_device(n)){ |
488 | printk(KERN_ERR "eth_setup: Device %d already configured\n", | 486 | *error_out = "Device already configured"; |
489 | n); | 487 | return err; |
490 | return(1); | ||
491 | } | 488 | } |
492 | if(index_out) *index_out = n; | 489 | |
490 | *index_out = n; | ||
493 | *str_out = str; | 491 | *str_out = str; |
494 | return(0); | 492 | return 0; |
495 | } | 493 | } |
496 | 494 | ||
497 | struct eth_init { | 495 | struct eth_init { |
@@ -581,11 +579,15 @@ static int eth_setup_common(char *str, int index) | |||
581 | static int eth_setup(char *str) | 579 | static int eth_setup(char *str) |
582 | { | 580 | { |
583 | struct eth_init *new; | 581 | struct eth_init *new; |
582 | char *error; | ||
584 | int n, err; | 583 | int n, err; |
585 | 584 | ||
586 | err = eth_parse(str, &n, &str); | 585 | err = eth_parse(str, &n, &str, &error); |
587 | if(err) | 586 | if(err){ |
587 | printk(KERN_ERR "eth_setup - Couldn't parse '%s' : %s\n", | ||
588 | str, error); | ||
588 | return 1; | 589 | return 1; |
590 | } | ||
589 | 591 | ||
590 | new = alloc_bootmem(sizeof(*new)); | 592 | new = alloc_bootmem(sizeof(*new)); |
591 | if (new == NULL){ | 593 | if (new == NULL){ |
@@ -619,26 +621,30 @@ static int eth_init(void) | |||
619 | if(eth_setup_common(eth->init, eth->index)) | 621 | if(eth_setup_common(eth->init, eth->index)) |
620 | list_del(ð->list); | 622 | list_del(ð->list); |
621 | } | 623 | } |
622 | 624 | ||
623 | return(1); | 625 | return(1); |
624 | } | 626 | } |
625 | __initcall(eth_init); | 627 | __initcall(eth_init); |
626 | #endif | 628 | #endif |
627 | 629 | ||
628 | static int net_config(char *str) | 630 | static int net_config(char *str, char **error_out) |
629 | { | 631 | { |
630 | int n, err; | 632 | int n, err; |
631 | 633 | ||
632 | err = eth_parse(str, &n, &str); | 634 | err = eth_parse(str, &n, &str, error_out); |
633 | if(err) return(err); | 635 | if(err) |
636 | return err; | ||
634 | 637 | ||
638 | /* This string is broken up and the pieces used by the underlying | ||
639 | * driver. So, it is freed only if eth_setup_common fails. | ||
640 | */ | ||
635 | str = kstrdup(str, GFP_KERNEL); | 641 | str = kstrdup(str, GFP_KERNEL); |
636 | if(str == NULL){ | 642 | if(str == NULL){ |
637 | printk(KERN_ERR "net_config failed to strdup string\n"); | 643 | *error_out = "net_config failed to strdup string"; |
638 | return(-1); | 644 | return -ENOMEM; |
639 | } | 645 | } |
640 | err = !eth_setup_common(str, n); | 646 | err = !eth_setup_common(str, n); |
641 | if(err) | 647 | if(err) |
642 | kfree(str); | 648 | kfree(str); |
643 | return(err); | 649 | return(err); |
644 | } | 650 | } |
@@ -658,7 +664,7 @@ static int net_id(char **str, int *start_out, int *end_out) | |||
658 | return n; | 664 | return n; |
659 | } | 665 | } |
660 | 666 | ||
661 | static int net_remove(int n) | 667 | static int net_remove(int n, char **error_out) |
662 | { | 668 | { |
663 | struct uml_net *device; | 669 | struct uml_net *device; |
664 | struct net_device *dev; | 670 | struct net_device *dev; |
@@ -727,7 +733,7 @@ struct notifier_block uml_inetaddr_notifier = { | |||
727 | static int uml_net_init(void) | 733 | static int uml_net_init(void) |
728 | { | 734 | { |
729 | struct list_head *ele; | 735 | struct list_head *ele; |
730 | struct uml_net_private *lp; | 736 | struct uml_net_private *lp; |
731 | struct in_device *ip; | 737 | struct in_device *ip; |
732 | struct in_ifaddr *in; | 738 | struct in_ifaddr *in; |
733 | 739 | ||
@@ -747,7 +753,7 @@ static int uml_net_init(void) | |||
747 | uml_inetaddr_event(NULL, NETDEV_UP, in); | 753 | uml_inetaddr_event(NULL, NETDEV_UP, in); |
748 | in = in->ifa_next; | 754 | in = in->ifa_next; |
749 | } | 755 | } |
750 | } | 756 | } |
751 | 757 | ||
752 | return(0); | 758 | return(0); |
753 | } | 759 | } |
@@ -783,8 +789,8 @@ struct sk_buff *ether_adjust_skb(struct sk_buff *skb, int extra) | |||
783 | return(skb); | 789 | return(skb); |
784 | } | 790 | } |
785 | 791 | ||
786 | void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, | 792 | void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, |
787 | void *), | 793 | void *), |
788 | void *arg) | 794 | void *arg) |
789 | { | 795 | { |
790 | struct net_device *dev = d; | 796 | struct net_device *dev = d; |
@@ -809,11 +815,11 @@ int dev_netmask(void *d, void *m) | |||
809 | struct in_ifaddr *in; | 815 | struct in_ifaddr *in; |
810 | __be32 *mask_out = m; | 816 | __be32 *mask_out = m; |
811 | 817 | ||
812 | if(ip == NULL) | 818 | if(ip == NULL) |
813 | return(1); | 819 | return(1); |
814 | 820 | ||
815 | in = ip->ifa_list; | 821 | in = ip->ifa_list; |
816 | if(in == NULL) | 822 | if(in == NULL) |
817 | return(1); | 823 | return(1); |
818 | 824 | ||
819 | *mask_out = in->ifa_mask; | 825 | *mask_out = in->ifa_mask; |
@@ -835,7 +841,7 @@ void free_output_buffer(void *buffer) | |||
835 | free_pages((unsigned long) buffer, 0); | 841 | free_pages((unsigned long) buffer, 0); |
836 | } | 842 | } |
837 | 843 | ||
838 | int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, | 844 | int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, |
839 | char **gate_addr) | 845 | char **gate_addr) |
840 | { | 846 | { |
841 | char *remain; | 847 | char *remain; |
@@ -854,14 +860,3 @@ unsigned short eth_protocol(struct sk_buff *skb) | |||
854 | { | 860 | { |
855 | return(eth_type_trans(skb, skb->dev)); | 861 | return(eth_type_trans(skb, skb->dev)); |
856 | } | 862 | } |
857 | |||
858 | /* | ||
859 | * Overrides for Emacs so that we follow Linus's tabbing style. | ||
860 | * Emacs will notice this stuff at the end of the file and automatically | ||
861 | * adjust the settings for this buffer only. This must remain at the end | ||
862 | * of the file. | ||
863 | * --------------------------------------------------------------------------- | ||
864 | * Local variables: | ||
865 | * c-file-style: "linux" | ||
866 | * End: | ||
867 | */ | ||