phy: core: Add consumer device link support
In order to enforce suspend/resume ordering, this commit creates link between phy consumers and phy devices. This link avoids to suspend phy before phy consumers. Signed-off-by: Alexandre Torgue <alexandre.torgue@st.com> [jonathanh@nvidia.com: Fix an abort when of_phy_get() returns error] Signed-off-by: Jonathan Hunter <jonathanh@nvidia.com> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>
This commit is contained in:
parent
24dbe0aaa0
commit
987351e1ea
|
@ -29,7 +29,7 @@ static void devm_phy_release(struct device *dev, void *res)
|
|||
{
|
||||
struct phy *phy = *(struct phy **)res;
|
||||
|
||||
phy_put(phy);
|
||||
phy_put(dev, phy);
|
||||
}
|
||||
|
||||
static void devm_phy_provider_release(struct device *dev, void *res)
|
||||
|
@ -566,12 +566,12 @@ struct phy *of_phy_get(struct device_node *np, const char *con_id)
|
|||
EXPORT_SYMBOL_GPL(of_phy_get);
|
||||
|
||||
/**
|
||||
* phy_put() - release the PHY
|
||||
* @phy: the phy returned by phy_get()
|
||||
* of_phy_put() - release the PHY
|
||||
* @phy: the phy returned by of_phy_get()
|
||||
*
|
||||
* Releases a refcount the caller received from phy_get().
|
||||
* Releases a refcount the caller received from of_phy_get().
|
||||
*/
|
||||
void phy_put(struct phy *phy)
|
||||
void of_phy_put(struct phy *phy)
|
||||
{
|
||||
if (!phy || IS_ERR(phy))
|
||||
return;
|
||||
|
@ -584,6 +584,20 @@ void phy_put(struct phy *phy)
|
|||
module_put(phy->ops->owner);
|
||||
put_device(&phy->dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(of_phy_put);
|
||||
|
||||
/**
|
||||
* phy_put() - release the PHY
|
||||
* @dev: device that wants to release this phy
|
||||
* @phy: the phy returned by phy_get()
|
||||
*
|
||||
* Releases a refcount the caller received from phy_get().
|
||||
*/
|
||||
void phy_put(struct device *dev, struct phy *phy)
|
||||
{
|
||||
device_link_remove(dev, &phy->dev);
|
||||
of_phy_put(phy);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phy_put);
|
||||
|
||||
/**
|
||||
|
@ -651,6 +665,7 @@ struct phy *phy_get(struct device *dev, const char *string)
|
|||
{
|
||||
int index = 0;
|
||||
struct phy *phy;
|
||||
struct device_link *link;
|
||||
|
||||
if (string == NULL) {
|
||||
dev_WARN(dev, "missing string\n");
|
||||
|
@ -672,6 +687,13 @@ struct phy *phy_get(struct device *dev, const char *string)
|
|||
|
||||
get_device(&phy->dev);
|
||||
|
||||
link = device_link_add(dev, &phy->dev, DL_FLAG_STATELESS);
|
||||
if (!link) {
|
||||
dev_err(dev, "failed to create device link to %s\n",
|
||||
dev_name(phy->dev.parent));
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return phy;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phy_get);
|
||||
|
@ -765,6 +787,7 @@ struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
|
|||
const char *con_id)
|
||||
{
|
||||
struct phy **ptr, *phy;
|
||||
struct device_link *link;
|
||||
|
||||
ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
|
@ -776,6 +799,14 @@ struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
|
|||
devres_add(dev, ptr);
|
||||
} else {
|
||||
devres_free(ptr);
|
||||
return phy;
|
||||
}
|
||||
|
||||
link = device_link_add(dev, &phy->dev, DL_FLAG_STATELESS);
|
||||
if (!link) {
|
||||
dev_err(dev, "failed to create device link to %s\n",
|
||||
dev_name(phy->dev.parent));
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return phy;
|
||||
|
@ -798,6 +829,7 @@ struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np,
|
|||
int index)
|
||||
{
|
||||
struct phy **ptr, *phy;
|
||||
struct device_link *link;
|
||||
|
||||
ptr = devres_alloc(devm_phy_release, sizeof(*ptr), GFP_KERNEL);
|
||||
if (!ptr)
|
||||
|
@ -819,6 +851,13 @@ struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np,
|
|||
*ptr = phy;
|
||||
devres_add(dev, ptr);
|
||||
|
||||
link = device_link_add(dev, &phy->dev, DL_FLAG_STATELESS);
|
||||
if (!link) {
|
||||
dev_err(dev, "failed to create device link to %s\n",
|
||||
dev_name(phy->dev.parent));
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return phy;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_of_phy_get_by_index);
|
||||
|
|
|
@ -34,7 +34,7 @@ static int usbhs_rcar2_hardware_exit(struct platform_device *pdev)
|
|||
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
|
||||
|
||||
if (priv->phy) {
|
||||
phy_put(priv->phy);
|
||||
phy_put(&pdev->dev, priv->phy);
|
||||
priv->phy = NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ static int usbhs_rza2_hardware_exit(struct platform_device *pdev)
|
|||
{
|
||||
struct usbhs_priv *priv = usbhs_pdev_to_priv(pdev);
|
||||
|
||||
phy_put(priv->phy);
|
||||
phy_put(&pdev->dev, priv->phy);
|
||||
priv->phy = NULL;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -234,7 +234,8 @@ struct phy *devm_of_phy_get(struct device *dev, struct device_node *np,
|
|||
const char *con_id);
|
||||
struct phy *devm_of_phy_get_by_index(struct device *dev, struct device_node *np,
|
||||
int index);
|
||||
void phy_put(struct phy *phy);
|
||||
void of_phy_put(struct phy *phy);
|
||||
void phy_put(struct device *dev, struct phy *phy);
|
||||
void devm_phy_put(struct device *dev, struct phy *phy);
|
||||
struct phy *of_phy_get(struct device_node *np, const char *con_id);
|
||||
struct phy *of_phy_simple_xlate(struct device *dev,
|
||||
|
@ -419,7 +420,11 @@ static inline struct phy *devm_of_phy_get_by_index(struct device *dev,
|
|||
return ERR_PTR(-ENOSYS);
|
||||
}
|
||||
|
||||
static inline void phy_put(struct phy *phy)
|
||||
static inline void of_phy_put(struct phy *phy)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void phy_put(struct device *dev, struct phy *phy)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue