aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers/net_kern.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/net_kern.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/net_kern.c')
-rw-r--r--arch/um/drivers/net_kern.c97
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:
159static int uml_net_close(struct net_device *dev) 159static 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
466static int eth_parse(char *str, int *index_out, char **str_out) 466static 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
497struct eth_init { 495struct eth_init {
@@ -581,11 +579,15 @@ static int eth_setup_common(char *str, int index)
581static int eth_setup(char *str) 579static 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(&eth->list); 622 list_del(&eth->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
628static int net_config(char *str) 630static 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
661static int net_remove(int n) 667static 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 = {
727static int uml_net_init(void) 733static 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
786void iter_addresses(void *d, void (*cb)(unsigned char *, unsigned char *, 792void 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
838int tap_setup_common(char *str, char *type, char **dev_name, char **mac_out, 844int 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 */