Message ID | 48ceed6b5d7b32c2e46b79fa597466b9212f745e.1691047285.git.chenfeiyang@loongson.cn (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | stmmac: Add Loongson platform support | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Guessing tree name failed - patch did not apply |
On Thu, Aug 03, 2023 at 07:30:34PM +0800, Feiyang Chen wrote: > Set 64-Bit DMA for specific versions. Request allocation for multi- > vector interrupts for DWLGMAC_CORE_1_00. If it fails, fallback to > request allocation for single interrupts. > > Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn> > --- > .../ethernet/stmicro/stmmac/dwmac-loongson.c | 83 ++++++++++++++++++- > 1 file changed, 81 insertions(+), 2 deletions(-) > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c > index c7790f73fe18..18bca996e1cb 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c > @@ -6,11 +6,15 @@ > #include <linux/pci.h> > #include <linux/dmi.h> > #include <linux/device.h> > +#include <linux/interrupt.h> > #include <linux/of_irq.h> > +#include "dwmac1000.h" > #include "stmmac.h" > > struct stmmac_pci_info { > int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat); > + int (*config)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat, > + struct stmmac_resources *res); > }; > > static void loongson_default_data(struct pci_dev *pdev, > @@ -66,14 +70,54 @@ static int loongson_gmac_data(struct pci_dev *pdev, > return 0; > } > > +static int loongson_gmac_config(struct pci_dev *pdev, > + struct plat_stmmacenet_data *plat, > + struct stmmac_resources *res) > +{ > + u32 version = readl(res->addr + GMAC_VERSION); > + > + switch (version & 0xff) { > + case DWLGMAC_CORE_1_00: > + plat->multi_msi_en = 1; > + plat->rx_queues_to_use = 8; > + plat->tx_queues_to_use = 8; > + plat->fix_channel_num = true; > + break; > + case DWMAC_CORE_3_50: > + case DWMAC_CORE_3_70: > + if (version & 0x00008000) { > + plat->host_dma_width = 64; > + plat->dma_cfg->dma64 = true; > + } > + break; > + default: > + break; > + } > + > + plat->dma_reset_times = 5; > + > + return 0; > +} > + > static struct stmmac_pci_info loongson_gmac_pci_info = { > .setup = loongson_gmac_data, > + .config = loongson_gmac_config, > }; > > +static u32 get_irq_type(struct device_node *np) > +{ > + struct of_phandle_args oirq; > + > + if (np && of_irq_parse_one(np, 0, &oirq) == 0 && oirq.args_count == 2) > + return oirq.args[1]; > + > + return IRQF_TRIGGER_RISING; > +} > + I do wish that there was some IRQ maintainer I could bounce this over to for them to comment on, because I don't believe that this should be necessary in any driver - the irq subsystem should configure the IRQ accordingly before the driver is probed. But since I don't know that code, and can't be bothered at this point to read through it and DT yet again, I don't feel qualified to comment on this... Maybe someone else can be bothered to comment on it... If not, then I suppose it will have to do as-is, and maybe someone at a later date can fix it if it needs fixing.
> > +static u32 get_irq_type(struct device_node *np) > > +{ > > + struct of_phandle_args oirq; > > + > > + if (np && of_irq_parse_one(np, 0, &oirq) == 0 && oirq.args_count == 2) > > + return oirq.args[1]; > > + > > + return IRQF_TRIGGER_RISING; > > +} > > + > > I do wish that there was some IRQ maintainer I could bounce this over to > for them to comment on, because I don't believe that this should be > necessary in any driver - the irq subsystem should configure the IRQ > accordingly before the driver is probed. I agree with you, this is very likely to be wrong. Feiyang, please look at other drivers and copy with they do. Andrew
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index c7790f73fe18..18bca996e1cb 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -6,11 +6,15 @@ #include <linux/pci.h> #include <linux/dmi.h> #include <linux/device.h> +#include <linux/interrupt.h> #include <linux/of_irq.h> +#include "dwmac1000.h" #include "stmmac.h" struct stmmac_pci_info { int (*setup)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat); + int (*config)(struct pci_dev *pdev, struct plat_stmmacenet_data *plat, + struct stmmac_resources *res); }; static void loongson_default_data(struct pci_dev *pdev, @@ -66,14 +70,54 @@ static int loongson_gmac_data(struct pci_dev *pdev, return 0; } +static int loongson_gmac_config(struct pci_dev *pdev, + struct plat_stmmacenet_data *plat, + struct stmmac_resources *res) +{ + u32 version = readl(res->addr + GMAC_VERSION); + + switch (version & 0xff) { + case DWLGMAC_CORE_1_00: + plat->multi_msi_en = 1; + plat->rx_queues_to_use = 8; + plat->tx_queues_to_use = 8; + plat->fix_channel_num = true; + break; + case DWMAC_CORE_3_50: + case DWMAC_CORE_3_70: + if (version & 0x00008000) { + plat->host_dma_width = 64; + plat->dma_cfg->dma64 = true; + } + break; + default: + break; + } + + plat->dma_reset_times = 5; + + return 0; +} + static struct stmmac_pci_info loongson_gmac_pci_info = { .setup = loongson_gmac_data, + .config = loongson_gmac_config, }; +static u32 get_irq_type(struct device_node *np) +{ + struct of_phandle_args oirq; + + if (np && of_irq_parse_one(np, 0, &oirq) == 0 && oirq.args_count == 2) + return oirq.args[1]; + + return IRQF_TRIGGER_RISING; +} + static int loongson_dwmac_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int ret, i, bus_id, phy_mode; + int ret, i, bus_id, phy_mode, ch_cnt, vecs; struct plat_stmmacenet_data *plat; struct stmmac_pci_info *info; struct stmmac_resources res; @@ -170,12 +214,46 @@ static int loongson_dwmac_probe(struct pci_dev *pdev, res.wol_irq = pdev->irq; } - ret = stmmac_dvr_probe(&pdev->dev, plat, &res); + ret = info->config(pdev, plat, &res); if (ret) goto err_disable_msi; + if (plat->multi_msi_en) { + ch_cnt = plat->rx_queues_to_use; + + pci_disable_msi(pdev); + + res.irq = pci_irq_vector(pdev, 0); + res.wol_irq = res.irq; + vecs = roundup_pow_of_two(ch_cnt * 2 + 1); + if (pci_alloc_irq_vectors(pdev, vecs, vecs, PCI_IRQ_MSI) < 0) { + dev_info(&pdev->dev, + "MSI enable failed, Fallback to line interrupt\n"); + plat->multi_msi_en = 0; + } else { + /* INT NAME | MAC | CH7 rx | CH7 tx | ... | CH0 rx | CH0 tx | + * --------- ----- -------- -------- ... -------- -------- + * IRQ NUM | 0 | 1 | 2 | ... | 15 | 16 | + */ + for (i = 0; i < ch_cnt; i++) { + res.rx_irq[ch_cnt - 1 - i] = pci_irq_vector(pdev, 1 + i * 2); + res.tx_irq[ch_cnt - 1 - i] = pci_irq_vector(pdev, 2 + i * 2); + } + + plat->control_value = GMAC_CONTROL_ACS; + plat->irq_flags = get_irq_type(np); + } + } + + ret = stmmac_dvr_probe(&pdev->dev, plat, &res); + if (ret) + goto err_free_irq_vectors; + return ret; +err_free_irq_vectors: + if (plat->multi_msi_en) + pci_free_irq_vectors(pdev); err_disable_msi: pci_disable_msi(pdev); err_disable_device: @@ -201,6 +279,7 @@ static void loongson_dwmac_remove(struct pci_dev *pdev) break; } + pci_free_irq_vectors(pdev); pci_disable_msi(pdev); pci_disable_device(pdev); }
Set 64-Bit DMA for specific versions. Request allocation for multi- vector interrupts for DWLGMAC_CORE_1_00. If it fails, fallback to request allocation for single interrupts. Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn> --- .../ethernet/stmicro/stmmac/dwmac-loongson.c | 83 ++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-)