forked from mirrors/linux
		
	 51a1ebc35b
			
		
	
	
		51a1ebc35b
		
	
	
	
	
		
			
			Correct a grammatical error. Signed-off-by: gushengxian <gushengxian@yulong.com> Signed-off-by: David S. Miller <davem@davemloft.net>
		
			
				
	
	
		
			95 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| // SPDX-License-Identifier: GPL-2.0-or-later
 | |
| /*
 | |
|  * This file contains all networking devres helpers.
 | |
|  */
 | |
| 
 | |
| #include <linux/device.h>
 | |
| #include <linux/etherdevice.h>
 | |
| #include <linux/netdevice.h>
 | |
| 
 | |
| struct net_device_devres {
 | |
| 	struct net_device *ndev;
 | |
| };
 | |
| 
 | |
| static void devm_free_netdev(struct device *dev, void *this)
 | |
| {
 | |
| 	struct net_device_devres *res = this;
 | |
| 
 | |
| 	free_netdev(res->ndev);
 | |
| }
 | |
| 
 | |
| struct net_device *devm_alloc_etherdev_mqs(struct device *dev, int sizeof_priv,
 | |
| 					   unsigned int txqs, unsigned int rxqs)
 | |
| {
 | |
| 	struct net_device_devres *dr;
 | |
| 
 | |
| 	dr = devres_alloc(devm_free_netdev, sizeof(*dr), GFP_KERNEL);
 | |
| 	if (!dr)
 | |
| 		return NULL;
 | |
| 
 | |
| 	dr->ndev = alloc_etherdev_mqs(sizeof_priv, txqs, rxqs);
 | |
| 	if (!dr->ndev) {
 | |
| 		devres_free(dr);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 
 | |
| 	devres_add(dev, dr);
 | |
| 
 | |
| 	return dr->ndev;
 | |
| }
 | |
| EXPORT_SYMBOL(devm_alloc_etherdev_mqs);
 | |
| 
 | |
| static void devm_unregister_netdev(struct device *dev, void *this)
 | |
| {
 | |
| 	struct net_device_devres *res = this;
 | |
| 
 | |
| 	unregister_netdev(res->ndev);
 | |
| }
 | |
| 
 | |
| static int netdev_devres_match(struct device *dev, void *this, void *match_data)
 | |
| {
 | |
| 	struct net_device_devres *res = this;
 | |
| 	struct net_device *ndev = match_data;
 | |
| 
 | |
| 	return ndev == res->ndev;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  *	devm_register_netdev - resource managed variant of register_netdev()
 | |
|  *	@dev: managing device for this netdev - usually the parent device
 | |
|  *	@ndev: device to register
 | |
|  *
 | |
|  *	This is a devres variant of register_netdev() for which the unregister
 | |
|  *	function will be called automatically when the managing device is
 | |
|  *	detached. Note: the net_device used must also be resource managed by
 | |
|  *	the same struct device.
 | |
|  */
 | |
| int devm_register_netdev(struct device *dev, struct net_device *ndev)
 | |
| {
 | |
| 	struct net_device_devres *dr;
 | |
| 	int ret;
 | |
| 
 | |
| 	/* struct net_device must itself be managed. For now a managed netdev
 | |
| 	 * can only be allocated by devm_alloc_etherdev_mqs() so the check is
 | |
| 	 * straightforward.
 | |
| 	 */
 | |
| 	if (WARN_ON(!devres_find(dev, devm_free_netdev,
 | |
| 				 netdev_devres_match, ndev)))
 | |
| 		return -EINVAL;
 | |
| 
 | |
| 	dr = devres_alloc(devm_unregister_netdev, sizeof(*dr), GFP_KERNEL);
 | |
| 	if (!dr)
 | |
| 		return -ENOMEM;
 | |
| 
 | |
| 	ret = register_netdev(ndev);
 | |
| 	if (ret) {
 | |
| 		devres_free(dr);
 | |
| 		return ret;
 | |
| 	}
 | |
| 
 | |
| 	dr->ndev = ndev;
 | |
| 	devres_add(ndev->dev.parent, dr);
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| EXPORT_SYMBOL(devm_register_netdev);
 |