Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * This file contains all networking devres helpers.
0004  */
0005 
0006 #include <linux/device.h>
0007 #include <linux/etherdevice.h>
0008 #include <linux/netdevice.h>
0009 
0010 struct net_device_devres {
0011     struct net_device *ndev;
0012 };
0013 
0014 static void devm_free_netdev(struct device *dev, void *this)
0015 {
0016     struct net_device_devres *res = this;
0017 
0018     free_netdev(res->ndev);
0019 }
0020 
0021 struct net_device *devm_alloc_etherdev_mqs(struct device *dev, int sizeof_priv,
0022                        unsigned int txqs, unsigned int rxqs)
0023 {
0024     struct net_device_devres *dr;
0025 
0026     dr = devres_alloc(devm_free_netdev, sizeof(*dr), GFP_KERNEL);
0027     if (!dr)
0028         return NULL;
0029 
0030     dr->ndev = alloc_etherdev_mqs(sizeof_priv, txqs, rxqs);
0031     if (!dr->ndev) {
0032         devres_free(dr);
0033         return NULL;
0034     }
0035 
0036     devres_add(dev, dr);
0037 
0038     return dr->ndev;
0039 }
0040 EXPORT_SYMBOL(devm_alloc_etherdev_mqs);
0041 
0042 static void devm_unregister_netdev(struct device *dev, void *this)
0043 {
0044     struct net_device_devres *res = this;
0045 
0046     unregister_netdev(res->ndev);
0047 }
0048 
0049 static int netdev_devres_match(struct device *dev, void *this, void *match_data)
0050 {
0051     struct net_device_devres *res = this;
0052     struct net_device *ndev = match_data;
0053 
0054     return ndev == res->ndev;
0055 }
0056 
0057 /**
0058  *  devm_register_netdev - resource managed variant of register_netdev()
0059  *  @dev: managing device for this netdev - usually the parent device
0060  *  @ndev: device to register
0061  *
0062  *  This is a devres variant of register_netdev() for which the unregister
0063  *  function will be called automatically when the managing device is
0064  *  detached. Note: the net_device used must also be resource managed by
0065  *  the same struct device.
0066  */
0067 int devm_register_netdev(struct device *dev, struct net_device *ndev)
0068 {
0069     struct net_device_devres *dr;
0070     int ret;
0071 
0072     /* struct net_device must itself be managed. For now a managed netdev
0073      * can only be allocated by devm_alloc_etherdev_mqs() so the check is
0074      * straightforward.
0075      */
0076     if (WARN_ON(!devres_find(dev, devm_free_netdev,
0077                  netdev_devres_match, ndev)))
0078         return -EINVAL;
0079 
0080     dr = devres_alloc(devm_unregister_netdev, sizeof(*dr), GFP_KERNEL);
0081     if (!dr)
0082         return -ENOMEM;
0083 
0084     ret = register_netdev(ndev);
0085     if (ret) {
0086         devres_free(dr);
0087         return ret;
0088     }
0089 
0090     dr->ndev = ndev;
0091     devres_add(ndev->dev.parent, dr);
0092 
0093     return 0;
0094 }
0095 EXPORT_SYMBOL(devm_register_netdev);