Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 
0003 #include <linux/device.h>
0004 #include <linux/of_mdio.h>
0005 #include <linux/phy.h>
0006 #include <linux/stddef.h>
0007 
0008 struct mdiobus_devres {
0009     struct mii_bus *mii;
0010 };
0011 
0012 static void devm_mdiobus_free(struct device *dev, void *this)
0013 {
0014     struct mdiobus_devres *dr = this;
0015 
0016     mdiobus_free(dr->mii);
0017 }
0018 
0019 /**
0020  * devm_mdiobus_alloc_size - Resource-managed mdiobus_alloc_size()
0021  * @dev:        Device to allocate mii_bus for
0022  * @sizeof_priv:    Space to allocate for private structure
0023  *
0024  * Managed mdiobus_alloc_size. mii_bus allocated with this function is
0025  * automatically freed on driver detach.
0026  *
0027  * RETURNS:
0028  * Pointer to allocated mii_bus on success, NULL on out-of-memory error.
0029  */
0030 struct mii_bus *devm_mdiobus_alloc_size(struct device *dev, int sizeof_priv)
0031 {
0032     struct mdiobus_devres *dr;
0033 
0034     dr = devres_alloc(devm_mdiobus_free, sizeof(*dr), GFP_KERNEL);
0035     if (!dr)
0036         return NULL;
0037 
0038     dr->mii = mdiobus_alloc_size(sizeof_priv);
0039     if (!dr->mii) {
0040         devres_free(dr);
0041         return NULL;
0042     }
0043 
0044     devres_add(dev, dr);
0045     return dr->mii;
0046 }
0047 EXPORT_SYMBOL(devm_mdiobus_alloc_size);
0048 
0049 static void devm_mdiobus_unregister(struct device *dev, void *this)
0050 {
0051     struct mdiobus_devres *dr = this;
0052 
0053     mdiobus_unregister(dr->mii);
0054 }
0055 
0056 static int mdiobus_devres_match(struct device *dev,
0057                 void *this, void *match_data)
0058 {
0059     struct mdiobus_devres *res = this;
0060     struct mii_bus *mii = match_data;
0061 
0062     return mii == res->mii;
0063 }
0064 
0065 /**
0066  * __devm_mdiobus_register - Resource-managed variant of mdiobus_register()
0067  * @dev:    Device to register mii_bus for
0068  * @bus:    MII bus structure to register
0069  * @owner:  Owning module
0070  *
0071  * Returns 0 on success, negative error number on failure.
0072  */
0073 int __devm_mdiobus_register(struct device *dev, struct mii_bus *bus,
0074                 struct module *owner)
0075 {
0076     struct mdiobus_devres *dr;
0077     int ret;
0078 
0079     if (WARN_ON(!devres_find(dev, devm_mdiobus_free,
0080                  mdiobus_devres_match, bus)))
0081         return -EINVAL;
0082 
0083     dr = devres_alloc(devm_mdiobus_unregister, sizeof(*dr), GFP_KERNEL);
0084     if (!dr)
0085         return -ENOMEM;
0086 
0087     ret = __mdiobus_register(bus, owner);
0088     if (ret) {
0089         devres_free(dr);
0090         return ret;
0091     }
0092 
0093     dr->mii = bus;
0094     devres_add(dev, dr);
0095     return 0;
0096 }
0097 EXPORT_SYMBOL(__devm_mdiobus_register);
0098 
0099 #if IS_ENABLED(CONFIG_OF_MDIO)
0100 /**
0101  * devm_of_mdiobus_register - Resource managed variant of of_mdiobus_register()
0102  * @dev:    Device to register mii_bus for
0103  * @mdio:   MII bus structure to register
0104  * @np:     Device node to parse
0105  */
0106 int devm_of_mdiobus_register(struct device *dev, struct mii_bus *mdio,
0107                  struct device_node *np)
0108 {
0109     struct mdiobus_devres *dr;
0110     int ret;
0111 
0112     if (WARN_ON(!devres_find(dev, devm_mdiobus_free,
0113                  mdiobus_devres_match, mdio)))
0114         return -EINVAL;
0115 
0116     dr = devres_alloc(devm_mdiobus_unregister, sizeof(*dr), GFP_KERNEL);
0117     if (!dr)
0118         return -ENOMEM;
0119 
0120     ret = of_mdiobus_register(mdio, np);
0121     if (ret) {
0122         devres_free(dr);
0123         return ret;
0124     }
0125 
0126     dr->mii = mdio;
0127     devres_add(dev, dr);
0128     return 0;
0129 }
0130 EXPORT_SYMBOL(devm_of_mdiobus_register);
0131 #endif /* CONFIG_OF_MDIO */
0132 
0133 MODULE_LICENSE("GPL");