diff mbox series

[net-next,v15,11/14] net: stmmac: dwmac-loongson: Add DT-less GMAC PCI-device support

Message ID 359b2c226e7b18d4af8bb827ca26a2e7869d5f85.1722253726.git.siyanteng@loongson.cn (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series stmmac: Add Loongson platform support | expand

Checks

Context Check Description
netdev/series_format success Posting correctly formatted
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 42 this patch: 42
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers warning 6 maintainers not CCed: linux-arm-kernel@lists.infradead.org mcoquelin.stm32@gmail.com edumazet@google.com linux-stm32@st-md-mailman.stormreply.com kuba@kernel.org pabeni@redhat.com
netdev/build_clang success Errors and warnings before: 43 this patch: 43
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 43 this patch: 43
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 226 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0
netdev/contest success net-next-2024-07-29--18-00 (tests: 703)

Commit Message

Yanteng Si July 29, 2024, 12:23 p.m. UTC
The Loongson GMAC driver currently supports the network controllers
installed on the LS2K1000 SoC and LS7A1000 chipset, for which the GMAC
devices are required to be defined in the platform device tree source.
But Loongson machines may have UEFI (implies ACPI) or PMON/UBOOT
(implies FDT) as the system bootloaders. In order to have both system
configurations support let's extend the driver functionality with the
case of having the Loongson GMAC probed on the PCI bus with no device
tree node defined for it. That requires to make the device DT-node
optional, to rely on the IRQ line detected by the PCI core and to
have the MDIO bus ID calculated using the PCIe Domain+BDF numbers.

In order to have the device probe() and remove() methods less
complicated let's move the DT- and ACPI-specific code to the
respective sub-functions.

Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
Acked-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
---
 .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 159 +++++++++++-------
 1 file changed, 100 insertions(+), 59 deletions(-)

Comments

Paolo Abeni Aug. 1, 2024, 11:32 a.m. UTC | #1
On 7/29/24 14:23, Yanteng Si wrote:
> The Loongson GMAC driver currently supports the network controllers
> installed on the LS2K1000 SoC and LS7A1000 chipset, for which the GMAC
> devices are required to be defined in the platform device tree source.
> But Loongson machines may have UEFI (implies ACPI) or PMON/UBOOT
> (implies FDT) as the system bootloaders. In order to have both system
> configurations support let's extend the driver functionality with the
> case of having the Loongson GMAC probed on the PCI bus with no device
> tree node defined for it. That requires to make the device DT-node
> optional, to rely on the IRQ line detected by the PCI core and to
> have the MDIO bus ID calculated using the PCIe Domain+BDF numbers.
> 
> In order to have the device probe() and remove() methods less
> complicated let's move the DT- and ACPI-specific code to the
> respective sub-functions.
> 
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> Acked-by: Huacai Chen <chenhuacai@loongson.cn>
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>

@Serge: I think this addresses your comment on the previous iteration, 
but it would be great if you could have a look!

Thanks,

Paolo
Serge Semin Aug. 1, 2024, 11:48 a.m. UTC | #2
Hi Paolo

On Thu, Aug 01, 2024 at 01:32:56PM +0200, Paolo Abeni wrote:
> On 7/29/24 14:23, Yanteng Si wrote:
> > The Loongson GMAC driver currently supports the network controllers
> > installed on the LS2K1000 SoC and LS7A1000 chipset, for which the GMAC
> > devices are required to be defined in the platform device tree source.
> > But Loongson machines may have UEFI (implies ACPI) or PMON/UBOOT
> > (implies FDT) as the system bootloaders. In order to have both system
> > configurations support let's extend the driver functionality with the
> > case of having the Loongson GMAC probed on the PCI bus with no device
> > tree node defined for it. That requires to make the device DT-node
> > optional, to rely on the IRQ line detected by the PCI core and to
> > have the MDIO bus ID calculated using the PCIe Domain+BDF numbers.
> > 
> > In order to have the device probe() and remove() methods less
> > complicated let's move the DT- and ACPI-specific code to the
> > respective sub-functions.
> > 
> > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > Acked-by: Huacai Chen <chenhuacai@loongson.cn>
> > Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> 
> @Serge: I think this addresses your comment on the previous iteration, but
> it would be great if you could have a look!

Thanks for reaching me out. I'll have a look at the series later
today.

-Serge(y)

> 
> Thanks,
> 
> Paolo
>
Serge Semin Aug. 1, 2024, 4:50 p.m. UTC | #3
Hi Yanteng,

On Mon, Jul 29, 2024 at 08:23:55PM +0800, Yanteng Si wrote:
> The Loongson GMAC driver currently supports the network controllers
> installed on the LS2K1000 SoC and LS7A1000 chipset, for which the GMAC
> devices are required to be defined in the platform device tree source.
> But Loongson machines may have UEFI (implies ACPI) or PMON/UBOOT
> (implies FDT) as the system bootloaders. In order to have both system
> configurations support let's extend the driver functionality with the
> case of having the Loongson GMAC probed on the PCI bus with no device
> tree node defined for it. That requires to make the device DT-node
> optional, to rely on the IRQ line detected by the PCI core and to
> have the MDIO bus ID calculated using the PCIe Domain+BDF numbers.
> 
> In order to have the device probe() and remove() methods less
> complicated let's move the DT- and ACPI-specific code to the
> respective sub-functions.
> 
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> Acked-by: Huacai Chen <chenhuacai@loongson.cn>
> Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> ---
>  .../ethernet/stmicro/stmmac/dwmac-loongson.c  | 159 +++++++++++-------
>  1 file changed, 100 insertions(+), 59 deletions(-)
> 
> diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> index 10b49bea8e3c..010821fb6474 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> @@ -12,11 +12,15 @@
>  #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
>  
>  struct stmmac_pci_info {
> -	int (*setup)(struct plat_stmmacenet_data *plat);
> +	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
>  };
>  
> -static void loongson_default_data(struct plat_stmmacenet_data *plat)
> +static void loongson_default_data(struct pci_dev *pdev,
> +				  struct plat_stmmacenet_data *plat)
>  {
> +	/* Get bus_id, this can be overwritten later */
> +	plat->bus_id = pci_dev_id(pdev);
> +
>  	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
>  	plat->has_gmac = 1;
>  	plat->force_sf_dma_mode = 1;
> @@ -49,9 +53,10 @@ static void loongson_default_data(struct plat_stmmacenet_data *plat)
>  	plat->dma_cfg->pblx8 = true;
>  }
>  
> -static int loongson_gmac_data(struct plat_stmmacenet_data *plat)
> +static int loongson_gmac_data(struct pci_dev *pdev,
> +			      struct plat_stmmacenet_data *plat)
>  {
> -	loongson_default_data(plat);
> +	loongson_default_data(pdev, plat);
>  
>  	plat->tx_queues_to_use = 1;
>  	plat->rx_queues_to_use = 1;
> @@ -65,20 +70,83 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
>  	.setup = loongson_gmac_data,
>  };
>  
> +static int loongson_dwmac_dt_config(struct pci_dev *pdev,
> +				    struct plat_stmmacenet_data *plat,
> +				    struct stmmac_resources *res)
> +{
> +	struct device_node *np = dev_of_node(&pdev->dev);
> +	int ret;
> +
> +	plat->mdio_node = of_get_child_by_name(np, "mdio");
> +	if (plat->mdio_node) {
> +		dev_info(&pdev->dev, "Found MDIO subnode\n");
> +		plat->mdio_bus_data->needs_reset = true;
> +	}
> +
> +	ret = of_alias_get_id(np, "ethernet");
> +	if (ret >= 0)
> +		plat->bus_id = ret;
> +
> +	res->irq = of_irq_get_byname(np, "macirq");
> +	if (res->irq < 0) {
> +		dev_err(&pdev->dev, "IRQ macirq not found\n");
> +		ret = -ENODEV;
> +		goto err_put_node;
> +	}
> +
> +	res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> +	if (res->wol_irq < 0) {
> +		dev_info(&pdev->dev,
> +			 "IRQ eth_wake_irq not found, using macirq\n");
> +		res->wol_irq = res->irq;
> +	}
> +
> +	res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
> +	if (res->lpi_irq < 0) {
> +		dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> +		ret = -ENODEV;
> +		goto err_put_node;
> +	}
> +
> +	ret = device_get_phy_mode(&pdev->dev);
> +	if (ret < 0) {
> +		dev_err(&pdev->dev, "phy_mode not found\n");
> +		ret = -ENODEV;
> +		goto err_put_node;
> +	}
> +
> +	plat->phy_interface = ret;
> +
> +err_put_node:
> +	of_node_put(plat->mdio_node);
> +
> +	return ret;
> +}
> +
> +static void loongson_dwmac_dt_clear(struct pci_dev *pdev,
> +				    struct plat_stmmacenet_data *plat)
> +{
> +	of_node_put(plat->mdio_node);
> +}
> +
> +static int loongson_dwmac_acpi_config(struct pci_dev *pdev,
> +				      struct plat_stmmacenet_data *plat,
> +				      struct stmmac_resources *res)
> +{
> +	if (!pdev->irq)
> +		return -EINVAL;
> +
> +	res->irq = pdev->irq;
> +
> +	return 0;
> +}
> +
>  static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id)
>  {
>  	struct plat_stmmacenet_data *plat;
>  	struct stmmac_pci_info *info;
>  	struct stmmac_resources res;
> -	struct device_node *np;
> -	int ret, i, phy_mode;
> -
> -	np = dev_of_node(&pdev->dev);
> -
> -	if (!np) {
> -		pr_info("dwmac_loongson_pci: No OF node\n");
> -		return -ENODEV;
> -	}
> +	int ret, i;
>  
>  	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
>  	if (!plat)
> @@ -90,17 +158,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  	if (!plat->mdio_bus_data)
>  		return -ENOMEM;
>  
> -	plat->mdio_node = of_get_child_by_name(np, "mdio");
> -	if (plat->mdio_node) {
> -		dev_info(&pdev->dev, "Found MDIO subnode\n");
> -		plat->mdio_bus_data->needs_reset = true;
> -	}
> -
>  	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
> -	if (!plat->dma_cfg) {
> -		ret = -ENOMEM;
> -		goto err_put_node;
> -	}
> +	if (!plat->dma_cfg)
> +		return -ENOMEM;
>  
>  	/* Enable pci device */
>  	ret = pci_enable_device(pdev);
> @@ -109,6 +169,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id

>  		goto err_put_node;

		return ret;

* Once again BTW.

>  	}
>  
> +	pci_set_master(pdev);
> +
>  	/* Get the base address of device */
>  	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
>  		if (pci_resource_len(pdev, i) == 0)
> @@ -119,57 +181,33 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
>  		break;
>  	}
>  
> -	plat->bus_id = of_alias_get_id(np, "ethernet");
> -	if (plat->bus_id < 0)
> -		plat->bus_id = pci_dev_id(pdev);
> -
> -	phy_mode = device_get_phy_mode(&pdev->dev);
> -	if (phy_mode < 0) {
> -		dev_err(&pdev->dev, "phy_mode not found\n");
> -		ret = phy_mode;
> -		goto err_disable_device;
> -	}
> -
> -	plat->phy_interface = phy_mode;
> -
> -	pci_set_master(pdev);
> -
>  	memset(&res, 0, sizeof(res));
>  	res.addr = pcim_iomap_table(pdev)[0];
>  
>  	info = (struct stmmac_pci_info *)id->driver_data;
> -	ret = info->setup(plat);
> +	ret = info->setup(pdev, plat);
>  	if (ret)
>  		goto err_disable_device;
>  
> -	res.irq = of_irq_get_byname(np, "macirq");
> -	if (res.irq < 0) {
> -		dev_err(&pdev->dev, "IRQ macirq not found\n");
> -		ret = -ENODEV;
> -		goto err_disable_device;
> -	}
> -
> -	res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> -	if (res.wol_irq < 0) {
> -		dev_info(&pdev->dev, "IRQ eth_wake_irq not found, using macirq\n");
> -		res.wol_irq = res.irq;
> -	}
> -
> -	res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
> -	if (res.lpi_irq < 0) {
> -		dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> -		ret = -ENODEV;
> +	if (dev_of_node(&pdev->dev))
> +		ret = loongson_dwmac_dt_config(pdev, plat, &res);
> +	else
> +		ret = loongson_dwmac_acpi_config(pdev, plat, &res);
> +	if (ret)
>  		goto err_disable_device;
> -	}
>  
>  	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
>  	if (ret)
> -		goto err_disable_device;
> +		goto err_plat_clear;
>  
> -	return ret;
> +	return 0;
>  
> +err_plat_clear:
> +	if (dev_of_node(&pdev->dev))
> +		loongson_dwmac_dt_clear(pdev, plat);
>  err_disable_device:
>  	pci_disable_device(pdev);
> +	return ret;

