diff options
Diffstat (limited to 'arch/um/drivers/net_kern.c')
| -rw-r--r-- | arch/um/drivers/net_kern.c | 81 | 
1 files changed, 46 insertions, 35 deletions
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c index 859303730b2..ac746fb5d10 100644 --- a/arch/um/drivers/net_kern.c +++ b/arch/um/drivers/net_kern.c @@ -325,8 +325,8 @@ static struct platform_driver uml_net_driver = {  };  static int driver_registered; -static int eth_configure(int n, void *init, char *mac, -			 struct transport *transport) +static void eth_configure(int n, void *init, char *mac, +			  struct transport *transport)  {  	struct uml_net *device;  	struct net_device *dev; @@ -339,16 +339,12 @@ static int eth_configure(int n, void *init, char *mac,  	device = kzalloc(sizeof(*device), GFP_KERNEL);  	if (device == NULL) {  		printk(KERN_ERR "eth_configure failed to allocate uml_net\n"); -		return(1); +		return;  	}  	INIT_LIST_HEAD(&device->list);  	device->index = n; -	spin_lock(&devices_lock); -	list_add(&device->list, &devices); -	spin_unlock(&devices_lock); -  	setup_etheraddr(mac, device->mac);  	printk(KERN_INFO "Netdevice %d ", n); @@ -360,7 +356,7 @@ static int eth_configure(int n, void *init, char *mac,  	dev = alloc_etherdev(size);  	if (dev == NULL) {  		printk(KERN_ERR "eth_configure: failed to allocate device\n"); -		return 1; +		goto out_free_device;  	}  	lp = dev->priv; @@ -376,7 +372,8 @@ static int eth_configure(int n, void *init, char *mac,  	}  	device->pdev.id = n;  	device->pdev.name = DRIVER_NAME; -	platform_device_register(&device->pdev); +	if(platform_device_register(&device->pdev)) +		goto out_free_netdev;  	SET_NETDEV_DEV(dev,&device->pdev.dev);  	/* If this name ends up conflicting with an existing registered @@ -386,31 +383,12 @@ static int eth_configure(int n, void *init, char *mac,  	snprintf(dev->name, sizeof(dev->name), "eth%d", n);  	device->dev = dev; +	/* +	 * These just fill in a data structure, so there's no failure +	 * to be worried about. +	 */  	(*transport->kern->init)(dev, init); -	dev->mtu = transport->user->max_packet; -	dev->open = uml_net_open; -	dev->hard_start_xmit = uml_net_start_xmit; -	dev->stop = uml_net_close; -	dev->get_stats = uml_net_get_stats; -	dev->set_multicast_list = uml_net_set_multicast_list; -	dev->tx_timeout = uml_net_tx_timeout; -	dev->set_mac_address = uml_net_set_mac; -	dev->change_mtu = uml_net_change_mtu; -	dev->ethtool_ops = ¨_net_ethtool_ops; -	dev->watchdog_timeo = (HZ >> 1); -	dev->irq = UM_ETH_IRQ; - -	rtnl_lock(); -	err = register_netdevice(dev); -	rtnl_unlock(); -	if (err) { -		device->dev = NULL; -		/* XXX: should we call ->remove() here? */ -		free_netdev(dev); -		return 1; -	} -  	/* lp.user is the first four bytes of the transport data, which  	 * has already been initialized.  This structure assignment will  	 * overwrite that, so we make sure that .user gets overwritten with @@ -438,12 +416,45 @@ static int eth_configure(int n, void *init, char *mac,  	lp->tl.function = uml_net_user_timer_expire;  	memcpy(lp->mac, device->mac, sizeof(lp->mac)); -	if (transport->user->init) -		(*transport->user->init)(&lp->user, dev); +	if ((transport->user->init != NULL) && +	    ((*transport->user->init)(&lp->user, dev) != 0)) +		goto out_unregister;  	set_ether_mac(dev, device->mac); +	dev->mtu = transport->user->max_packet; +	dev->open = uml_net_open; +	dev->hard_start_xmit = uml_net_start_xmit; +	dev->stop = uml_net_close; +	dev->get_stats = uml_net_get_stats; +	dev->set_multicast_list = uml_net_set_multicast_list; +	dev->tx_timeout = uml_net_tx_timeout; +	dev->set_mac_address = uml_net_set_mac; +	dev->change_mtu = uml_net_change_mtu; +	dev->ethtool_ops = ¨_net_ethtool_ops; +	dev->watchdog_timeo = (HZ >> 1); +	dev->irq = UM_ETH_IRQ; -	return 0; +	rtnl_lock(); +	err = register_netdevice(dev); +	rtnl_unlock(); +	if (err) +		goto out_undo_user_init; + +	spin_lock(&devices_lock); +	list_add(&device->list, &devices); +	spin_unlock(&devices_lock); + +	return; + +out_undo_user_init: +	if (transport->user->init != NULL) +		(*transport->user->remove)(&lp->user); +out_unregister: +	platform_device_unregister(&device->pdev); +out_free_netdev: +	free_netdev(dev); +out_free_device: ; +	kfree(device);  }  static struct uml_net *find_device(int n)  |