Re: [PATCH v7 1/5] net: wan: Add support for QMC HDLC
Herve Codina writes: > Hi Michael, > > On Thu, 14 Mar 2024 10:05:37 +1100 > Michael Ellerman wrote: > >> Hi Herve, >> >> Herve Codina writes: > .. >> This breaks when building as a module (eg. ppc32_allmodconfig): >> >> In file included from ../include/linux/device/driver.h:21, >>from ../include/linux/device.h:32, >>from ../include/linux/dma-mapping.h:8, >>from ../drivers/net/wan/fsl_qmc_hdlc.c:13: >> ../drivers/net/wan/fsl_qmc_hdlc.c:405:25: error: ‘qmc_hdlc_driver’ >> undeclared here (not in a function); did you mean ‘qmc_hdlc_probe’? >> 405 | MODULE_DEVICE_TABLE(of, qmc_hdlc_driver); >> | ^~~ >> >> >> IIUIC it should be pointing to the table, not the driver, so: >> >> diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c >> index 5fd7ed325f5b..705c3681fb92 100644 >> --- a/drivers/net/wan/fsl_qmc_hdlc.c >> +++ b/drivers/net/wan/fsl_qmc_hdlc.c >> @@ -402,7 +402,7 @@ static const struct of_device_id qmc_hdlc_id_table[] = { >> { .compatible = "fsl,qmc-hdlc" }, >> {} /* sentinel */ >> }; >> -MODULE_DEVICE_TABLE(of, qmc_hdlc_driver); >> +MODULE_DEVICE_TABLE(of, qmc_hdlc_id_table); >> >> static struct platform_driver qmc_hdlc_driver = { >> .driver = { >> >> >> Which then builds correctly. > > My bad, I missed that one. > I fully agree with your modification. > > Do you want me to make a patch (copy/paste of your proposed modification) > or do you plan to send the patch on your side ? Yes if you can please turn it into a proper patch and submit it. No need to add my SoB, it's trivial. cheers
Re: [PATCH v7 1/5] net: wan: Add support for QMC HDLC
Hi Michael, On Thu, 14 Mar 2024 10:05:37 +1100 Michael Ellerman wrote: > Hi Herve, > > Herve Codina writes: ... > This breaks when building as a module (eg. ppc32_allmodconfig): > > In file included from ../include/linux/device/driver.h:21, >from ../include/linux/device.h:32, >from ../include/linux/dma-mapping.h:8, >from ../drivers/net/wan/fsl_qmc_hdlc.c:13: > ../drivers/net/wan/fsl_qmc_hdlc.c:405:25: error: ‘qmc_hdlc_driver’ > undeclared here (not in a function); did you mean ‘qmc_hdlc_probe’? > 405 | MODULE_DEVICE_TABLE(of, qmc_hdlc_driver); > | ^~~ > > > IIUIC it should be pointing to the table, not the driver, so: > > diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c > index 5fd7ed325f5b..705c3681fb92 100644 > --- a/drivers/net/wan/fsl_qmc_hdlc.c > +++ b/drivers/net/wan/fsl_qmc_hdlc.c > @@ -402,7 +402,7 @@ static const struct of_device_id qmc_hdlc_id_table[] = { > { .compatible = "fsl,qmc-hdlc" }, > {} /* sentinel */ > }; > -MODULE_DEVICE_TABLE(of, qmc_hdlc_driver); > +MODULE_DEVICE_TABLE(of, qmc_hdlc_id_table); > > static struct platform_driver qmc_hdlc_driver = { > .driver = { > > > Which then builds correctly. My bad, I missed that one. I fully agree with your modification. Do you want me to make a patch (copy/paste of your proposed modification) or do you plan to send the patch on your side ? Best regards, Hervé -- Hervé Codina, Bootlin Embedded Linux and Kernel engineering https://bootlin.com
Re: [PATCH v7 1/5] net: wan: Add support for QMC HDLC
Hi Herve, Herve Codina writes: > The QMC HDLC driver provides support for HDLC using the QMC (QUICC > Multichannel Controller) to transfer the HDLC data. ... > > diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c > new file mode 100644 > index ..5fd7ed325f5b > --- /dev/null > +++ b/drivers/net/wan/fsl_qmc_hdlc.c > @@ -0,0 +1,419 @@ ... > +static int qmc_hdlc_remove(struct platform_device *pdev) > +{ > + struct qmc_hdlc *qmc_hdlc = platform_get_drvdata(pdev); > + > + unregister_hdlc_device(qmc_hdlc->netdev); > + free_netdev(qmc_hdlc->netdev); > + > + return 0; > +} > + > +static const struct of_device_id qmc_hdlc_id_table[] = { > + { .compatible = "fsl,qmc-hdlc" }, > + {} /* sentinel */ > +}; > +MODULE_DEVICE_TABLE(of, qmc_hdlc_driver); This breaks when building as a module (eg. ppc32_allmodconfig): In file included from ../include/linux/device/driver.h:21, from ../include/linux/device.h:32, from ../include/linux/dma-mapping.h:8, from ../drivers/net/wan/fsl_qmc_hdlc.c:13: ../drivers/net/wan/fsl_qmc_hdlc.c:405:25: error: ‘qmc_hdlc_driver’ undeclared here (not in a function); did you mean ‘qmc_hdlc_probe’? 405 | MODULE_DEVICE_TABLE(of, qmc_hdlc_driver); | ^~~ IIUIC it should be pointing to the table, not the driver, so: diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c index 5fd7ed325f5b..705c3681fb92 100644 --- a/drivers/net/wan/fsl_qmc_hdlc.c +++ b/drivers/net/wan/fsl_qmc_hdlc.c @@ -402,7 +402,7 @@ static const struct of_device_id qmc_hdlc_id_table[] = { { .compatible = "fsl,qmc-hdlc" }, {} /* sentinel */ }; -MODULE_DEVICE_TABLE(of, qmc_hdlc_driver); +MODULE_DEVICE_TABLE(of, qmc_hdlc_id_table); static struct platform_driver qmc_hdlc_driver = { .driver = { Which then builds correctly. cheers
[PATCH v7 1/5] net: wan: Add support for QMC HDLC
The QMC HDLC driver provides support for HDLC using the QMC (QUICC Multichannel Controller) to transfer the HDLC data. Signed-off-by: Herve Codina Reviewed-by: Christophe Leroy Acked-by: Jakub Kicinski Reviewed-by: Andy Shevchenko --- drivers/net/wan/Kconfig| 12 + drivers/net/wan/Makefile | 1 + drivers/net/wan/fsl_qmc_hdlc.c | 419 + 3 files changed, 432 insertions(+) create mode 100644 drivers/net/wan/fsl_qmc_hdlc.c diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 7dda87756d3f..31ab2136cdf1 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -197,6 +197,18 @@ config FARSYNC To compile this driver as a module, choose M here: the module will be called farsync. +config FSL_QMC_HDLC + tristate "Freescale QMC HDLC support" + depends on HDLC + depends on CPM_QMC + help + HDLC support using the Freescale QUICC Multichannel Controller (QMC). + + To compile this driver as a module, choose M here: the + module will be called fsl_qmc_hdlc. + + If unsure, say N. + config FSL_UCC_HDLC tristate "Freescale QUICC Engine HDLC support" depends on HDLC diff --git a/drivers/net/wan/Makefile b/drivers/net/wan/Makefile index 8119b49d1da9..00e9b7ee1e01 100644 --- a/drivers/net/wan/Makefile +++ b/drivers/net/wan/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_WANXL) += wanxl.o obj-$(CONFIG_PCI200SYN)+= pci200syn.o obj-$(CONFIG_PC300TOO) += pc300too.o obj-$(CONFIG_IXP4XX_HSS) += ixp4xx_hss.o +obj-$(CONFIG_FSL_QMC_HDLC) += fsl_qmc_hdlc.o obj-$(CONFIG_FSL_UCC_HDLC) += fsl_ucc_hdlc.o obj-$(CONFIG_SLIC_DS26522) += slic_ds26522.o diff --git a/drivers/net/wan/fsl_qmc_hdlc.c b/drivers/net/wan/fsl_qmc_hdlc.c new file mode 100644 index ..5fd7ed325f5b --- /dev/null +++ b/drivers/net/wan/fsl_qmc_hdlc.c @@ -0,0 +1,419 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Freescale QMC HDLC Device Driver + * + * Copyright 2023 CS GROUP France + * + * Author: Herve Codina + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct qmc_hdlc_desc { + struct net_device *netdev; + struct sk_buff *skb; /* NULL if the descriptor is not in use */ + dma_addr_t dma_addr; + size_t dma_size; +}; + +struct qmc_hdlc { + struct device *dev; + struct qmc_chan *qmc_chan; + struct net_device *netdev; + bool is_crc32; + spinlock_t tx_lock; /* Protect tx descriptors */ + struct qmc_hdlc_desc tx_descs[8]; + unsigned int tx_out; + struct qmc_hdlc_desc rx_descs[4]; +}; + +static struct qmc_hdlc *netdev_to_qmc_hdlc(struct net_device *netdev) +{ + return dev_to_hdlc(netdev)->priv; +} + +static int qmc_hdlc_recv_queue(struct qmc_hdlc *qmc_hdlc, struct qmc_hdlc_desc *desc, size_t size); + +#define QMC_HDLC_RX_ERROR_FLAGS\ + (QMC_RX_FLAG_HDLC_OVF | QMC_RX_FLAG_HDLC_UNA | \ +QMC_RX_FLAG_HDLC_CRC | QMC_RX_FLAG_HDLC_ABORT) + +static void qmc_hcld_recv_complete(void *context, size_t length, unsigned int flags) +{ + struct qmc_hdlc_desc *desc = context; + struct net_device *netdev; + struct qmc_hdlc *qmc_hdlc; + int ret; + + netdev = desc->netdev; + qmc_hdlc = netdev_to_qmc_hdlc(netdev); + + dma_unmap_single(qmc_hdlc->dev, desc->dma_addr, desc->dma_size, DMA_FROM_DEVICE); + + if (flags & QMC_HDLC_RX_ERROR_FLAGS) { + netdev->stats.rx_errors++; + if (flags & QMC_RX_FLAG_HDLC_OVF) /* Data overflow */ + netdev->stats.rx_over_errors++; + if (flags & QMC_RX_FLAG_HDLC_UNA) /* bits received not multiple of 8 */ + netdev->stats.rx_frame_errors++; + if (flags & QMC_RX_FLAG_HDLC_ABORT) /* Received an abort sequence */ + netdev->stats.rx_frame_errors++; + if (flags & QMC_RX_FLAG_HDLC_CRC) /* CRC error */ + netdev->stats.rx_crc_errors++; + kfree_skb(desc->skb); + } else { + netdev->stats.rx_packets++; + netdev->stats.rx_bytes += length; + + skb_put(desc->skb, length); + desc->skb->protocol = hdlc_type_trans(desc->skb, netdev); + netif_rx(desc->skb); + } + + /* Re-queue a transfer using the same descriptor */ + ret = qmc_hdlc_recv_queue(qmc_hdlc, desc, desc->dma_size); + if (ret) { + dev_err(qmc_hdlc->dev, "queue recv desc failed (%d)\n", ret); + netdev->stats.rx_errors++; + } +} + +static int qmc_hdlc_recv_queue(struct qmc_hdlc *qmc_hdlc, struct qmc_hdlc_desc *desc, size_t size) +{ + int ret; + + desc->skb = dev_alloc_skb(size); +