>  err_put_node:
>  	of_node_put(plat->mdio_node);
>  	return ret;

The main point of my v14 comment was to completely move the
of_node_put(plat->mdio_node) call to the DT-config/clear methods
(since it's OF-related config) and setting the loongson_dwmac_probe()
method free from the direct MDIO-node putting. Don't you see that
calling of_node_put() in the loongson_dwmac_probe() and
loongson_dwmac_remove() is now redundant?

Moreover don't you find the next chunk being weird:

err_disable_device:
  	pci_disable_device(pdev);
+	return ret;

err_put_node:
 	of_node_put(plat->mdio_node);
 	return ret;

? Two return statements in a single cleanup-on-error path. After
dropping the "err_put_node" label and the respective statements, the
cleanup-on-error path will turn to being saner.

> @@ -184,6 +222,9 @@ static void loongson_dwmac_remove(struct pci_dev *pdev)

>  	of_node_put(priv->plat->mdio_node);

This is done in the loongson_dwmac_dt_clear() method. So the direct
of_node_put() call should be dropped.

-Serge(y)

>  	stmmac_dvr_remove(&pdev->dev);
>  
> +	if (dev_of_node(&pdev->dev))
> +		loongson_dwmac_dt_clear(pdev, priv->plat);
> +
>  	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
>  		if (pci_resource_len(pdev, i) == 0)
>  			continue;
> -- 
> 2.31.4
>
Yanteng Si Aug. 4, 2024, 3:13 p.m. UTC | #4
2024年8月2日 00:50, "Serge Semin" <fancer.lancer@gmail.com> 写到:



> 
> Hi Yanteng,
> 
> On Mon, Jul 29, 2024 at 08:23:55PM +0800, Yanteng Si wrote:
> 
> > 
> > The Loongson GMAC driver currently supports the network controllers
> > 
> >  installed on the LS2K1000 SoC and LS7A1000 chipset, for which the GMAC
> > 
> >  devices are required to be defined in the platform device tree source.
> > 
> >  But Loongson machines may have UEFI (implies ACPI) or PMON/UBOOT
> > 
> >  (implies FDT) as the system bootloaders. In order to have both system
> > 
> >  configurations support let's extend the driver functionality with the
> > 
> >  case of having the Loongson GMAC probed on the PCI bus with no device
> > 
> >  tree node defined for it. That requires to make the device DT-node
> > 
> >  optional, to rely on the IRQ line detected by the PCI core and to
> > 
> >  have the MDIO bus ID calculated using the PCIe Domain+BDF numbers.
> > 
> >  
> > 
> >  In order to have the device probe() and remove() methods less
> > 
> >  complicated let's move the DT- and ACPI-specific code to the
> > 
> >  respective sub-functions.
> > 
> >  
> > 
> >  Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> > 
> >  Signed-off-by: Yinggang Gu <guyinggang@loongson.cn>
> > 
> >  Acked-by: Huacai Chen <chenhuacai@loongson.cn>
> > 
> >  Signed-off-by: Yanteng Si <siyanteng@loongson.cn>
> > 
> >  ---
> > 
> >  .../ethernet/stmicro/stmmac/dwmac-loongson.c | 159 +++++++++++-------
> > 
> >  1 file changed, 100 insertions(+), 59 deletions(-)
> > 
> >  
> > 
> >  diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > 
> >  index 10b49bea8e3c..010821fb6474 100644
> > 
> >  --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > 
> >  +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
> > 
> >  @@ -12,11 +12,15 @@
> > 
> >  #define PCI_DEVICE_ID_LOONGSON_GMAC 0x7a03
> > 
> >  
> > 
> >  struct stmmac_pci_info {
> > 
> >  - int (*setup)(struct plat_stmmacenet_data *plat);
> > 
> >  + int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
> > 
> >  };
> > 
> >  
> > 
> >  -static void loongson_default_data(struct plat_stmmacenet_data *plat)
> > 
> >  +static void loongson_default_data(struct pci_dev *pdev,
> > 
> >  + struct plat_stmmacenet_data *plat)
> > 
> >  {
> > 
> >  + /* Get bus_id, this can be overwritten later */
> > 
> >  + plat->bus_id = pci_dev_id(pdev);
> > 
> >  +
> > 
> >  plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
> > 
> >  plat->has_gmac = 1;
> > 
> >  plat->force_sf_dma_mode = 1;
> > 
> >  @@ -49,9 +53,10 @@ static void loongson_default_data(struct plat_stmmacenet_data *plat)
> > 
> >  plat->dma_cfg->pblx8 = true;
> > 
> >  }
> > 
> >  
> > 
> >  -static int loongson_gmac_data(struct plat_stmmacenet_data *plat)
> > 
> >  +static int loongson_gmac_data(struct pci_dev *pdev,
> > 
> >  + struct plat_stmmacenet_data *plat)
> > 
> >  {
> > 
> >  - loongson_default_data(plat);
> > 
> >  + loongson_default_data(pdev, plat);
> > 
> >  
> > 
> >  plat->tx_queues_to_use = 1;
> > 
> >  plat->rx_queues_to_use = 1;
> > 
> >  @@ -65,20 +70,83 @@ static struct stmmac_pci_info loongson_gmac_pci_info = {
> > 
> >  .setup = loongson_gmac_data,
> > 
> >  };
> > 
> >  
> > 
> >  +static int loongson_dwmac_dt_config(struct pci_dev *pdev,
> > 
> >  + struct plat_stmmacenet_data *plat,
> > 
> >  + struct stmmac_resources *res)
> > 
> >  +{
> > 
> >  + struct device_node *np = dev_of_node(&pdev->dev);
> > 
> >  + int ret;
> > 
> >  +
> > 
> >  + plat->mdio_node = of_get_child_by_name(np, "mdio");
> > 
> >  + if (plat->mdio_node) {
> > 
> >  + dev_info(&pdev->dev, "Found MDIO subnode\n");
> > 
> >  + plat->mdio_bus_data->needs_reset = true;
> > 
> >  + }
> > 
> >  +
> > 
> >  + ret = of_alias_get_id(np, "ethernet");
> > 
> >  + if (ret >= 0)
> > 
> >  + plat->bus_id = ret;
> > 
> >  +
> > 
> >  + res->irq = of_irq_get_byname(np, "macirq");
> > 
> >  + if (res->irq < 0) {
> > 
> >  + dev_err(&pdev->dev, "IRQ macirq not found\n");
> > 
> >  + ret = -ENODEV;
> > 
> >  + goto err_put_node;
> > 
> >  + }
> > 
> >  +
> > 
> >  + res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> > 
> >  + if (res->wol_irq < 0) {
> > 
> >  + dev_info(&pdev->dev,
> > 
> >  + "IRQ eth_wake_irq not found, using macirq\n");
> > 
> >  + res->wol_irq = res->irq;
> > 
> >  + }
> > 
> >  +
> > 
> >  + res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
> > 
> >  + if (res->lpi_irq < 0) {
> > 
> >  + dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> > 
> >  + ret = -ENODEV;
> > 
> >  + goto err_put_node;
> > 
> >  + }
> > 
> >  +
> > 
> >  + ret = device_get_phy_mode(&pdev->dev);
> > 
> >  + if (ret < 0) {
> > 
> >  + dev_err(&pdev->dev, "phy_mode not found\n");
> > 
> >  + ret = -ENODEV;
> > 
> >  + goto err_put_node;
> > 
> >  + }
> > 
> >  +
> > 
> >  + plat->phy_interface = ret;
> > 
> >  +
> > 
> >  +err_put_node:
> > 
> >  + of_node_put(plat->mdio_node);
> > 
> >  +
> > 
> >  + return ret;
> > 
> >  +}
> > 
> >  +
> > 
> >  +static void loongson_dwmac_dt_clear(struct pci_dev *pdev,
> > 
> >  + struct plat_stmmacenet_data *plat)
> > 
> >  +{
> > 
> >  + of_node_put(plat->mdio_node);
> > 
> >  +}
> > 
> >  +
> > 
> >  +static int loongson_dwmac_acpi_config(struct pci_dev *pdev,
> > 
> >  + struct plat_stmmacenet_data *plat,
> > 
> >  + struct stmmac_resources *res)
> > 
> >  +{
> > 
> >  + if (!pdev->irq)
> > 
> >  + return -EINVAL;
> > 
> >  +
> > 
> >  + res->irq = pdev->irq;
> > 
> >  +
> > 
> >  + return 0;
> > 
> >  +}
> > 
> >  +
> > 
> >  static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id)
> > 
> >  {
> > 
> >  struct plat_stmmacenet_data *plat;
> > 
> >  struct stmmac_pci_info *info;
> > 
> >  struct stmmac_resources res;
> > 
> >  - struct device_node *np;
> > 
> >  - int ret, i, phy_mode;
> > 
> >  -
> > 
> >  - np = dev_of_node(&pdev->dev);
> > 
> >  -
> > 
> >  - if (!np) {
> > 
> >  - pr_info("dwmac_loongson_pci: No OF node\n");
> > 
> >  - return -ENODEV;
> > 
> >  - }
> > 
> >  + int ret, i;
> > 
> >  
> > 
> >  plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
> > 
> >  if (!plat)
> > 
> >  @@ -90,17 +158,9 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
> > 
> >  if (!plat->mdio_bus_data)
> > 
> >  return -ENOMEM;
> > 
> >  
> > 
> >  - plat->mdio_node = of_get_child_by_name(np, "mdio");
> > 
> >  - if (plat->mdio_node) {
> > 
> >  - dev_info(&pdev->dev, "Found MDIO subnode\n");
> > 
> >  - plat->mdio_bus_data->needs_reset = true;
> > 
> >  - }
> > 
> >  -
> > 
> >  plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
> > 
> >  - if (!plat->dma_cfg) {
> > 
> >  - ret = -ENOMEM;
> > 
> >  - goto err_put_node;
> > 
> >  - }
> > 
> >  + if (!plat->dma_cfg)
> > 
> >  + return -ENOMEM;
> > 
> >  
> > 
> >  /* Enable pci device */
> > 
> >  ret = pci_enable_device(pdev);
> > 
> >  @@ -109,6 +169,8 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
> > 
> >  goto err_put_node;
> > 
> 
>  return ret;
> 
> * Once again BTW.
> 
> > 
> > }
> > 
> >  
> > 
> >  + pci_set_master(pdev);
> > 
> >  +
> > 
> >  /* Get the base address of device */
> > 
> >  for (i = 0; i < PCI_STD_NUM_BARS; i++) {
> > 
> >  if (pci_resource_len(pdev, i) == 0)
> > 
> >  @@ -119,57 +181,33 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
> > 
> >  break;
> > 
> >  }
> > 
> >  
> > 
> >  - plat->bus_id = of_alias_get_id(np, "ethernet");
> > 
> >  - if (plat->bus_id < 0)
> > 
> >  - plat->bus_id = pci_dev_id(pdev);
> > 
> >  -
> > 
> >  - phy_mode = device_get_phy_mode(&pdev->dev);
> > 
> >  - if (phy_mode < 0) {
> > 
> >  - dev_err(&pdev->dev, "phy_mode not found\n");
> > 
> >  - ret = phy_mode;
> > 
> >  - goto err_disable_device;
> > 
> >  - }
> > 
> >  -
> > 
> >  - plat->phy_interface = phy_mode;
> > 
> >  -
> > 
> >  - pci_set_master(pdev);
> > 
> >  -
> > 
> >  memset(&res, 0, sizeof(res));
> > 
> >  res.addr = pcim_iomap_table(pdev)[0];
> > 
> >  
> > 
> >  info = (struct stmmac_pci_info *)id->driver_data;
> > 
> >  - ret = info->setup(plat);
> > 
> >  + ret = info->setup(pdev, plat);
> > 
> >  if (ret)
> > 
> >  goto err_disable_device;
> > 
> >  
> > 
> >  - res.irq = of_irq_get_byname(np, "macirq");
> > 
> >  - if (res.irq < 0) {
> > 
> >  - dev_err(&pdev->dev, "IRQ macirq not found\n");
> > 
> >  - ret = -ENODEV;
> > 
> >  - goto err_disable_device;
> > 
> >  - }
> > 
> >  -
> > 
> >  - res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
> > 
> >  - if (res.wol_irq < 0) {
> > 
> >  - dev_info(&pdev->dev, "IRQ eth_wake_irq not found, using macirq\n");
> > 
> >  - res.wol_irq = res.irq;
> > 
> >  - }
> > 
> >  -
> > 
> >  - res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
> > 
> >  - if (res.lpi_irq < 0) {
> > 
> >  - dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
> > 
> >  - ret = -ENODEV;
> > 
> >  + if (dev_of_node(&pdev->dev))
> > 
> >  + ret = loongson_dwmac_dt_config(pdev, plat, &res);
> > 
> >  + else
> > 
> >  + ret = loongson_dwmac_acpi_config(pdev, plat, &res);
> > 
> >  + if (ret)
> > 
> >  goto err_disable_device;
> > 
> >  - }
> > 
> >  
> > 
> >  ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
> > 
> >  if (ret)
> > 
> >  - goto err_disable_device;
> > 
> >  + goto err_plat_clear;
> > 
> >  
> > 
> >  - return ret;
> > 
> >  + return 0;
> > 
> >  
> > 
> >  +err_plat_clear:
> > 
> >  + if (dev_of_node(&pdev->dev))
> > 
> >  + loongson_dwmac_dt_clear(pdev, plat);
> > 
> >  err_disable_device:
> > 
> >  pci_disable_device(pdev);
> > 
> >  + return ret;
> > 
> >  err_put_node:
> > 
> >  of_node_put(plat->mdio_node);
> > 
> >  return ret;
> > 
> 
> The main point of my v14 comment was to completely move the
> 
> of_node_put(plat->mdio_node) call to the DT-config/clear methods
> 
> (since it's OF-related config) and setting the loongson_dwmac_probe()
> 
> method free from the direct MDIO-node putting. Don't you see that
> 
> calling of_node_put() in the loongson_dwmac_probe() and
> 
> loongson_dwmac_remove() is now redundant?
Oh, I see! Thanks!


Thanks,
Yanteng
diff mbox series

Patch

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
index 10b49bea8e3c..010821fb6474 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c
@@ -12,11 +12,15 @@ 
 #define PCI_DEVICE_ID_LOONGSON_GMAC	0x7a03
 
 struct stmmac_pci_info {
-	int (*setup)(struct plat_stmmacenet_data *plat);
+	int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat);
 };
 
-static void loongson_default_data(struct plat_stmmacenet_data *plat)
+static void loongson_default_data(struct pci_dev *pdev,
+				  struct plat_stmmacenet_data *plat)
 {
+	/* Get bus_id, this can be overwritten later */
+	plat->bus_id = pci_dev_id(pdev);
+
 	plat->clk_csr = 2;	/* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
 	plat->has_gmac = 1;
 	plat->force_sf_dma_mode = 1;
@@ -49,9 +53,10 @@  static void loongson_default_data(struct plat_stmmacenet_data *plat)
 	plat->dma_cfg->pblx8 = true;
 }
 
-static int loongson_gmac_data(struct plat_stmmacenet_data *plat)
+static int loongson_gmac_data(struct pci_dev *pdev,
+			      struct plat_stmmacenet_data *plat)
 {
-	loongson_default_data(plat);
+	loongson_default_data(pdev, plat);
 
 	plat->tx_queues_to_use = 1;
 	plat->rx_queues_to_use = 1;
@@ -65,20 +70,83 @@  static struct stmmac_pci_info loongson_gmac_pci_info = {
 	.setup = loongson_gmac_data,
 };
 
+static int loongson_dwmac_dt_config(struct pci_dev *pdev,
+				    struct plat_stmmacenet_data *plat,
+				    struct stmmac_resources *res)
+{
+	struct device_node *np = dev_of_node(&pdev->dev);
+	int ret;
+
+	plat->mdio_node = of_get_child_by_name(np, "mdio");
+	if (plat->mdio_node) {
+		dev_info(&pdev->dev, "Found MDIO subnode\n");
+		plat->mdio_bus_data->needs_reset = true;
+	}
+
+	ret = of_alias_get_id(np, "ethernet");
+	if (ret >= 0)
+		plat->bus_id = ret;
+
+	res->irq = of_irq_get_byname(np, "macirq");
+	if (res->irq < 0) {
+		dev_err(&pdev->dev, "IRQ macirq not found\n");
+		ret = -ENODEV;
+		goto err_put_node;
+	}
+
+	res->wol_irq = of_irq_get_byname(np, "eth_wake_irq");
+	if (res->wol_irq < 0) {
+		dev_info(&pdev->dev,
+			 "IRQ eth_wake_irq not found, using macirq\n");
+		res->wol_irq = res->irq;
+	}
+
+	res->lpi_irq = of_irq_get_byname(np, "eth_lpi");
+	if (res->lpi_irq < 0) {
+		dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
+		ret = -ENODEV;
+		goto err_put_node;
+	}
+
+	ret = device_get_phy_mode(&pdev->dev);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "phy_mode not found\n");
+		ret = -ENODEV;
+		goto err_put_node;
+	}
+
+	plat->phy_interface = ret;
+
+err_put_node:
+	of_node_put(plat->mdio_node);
+
+	return ret;
+}
+
+static void loongson_dwmac_dt_clear(struct pci_dev *pdev,
+				    struct plat_stmmacenet_data *plat)
+{
+	of_node_put(plat->mdio_node);
+}
+
+static int loongson_dwmac_acpi_config(struct pci_dev *pdev,
+				      struct plat_stmmacenet_data *plat,
+				      struct stmmac_resources *res)
+{
+	if (!pdev->irq)
+		return -EINVAL;
+
+	res->irq = pdev->irq;
+
+	return 0;
+}
+
 static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct plat_stmmacenet_data *plat;
 	struct stmmac_pci_info *info;
 	struct stmmac_resources res;
-	struct device_node *np;
-	int ret, i, phy_mode;
-
-	np = dev_of_node(&pdev->dev);
-
-	if (!np) {
-		pr_info("dwmac_loongson_pci: No OF node\n");
-		return -ENODEV;
-	}
+	int ret, i;
 
 	plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL);
 	if (!plat)
@@ -90,17 +158,9 @@  static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 	if (!plat->mdio_bus_data)
 		return -ENOMEM;
 
-	plat->mdio_node = of_get_child_by_name(np, "mdio");
-	if (plat->mdio_node) {
-		dev_info(&pdev->dev, "Found MDIO subnode\n");
-		plat->mdio_bus_data->needs_reset = true;
-	}
-
 	plat->dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*plat->dma_cfg), GFP_KERNEL);
-	if (!plat->dma_cfg) {
-		ret = -ENOMEM;
-		goto err_put_node;
-	}
+	if (!plat->dma_cfg)
+		return -ENOMEM;
 
 	/* Enable pci device */
 	ret = pci_enable_device(pdev);
@@ -109,6 +169,8 @@  static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 		goto err_put_node;
 	}
 
+	pci_set_master(pdev);
+
 	/* Get the base address of device */
 	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
 		if (pci_resource_len(pdev, i) == 0)
@@ -119,57 +181,33 @@  static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id
 		break;
 	}
 
