Re: [PATCH 6/7] net: stmmac: dwc-qos: Split out ->probe() and ->remove()
Às 5:24 PM de 2/23/2017, Thierry Reding escreveu: > From: Thierry Reding> > Split out the binding specific parts of ->probe() and ->remove() to > enable the driver to support variants of the binding. This is useful in > order to keep backwards-compatibility while making it easy for a sub- > driver to deal only with the updated bindings rather than having to add > compatibility quirks all over the place. > > Signed-off-by: Thierry Reding > --- > .../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c| 114 > - > 1 file changed, 88 insertions(+), 26 deletions(-) > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c > b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c > index 1a3fa3d9f855..5071d3c15adc 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c > @@ -18,6 +18,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -106,13 +107,70 @@ static int dwc_eth_dwmac_config_dt(struct > platform_device *pdev, > return 0; > } > > +static void *dwc_qos_probe(struct platform_device *pdev, > +struct plat_stmmacenet_data *plat_dat, > +struct stmmac_resources *stmmac_res) > +{ > + int err; > + > + plat_dat->stmmac_clk = devm_clk_get(>dev, "apb_pclk"); > + if (IS_ERR(plat_dat->stmmac_clk)) { > + dev_err(>dev, "apb_pclk clock not found.\n"); > + return ERR_CAST(plat_dat->stmmac_clk); > + } > + > + clk_prepare_enable(plat_dat->stmmac_clk); > + > + plat_dat->pclk = devm_clk_get(>dev, "phy_ref_clk"); > + if (IS_ERR(plat_dat->pclk)) { > + dev_err(>dev, "phy_ref_clk clock not found.\n"); > + err = PTR_ERR(plat_dat->pclk); > + goto disable; > + } > + > + clk_prepare_enable(plat_dat->pclk); > + > + return NULL; > + > +disable: > + clk_disable_unprepare(plat_dat->stmmac_clk); > + return ERR_PTR(err); > +} > + > +static int dwc_qos_remove(struct platform_device *pdev) > +{ > + struct net_device *ndev = platform_get_drvdata(pdev); > + struct stmmac_priv *priv = netdev_priv(ndev); > + > + clk_disable_unprepare(priv->plat->pclk); > + clk_disable_unprepare(priv->plat->stmmac_clk); > + > + return 0; > +} > + > +struct dwc_eth_dwmac_data { > + void *(*probe)(struct platform_device *pdev, > +struct plat_stmmacenet_data *data, > +struct stmmac_resources *res); > + int (*remove)(struct platform_device *pdev); > +}; > + > +static const struct dwc_eth_dwmac_data dwc_qos_data = { > + .probe = dwc_qos_probe, > + .remove = dwc_qos_remove, > +}; > + > static int dwc_eth_dwmac_probe(struct platform_device *pdev) > { > + const struct dwc_eth_dwmac_data *data; > struct plat_stmmacenet_data *plat_dat; > struct stmmac_resources stmmac_res; > struct resource *res; > + void *priv; > int ret; > > + data = of_device_get_match_data(>dev); > + > memset(_res, 0, sizeof(struct stmmac_resources)); > > /** > @@ -138,39 +196,26 @@ static int dwc_eth_dwmac_probe(struct platform_device > *pdev) > if (IS_ERR(plat_dat)) > return PTR_ERR(plat_dat); > > - plat_dat->stmmac_clk = devm_clk_get(>dev, "apb_pclk"); > - if (IS_ERR(plat_dat->stmmac_clk)) { > - dev_err(>dev, "apb_pclk clock not found.\n"); > - ret = PTR_ERR(plat_dat->stmmac_clk); > - plat_dat->stmmac_clk = NULL; > - goto err_remove_config_dt; > - } > - clk_prepare_enable(plat_dat->stmmac_clk); > - > - plat_dat->pclk = devm_clk_get(>dev, "phy_ref_clk"); > - if (IS_ERR(plat_dat->pclk)) { > - dev_err(>dev, "phy_ref_clk clock not found.\n"); > - ret = PTR_ERR(plat_dat->pclk); > - plat_dat->pclk = NULL; > - goto err_out_clk_dis_phy; > + priv = data->probe(pdev, plat_dat, _res); > + if (IS_ERR(priv)) { > + ret = PTR_ERR(priv); > + dev_err(>dev, "failed to probe subdriver: %d\n", ret); > + goto remove_config; > } > - clk_prepare_enable(plat_dat->pclk); > > ret = dwc_eth_dwmac_config_dt(pdev, plat_dat); > if (ret) > - goto err_out_clk_dis_aper; > + goto remove; > > ret = stmmac_dvr_probe(>dev, plat_dat, _res); > if (ret) > - goto err_out_clk_dis_aper; > + goto remove; > > - return 0; > + return ret; > > -err_out_clk_dis_aper: > - clk_disable_unprepare(plat_dat->pclk); > -err_out_clk_dis_phy: > - clk_disable_unprepare(plat_dat->stmmac_clk); > -err_remove_config_dt: > +remove: > + data->remove(pdev); > +remove_config: > stmmac_remove_config_dt(pdev, plat_dat); > > return ret; > @@ -178,11 +223,28 @@
Re: [PATCH 6/7] net: stmmac: dwc-qos: Split out ->probe() and ->remove()
Às 5:24 PM de 2/23/2017, Thierry Reding escreveu: > From: Thierry Reding > > Split out the binding specific parts of ->probe() and ->remove() to > enable the driver to support variants of the binding. This is useful in > order to keep backwards-compatibility while making it easy for a sub- > driver to deal only with the updated bindings rather than having to add > compatibility quirks all over the place. > > Signed-off-by: Thierry Reding > --- > .../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c| 114 > - > 1 file changed, 88 insertions(+), 26 deletions(-) > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c > b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c > index 1a3fa3d9f855..5071d3c15adc 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c > @@ -18,6 +18,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -106,13 +107,70 @@ static int dwc_eth_dwmac_config_dt(struct > platform_device *pdev, > return 0; > } > > +static void *dwc_qos_probe(struct platform_device *pdev, > +struct plat_stmmacenet_data *plat_dat, > +struct stmmac_resources *stmmac_res) > +{ > + int err; > + > + plat_dat->stmmac_clk = devm_clk_get(>dev, "apb_pclk"); > + if (IS_ERR(plat_dat->stmmac_clk)) { > + dev_err(>dev, "apb_pclk clock not found.\n"); > + return ERR_CAST(plat_dat->stmmac_clk); > + } > + > + clk_prepare_enable(plat_dat->stmmac_clk); > + > + plat_dat->pclk = devm_clk_get(>dev, "phy_ref_clk"); > + if (IS_ERR(plat_dat->pclk)) { > + dev_err(>dev, "phy_ref_clk clock not found.\n"); > + err = PTR_ERR(plat_dat->pclk); > + goto disable; > + } > + > + clk_prepare_enable(plat_dat->pclk); > + > + return NULL; > + > +disable: > + clk_disable_unprepare(plat_dat->stmmac_clk); > + return ERR_PTR(err); > +} > + > +static int dwc_qos_remove(struct platform_device *pdev) > +{ > + struct net_device *ndev = platform_get_drvdata(pdev); > + struct stmmac_priv *priv = netdev_priv(ndev); > + > + clk_disable_unprepare(priv->plat->pclk); > + clk_disable_unprepare(priv->plat->stmmac_clk); > + > + return 0; > +} > + > +struct dwc_eth_dwmac_data { > + void *(*probe)(struct platform_device *pdev, > +struct plat_stmmacenet_data *data, > +struct stmmac_resources *res); > + int (*remove)(struct platform_device *pdev); > +}; > + > +static const struct dwc_eth_dwmac_data dwc_qos_data = { > + .probe = dwc_qos_probe, > + .remove = dwc_qos_remove, > +}; > + > static int dwc_eth_dwmac_probe(struct platform_device *pdev) > { > + const struct dwc_eth_dwmac_data *data; > struct plat_stmmacenet_data *plat_dat; > struct stmmac_resources stmmac_res; > struct resource *res; > + void *priv; > int ret; > > + data = of_device_get_match_data(>dev); > + > memset(_res, 0, sizeof(struct stmmac_resources)); > > /** > @@ -138,39 +196,26 @@ static int dwc_eth_dwmac_probe(struct platform_device > *pdev) > if (IS_ERR(plat_dat)) > return PTR_ERR(plat_dat); > > - plat_dat->stmmac_clk = devm_clk_get(>dev, "apb_pclk"); > - if (IS_ERR(plat_dat->stmmac_clk)) { > - dev_err(>dev, "apb_pclk clock not found.\n"); > - ret = PTR_ERR(plat_dat->stmmac_clk); > - plat_dat->stmmac_clk = NULL; > - goto err_remove_config_dt; > - } > - clk_prepare_enable(plat_dat->stmmac_clk); > - > - plat_dat->pclk = devm_clk_get(>dev, "phy_ref_clk"); > - if (IS_ERR(plat_dat->pclk)) { > - dev_err(>dev, "phy_ref_clk clock not found.\n"); > - ret = PTR_ERR(plat_dat->pclk); > - plat_dat->pclk = NULL; > - goto err_out_clk_dis_phy; > + priv = data->probe(pdev, plat_dat, _res); > + if (IS_ERR(priv)) { > + ret = PTR_ERR(priv); > + dev_err(>dev, "failed to probe subdriver: %d\n", ret); > + goto remove_config; > } > - clk_prepare_enable(plat_dat->pclk); > > ret = dwc_eth_dwmac_config_dt(pdev, plat_dat); > if (ret) > - goto err_out_clk_dis_aper; > + goto remove; > > ret = stmmac_dvr_probe(>dev, plat_dat, _res); > if (ret) > - goto err_out_clk_dis_aper; > + goto remove; > > - return 0; > + return ret; > > -err_out_clk_dis_aper: > - clk_disable_unprepare(plat_dat->pclk); > -err_out_clk_dis_phy: > - clk_disable_unprepare(plat_dat->stmmac_clk); > -err_remove_config_dt: > +remove: > + data->remove(pdev); > +remove_config: > stmmac_remove_config_dt(pdev, plat_dat); > > return ret; > @@ -178,11 +223,28 @@ static int dwc_eth_dwmac_probe(struct
Re: [PATCH 6/7] net: stmmac: dwc-qos: Split out ->probe() and ->remove()
On 23.02.2017 19:24, Thierry Reding wrote: From: Thierry RedingSplit out the binding specific parts of ->probe() and ->remove() to enable the driver to support variants of the binding. This is useful in order to keep backwards-compatibility while making it easy for a sub- driver to deal only with the updated bindings rather than having to add compatibility quirks all over the place. Signed-off-by: Thierry Reding --- .../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c| 114 - 1 file changed, 88 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index 1a3fa3d9f855..5071d3c15adc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -106,13 +107,70 @@ static int dwc_eth_dwmac_config_dt(struct platform_device *pdev, return 0; } +static void *dwc_qos_probe(struct platform_device *pdev, + struct plat_stmmacenet_data *plat_dat, + struct stmmac_resources *stmmac_res) +{ + int err; + + plat_dat->stmmac_clk = devm_clk_get(>dev, "apb_pclk"); + if (IS_ERR(plat_dat->stmmac_clk)) { + dev_err(>dev, "apb_pclk clock not found.\n"); + return ERR_CAST(plat_dat->stmmac_clk); + } + + clk_prepare_enable(plat_dat->stmmac_clk); + + plat_dat->pclk = devm_clk_get(>dev, "phy_ref_clk"); + if (IS_ERR(plat_dat->pclk)) { + dev_err(>dev, "phy_ref_clk clock not found.\n"); + err = PTR_ERR(plat_dat->pclk); + goto disable; + } + + clk_prepare_enable(plat_dat->pclk); + + return NULL; + +disable: + clk_disable_unprepare(plat_dat->stmmac_clk); + return ERR_PTR(err); +} + +static int dwc_qos_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct stmmac_priv *priv = netdev_priv(ndev); + + clk_disable_unprepare(priv->plat->pclk); + clk_disable_unprepare(priv->plat->stmmac_clk); + + return 0; +} + +struct dwc_eth_dwmac_data { + void *(*probe)(struct platform_device *pdev, + struct plat_stmmacenet_data *data, + struct stmmac_resources *res); + int (*remove)(struct platform_device *pdev); +}; + +static const struct dwc_eth_dwmac_data dwc_qos_data = { + .probe = dwc_qos_probe, + .remove = dwc_qos_remove, +}; + static int dwc_eth_dwmac_probe(struct platform_device *pdev) { + const struct dwc_eth_dwmac_data *data; struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; struct resource *res; + void *priv; int ret; + data = of_device_get_match_data(>dev); + memset(_res, 0, sizeof(struct stmmac_resources)); /** @@ -138,39 +196,26 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) if (IS_ERR(plat_dat)) return PTR_ERR(plat_dat); - plat_dat->stmmac_clk = devm_clk_get(>dev, "apb_pclk"); - if (IS_ERR(plat_dat->stmmac_clk)) { - dev_err(>dev, "apb_pclk clock not found.\n"); - ret = PTR_ERR(plat_dat->stmmac_clk); - plat_dat->stmmac_clk = NULL; - goto err_remove_config_dt; - } - clk_prepare_enable(plat_dat->stmmac_clk); - - plat_dat->pclk = devm_clk_get(>dev, "phy_ref_clk"); - if (IS_ERR(plat_dat->pclk)) { - dev_err(>dev, "phy_ref_clk clock not found.\n"); - ret = PTR_ERR(plat_dat->pclk); - plat_dat->pclk = NULL; - goto err_out_clk_dis_phy; + priv = data->probe(pdev, plat_dat, _res); + if (IS_ERR(priv)) { + ret = PTR_ERR(priv); + dev_err(>dev, "failed to probe subdriver: %d\n", ret); + goto remove_config; } - clk_prepare_enable(plat_dat->pclk); ret = dwc_eth_dwmac_config_dt(pdev, plat_dat); if (ret) - goto err_out_clk_dis_aper; + goto remove; ret = stmmac_dvr_probe(>dev, plat_dat, _res); if (ret) - goto err_out_clk_dis_aper; + goto remove; - return 0; + return ret; -err_out_clk_dis_aper: - clk_disable_unprepare(plat_dat->pclk); -err_out_clk_dis_phy: - clk_disable_unprepare(plat_dat->stmmac_clk); -err_remove_config_dt: +remove: + data->remove(pdev); +remove_config: stmmac_remove_config_dt(pdev, plat_dat); return ret; @@ -178,11 +223,28 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) static int dwc_eth_dwmac_remove(struct platform_device *pdev) { - return
Re: [PATCH 6/7] net: stmmac: dwc-qos: Split out ->probe() and ->remove()
On 23.02.2017 19:24, Thierry Reding wrote: From: Thierry Reding Split out the binding specific parts of ->probe() and ->remove() to enable the driver to support variants of the binding. This is useful in order to keep backwards-compatibility while making it easy for a sub- driver to deal only with the updated bindings rather than having to add compatibility quirks all over the place. Signed-off-by: Thierry Reding --- .../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c| 114 - 1 file changed, 88 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index 1a3fa3d9f855..5071d3c15adc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -106,13 +107,70 @@ static int dwc_eth_dwmac_config_dt(struct platform_device *pdev, return 0; } +static void *dwc_qos_probe(struct platform_device *pdev, + struct plat_stmmacenet_data *plat_dat, + struct stmmac_resources *stmmac_res) +{ + int err; + + plat_dat->stmmac_clk = devm_clk_get(>dev, "apb_pclk"); + if (IS_ERR(plat_dat->stmmac_clk)) { + dev_err(>dev, "apb_pclk clock not found.\n"); + return ERR_CAST(plat_dat->stmmac_clk); + } + + clk_prepare_enable(plat_dat->stmmac_clk); + + plat_dat->pclk = devm_clk_get(>dev, "phy_ref_clk"); + if (IS_ERR(plat_dat->pclk)) { + dev_err(>dev, "phy_ref_clk clock not found.\n"); + err = PTR_ERR(plat_dat->pclk); + goto disable; + } + + clk_prepare_enable(plat_dat->pclk); + + return NULL; + +disable: + clk_disable_unprepare(plat_dat->stmmac_clk); + return ERR_PTR(err); +} + +static int dwc_qos_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct stmmac_priv *priv = netdev_priv(ndev); + + clk_disable_unprepare(priv->plat->pclk); + clk_disable_unprepare(priv->plat->stmmac_clk); + + return 0; +} + +struct dwc_eth_dwmac_data { + void *(*probe)(struct platform_device *pdev, + struct plat_stmmacenet_data *data, + struct stmmac_resources *res); + int (*remove)(struct platform_device *pdev); +}; + +static const struct dwc_eth_dwmac_data dwc_qos_data = { + .probe = dwc_qos_probe, + .remove = dwc_qos_remove, +}; + static int dwc_eth_dwmac_probe(struct platform_device *pdev) { + const struct dwc_eth_dwmac_data *data; struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; struct resource *res; + void *priv; int ret; + data = of_device_get_match_data(>dev); + memset(_res, 0, sizeof(struct stmmac_resources)); /** @@ -138,39 +196,26 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) if (IS_ERR(plat_dat)) return PTR_ERR(plat_dat); - plat_dat->stmmac_clk = devm_clk_get(>dev, "apb_pclk"); - if (IS_ERR(plat_dat->stmmac_clk)) { - dev_err(>dev, "apb_pclk clock not found.\n"); - ret = PTR_ERR(plat_dat->stmmac_clk); - plat_dat->stmmac_clk = NULL; - goto err_remove_config_dt; - } - clk_prepare_enable(plat_dat->stmmac_clk); - - plat_dat->pclk = devm_clk_get(>dev, "phy_ref_clk"); - if (IS_ERR(plat_dat->pclk)) { - dev_err(>dev, "phy_ref_clk clock not found.\n"); - ret = PTR_ERR(plat_dat->pclk); - plat_dat->pclk = NULL; - goto err_out_clk_dis_phy; + priv = data->probe(pdev, plat_dat, _res); + if (IS_ERR(priv)) { + ret = PTR_ERR(priv); + dev_err(>dev, "failed to probe subdriver: %d\n", ret); + goto remove_config; } - clk_prepare_enable(plat_dat->pclk); ret = dwc_eth_dwmac_config_dt(pdev, plat_dat); if (ret) - goto err_out_clk_dis_aper; + goto remove; ret = stmmac_dvr_probe(>dev, plat_dat, _res); if (ret) - goto err_out_clk_dis_aper; + goto remove; - return 0; + return ret; -err_out_clk_dis_aper: - clk_disable_unprepare(plat_dat->pclk); -err_out_clk_dis_phy: - clk_disable_unprepare(plat_dat->stmmac_clk); -err_remove_config_dt: +remove: + data->remove(pdev); +remove_config: stmmac_remove_config_dt(pdev, plat_dat); return ret; @@ -178,11 +223,28 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) static int dwc_eth_dwmac_remove(struct platform_device *pdev) { - return stmmac_pltfr_remove(pdev); + struct net_device *ndev =
[PATCH 6/7] net: stmmac: dwc-qos: Split out ->probe() and ->remove()
From: Thierry RedingSplit out the binding specific parts of ->probe() and ->remove() to enable the driver to support variants of the binding. This is useful in order to keep backwards-compatibility while making it easy for a sub- driver to deal only with the updated bindings rather than having to add compatibility quirks all over the place. Signed-off-by: Thierry Reding --- .../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c| 114 - 1 file changed, 88 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index 1a3fa3d9f855..5071d3c15adc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -106,13 +107,70 @@ static int dwc_eth_dwmac_config_dt(struct platform_device *pdev, return 0; } +static void *dwc_qos_probe(struct platform_device *pdev, + struct plat_stmmacenet_data *plat_dat, + struct stmmac_resources *stmmac_res) +{ + int err; + + plat_dat->stmmac_clk = devm_clk_get(>dev, "apb_pclk"); + if (IS_ERR(plat_dat->stmmac_clk)) { + dev_err(>dev, "apb_pclk clock not found.\n"); + return ERR_CAST(plat_dat->stmmac_clk); + } + + clk_prepare_enable(plat_dat->stmmac_clk); + + plat_dat->pclk = devm_clk_get(>dev, "phy_ref_clk"); + if (IS_ERR(plat_dat->pclk)) { + dev_err(>dev, "phy_ref_clk clock not found.\n"); + err = PTR_ERR(plat_dat->pclk); + goto disable; + } + + clk_prepare_enable(plat_dat->pclk); + + return NULL; + +disable: + clk_disable_unprepare(plat_dat->stmmac_clk); + return ERR_PTR(err); +} + +static int dwc_qos_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct stmmac_priv *priv = netdev_priv(ndev); + + clk_disable_unprepare(priv->plat->pclk); + clk_disable_unprepare(priv->plat->stmmac_clk); + + return 0; +} + +struct dwc_eth_dwmac_data { + void *(*probe)(struct platform_device *pdev, + struct plat_stmmacenet_data *data, + struct stmmac_resources *res); + int (*remove)(struct platform_device *pdev); +}; + +static const struct dwc_eth_dwmac_data dwc_qos_data = { + .probe = dwc_qos_probe, + .remove = dwc_qos_remove, +}; + static int dwc_eth_dwmac_probe(struct platform_device *pdev) { + const struct dwc_eth_dwmac_data *data; struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; struct resource *res; + void *priv; int ret; + data = of_device_get_match_data(>dev); + memset(_res, 0, sizeof(struct stmmac_resources)); /** @@ -138,39 +196,26 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) if (IS_ERR(plat_dat)) return PTR_ERR(plat_dat); - plat_dat->stmmac_clk = devm_clk_get(>dev, "apb_pclk"); - if (IS_ERR(plat_dat->stmmac_clk)) { - dev_err(>dev, "apb_pclk clock not found.\n"); - ret = PTR_ERR(plat_dat->stmmac_clk); - plat_dat->stmmac_clk = NULL; - goto err_remove_config_dt; - } - clk_prepare_enable(plat_dat->stmmac_clk); - - plat_dat->pclk = devm_clk_get(>dev, "phy_ref_clk"); - if (IS_ERR(plat_dat->pclk)) { - dev_err(>dev, "phy_ref_clk clock not found.\n"); - ret = PTR_ERR(plat_dat->pclk); - plat_dat->pclk = NULL; - goto err_out_clk_dis_phy; + priv = data->probe(pdev, plat_dat, _res); + if (IS_ERR(priv)) { + ret = PTR_ERR(priv); + dev_err(>dev, "failed to probe subdriver: %d\n", ret); + goto remove_config; } - clk_prepare_enable(plat_dat->pclk); ret = dwc_eth_dwmac_config_dt(pdev, plat_dat); if (ret) - goto err_out_clk_dis_aper; + goto remove; ret = stmmac_dvr_probe(>dev, plat_dat, _res); if (ret) - goto err_out_clk_dis_aper; + goto remove; - return 0; + return ret; -err_out_clk_dis_aper: - clk_disable_unprepare(plat_dat->pclk); -err_out_clk_dis_phy: - clk_disable_unprepare(plat_dat->stmmac_clk); -err_remove_config_dt: +remove: + data->remove(pdev); +remove_config: stmmac_remove_config_dt(pdev, plat_dat); return ret; @@ -178,11 +223,28 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) static int dwc_eth_dwmac_remove(struct platform_device *pdev) { - return stmmac_pltfr_remove(pdev); + struct net_device *ndev
[PATCH 6/7] net: stmmac: dwc-qos: Split out ->probe() and ->remove()
From: Thierry Reding Split out the binding specific parts of ->probe() and ->remove() to enable the driver to support variants of the binding. This is useful in order to keep backwards-compatibility while making it easy for a sub- driver to deal only with the updated bindings rather than having to add compatibility quirks all over the place. Signed-off-by: Thierry Reding --- .../ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c| 114 - 1 file changed, 88 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index 1a3fa3d9f855..5071d3c15adc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -106,13 +107,70 @@ static int dwc_eth_dwmac_config_dt(struct platform_device *pdev, return 0; } +static void *dwc_qos_probe(struct platform_device *pdev, + struct plat_stmmacenet_data *plat_dat, + struct stmmac_resources *stmmac_res) +{ + int err; + + plat_dat->stmmac_clk = devm_clk_get(>dev, "apb_pclk"); + if (IS_ERR(plat_dat->stmmac_clk)) { + dev_err(>dev, "apb_pclk clock not found.\n"); + return ERR_CAST(plat_dat->stmmac_clk); + } + + clk_prepare_enable(plat_dat->stmmac_clk); + + plat_dat->pclk = devm_clk_get(>dev, "phy_ref_clk"); + if (IS_ERR(plat_dat->pclk)) { + dev_err(>dev, "phy_ref_clk clock not found.\n"); + err = PTR_ERR(plat_dat->pclk); + goto disable; + } + + clk_prepare_enable(plat_dat->pclk); + + return NULL; + +disable: + clk_disable_unprepare(plat_dat->stmmac_clk); + return ERR_PTR(err); +} + +static int dwc_qos_remove(struct platform_device *pdev) +{ + struct net_device *ndev = platform_get_drvdata(pdev); + struct stmmac_priv *priv = netdev_priv(ndev); + + clk_disable_unprepare(priv->plat->pclk); + clk_disable_unprepare(priv->plat->stmmac_clk); + + return 0; +} + +struct dwc_eth_dwmac_data { + void *(*probe)(struct platform_device *pdev, + struct plat_stmmacenet_data *data, + struct stmmac_resources *res); + int (*remove)(struct platform_device *pdev); +}; + +static const struct dwc_eth_dwmac_data dwc_qos_data = { + .probe = dwc_qos_probe, + .remove = dwc_qos_remove, +}; + static int dwc_eth_dwmac_probe(struct platform_device *pdev) { + const struct dwc_eth_dwmac_data *data; struct plat_stmmacenet_data *plat_dat; struct stmmac_resources stmmac_res; struct resource *res; + void *priv; int ret; + data = of_device_get_match_data(>dev); + memset(_res, 0, sizeof(struct stmmac_resources)); /** @@ -138,39 +196,26 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) if (IS_ERR(plat_dat)) return PTR_ERR(plat_dat); - plat_dat->stmmac_clk = devm_clk_get(>dev, "apb_pclk"); - if (IS_ERR(plat_dat->stmmac_clk)) { - dev_err(>dev, "apb_pclk clock not found.\n"); - ret = PTR_ERR(plat_dat->stmmac_clk); - plat_dat->stmmac_clk = NULL; - goto err_remove_config_dt; - } - clk_prepare_enable(plat_dat->stmmac_clk); - - plat_dat->pclk = devm_clk_get(>dev, "phy_ref_clk"); - if (IS_ERR(plat_dat->pclk)) { - dev_err(>dev, "phy_ref_clk clock not found.\n"); - ret = PTR_ERR(plat_dat->pclk); - plat_dat->pclk = NULL; - goto err_out_clk_dis_phy; + priv = data->probe(pdev, plat_dat, _res); + if (IS_ERR(priv)) { + ret = PTR_ERR(priv); + dev_err(>dev, "failed to probe subdriver: %d\n", ret); + goto remove_config; } - clk_prepare_enable(plat_dat->pclk); ret = dwc_eth_dwmac_config_dt(pdev, plat_dat); if (ret) - goto err_out_clk_dis_aper; + goto remove; ret = stmmac_dvr_probe(>dev, plat_dat, _res); if (ret) - goto err_out_clk_dis_aper; + goto remove; - return 0; + return ret; -err_out_clk_dis_aper: - clk_disable_unprepare(plat_dat->pclk); -err_out_clk_dis_phy: - clk_disable_unprepare(plat_dat->stmmac_clk); -err_remove_config_dt: +remove: + data->remove(pdev); +remove_config: stmmac_remove_config_dt(pdev, plat_dat); return ret; @@ -178,11 +223,28 @@ static int dwc_eth_dwmac_probe(struct platform_device *pdev) static int dwc_eth_dwmac_remove(struct platform_device *pdev) { - return stmmac_pltfr_remove(pdev); + struct net_device *ndev = platform_get_drvdata(pdev); +