int unregister_netdevice(struct net_device *dev)
{
	struct net_device *d, **dp;

	BUG_ON(dev_boot_phase);
	ASSERT_RTNL();

	/* Some devices call without registering for initialization unwind. */
	if (dev->reg_state == NETREG_UNINITIALIZED) {
		printk(KERN_DEBUG "unregister_netdevice: device %s/%p never "
				  "was registered\n", dev->name, dev);
		return -ENODEV;
	}

	BUG_ON(dev->reg_state != NETREG_REGISTERED);

	/* If device is running, close it first. */
	if (dev->flags & IFF_UP)
		dev_close(dev);

	/* And unlink it from device chain. */
	for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) {
		if (d == dev) {
			write_lock_bh(&dev_base_lock);
			hlist_del(&dev->name_hlist);
			hlist_del(&dev->index_hlist);
			if (dev_tail == &dev->next)
				dev_tail = dp;
			*dp = d->next;
			write_unlock_bh(&dev_base_lock);
			break;
		}
	}
	if (!d) {
		printk(KERN_ERR "unregister net_device: '%s' not found\n",
		       dev->name);
		return -ENODEV;
	}

	dev->reg_state = NETREG_UNREGISTERING;

	synchronize_net();

	/* Shutdown queueing discipline. */
	dev_shutdown(dev);

	
	/* Notify protocols, that we are about to destroy
	   this device. They should clean all the things.
	*/
	notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
	
	/*
	 *	Flush the multicast chain
	 */
	dev_mc_discard(dev);

	if (dev->uninit)
		dev->uninit(dev);

	/* Notifier chain MUST detach us from master device. */
	BUG_TRAP(!dev->master);

	free_divert_blk(dev);

	/* Finish processing unregister after unlock */
	net_set_todo(dev);

	synchronize_net();

	dev_put(dev);
	return 0;
}
int unregister_netdevice(struct net_device *dev)
{
	struct net_device *d, **dp;

	BUG_ON(dev_boot_phase);
	ASSERT_RTNL();

	 
	if (dev->reg_state == NETREG_UNINITIALIZED) {
		printk(KERN_DEBUG "unregister_netdevice: device %s/%p never "
				  "was registered\n", dev->name, dev);
		return -ENODEV;
	}

	BUG_ON(dev->reg_state != NETREG_REGISTERED);

	 
	if (dev->flags & IFF_UP)
		dev_close(dev);

	 
	for (dp = &dev_base; (d = *dp) != NULL; dp = &d->next) {
		if (d == dev) {
			write_lock_bh(&dev_base_lock);
			hlist_del(&dev->name_hlist);
			hlist_del(&dev->index_hlist);
			if (dev_tail == &dev->next)
				dev_tail = dp;
			*dp = d->next;
			write_unlock_bh(&dev_base_lock);
			break;
		}
	}
	if (!d) {
		printk(KERN_ERR "unregister net_device: '%s' not found\n",
		       dev->name);
		return -ENODEV;
	}

	dev->reg_state = NETREG_UNREGISTERING;

	synchronize_net();

	 
	dev_shutdown(dev);

	
	 
	notifier_call_chain(&netdev_chain, NETDEV_UNREGISTER, dev);
	
	 
	dev_mc_discard(dev);

	if (dev->uninit)
		dev->uninit(dev);

	 
	BUG_TRAP(!dev->master);

	free_divert_blk(dev);

	 
	net_set_todo(dev);

	synchronize_net();

	dev_put(dev);
	return 0;
}