-	plat->bus_id = of_alias_get_id(np, "ethernet");
-	if (plat->bus_id < 0)
-		plat->bus_id = pci_dev_id(pdev);
-
-	phy_mode = device_get_phy_mode(&pdev->dev);
-	if (phy_mode < 0) {
-		dev_err(&pdev->dev, "phy_mode not found\n");
-		ret = phy_mode;
-		goto err_disable_device;
-	}
-
-	plat->phy_interface = phy_mode;
-
-	pci_set_master(pdev);
-
 	memset(&res, 0, sizeof(res));
 	res.addr = pcim_iomap_table(pdev)[0];
 
 	info = (struct stmmac_pci_info *)id->driver_data;
-	ret = info->setup(plat);
+	ret = info->setup(pdev, plat);
 	if (ret)
 		goto err_disable_device;
 
-	res.irq = of_irq_get_byname(np, "macirq");
-	if (res.irq < 0) {
-		dev_err(&pdev->dev, "IRQ macirq not found\n");
-		ret = -ENODEV;
-		goto err_disable_device;
-	}
-
-	res.wol_irq = of_irq_get_byname(np, "eth_wake_irq");
-	if (res.wol_irq < 0) {
-		dev_info(&pdev->dev, "IRQ eth_wake_irq not found, using macirq\n");
-		res.wol_irq = res.irq;
-	}
-
-	res.lpi_irq = of_irq_get_byname(np, "eth_lpi");
-	if (res.lpi_irq < 0) {
-		dev_err(&pdev->dev, "IRQ eth_lpi not found\n");
-		ret = -ENODEV;
+	if (dev_of_node(&pdev->dev))
+		ret = loongson_dwmac_dt_config(pdev, plat, &res);
+	else
+		ret = loongson_dwmac_acpi_config(pdev, plat, &res);
+	if (ret)
 		goto err_disable_device;
-	}
 
 	ret = stmmac_dvr_probe(&pdev->dev, plat, &res);
 	if (ret)
-		goto err_disable_device;
+		goto err_plat_clear;
 
-	return ret;
+	return 0;
 
+err_plat_clear:
+	if (dev_of_node(&pdev->dev))
+		loongson_dwmac_dt_clear(pdev, plat);
 err_disable_device:
 	pci_disable_device(pdev);
+	return ret;
 err_put_node:
 	of_node_put(plat->mdio_node);
 	return ret;
@@ -184,6 +222,9 @@  static void loongson_dwmac_remove(struct pci_dev *pdev)
 	of_node_put(priv->plat->mdio_node);
 	stmmac_dvr_remove(&pdev->dev);
 
+	if (dev_of_node(&pdev->dev))
+		loongson_dwmac_dt_clear(pdev, priv->plat);
+
 	for (i = 0; i < PCI_STD_NUM_BARS; i++) {
 		if (pci_resource_len(pdev, i) == 0)
 			continue;