* Re: [PATCH v9 2/2] can: esd: add support for esd GmbH PCIe/402 CAN interface family
From: Vincent MAILHOL @ 2023-11-08 11:00 UTC (permalink / raw)
To: Stefan Mätje
Cc: Marc Kleine-Budde, linux-can, netdev, linux-kernel,
Wolfgang Grandegger, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni
In-Reply-To: <20231107184103.2802678-3-stefan.maetje@esd.eu>
Hi,
I do not know much about PCI, so no thorough review of that part. Here
is a set of small fixes or nitpicks. The driver starts to look good.
If things go right, expect to receive my reviewed-by tag in the next
iteration.
On Wed. 8 Nov. 2023 at 08:30, Stefan Mätje <stefan.maetje@esd.eu> wrote:
> This patch adds support for the PCI based PCIe/402 CAN interface family
> from esd GmbH that is available with various form factors
> (https://esd.eu/en/products/402-series-can-interfaces).
>
> All boards utilize a FPGA based CAN controller solution developed
> by esd (esdACC). For more information on the esdACC see
> https://esd.eu/en/products/esdacc.
>
> This driver detects all available CAN interface board variants of
> the family but atm. operates the CAN-FD capable devices in
> Classic-CAN mode only! A later patch will introduce the CAN-FD
> functionality in this driver.
The driver already introduces pieces of code for CAN-FD, for example
struct can_bittiming_const pci402_bittiming_const_canfd. Would it make
sense to remove those for now and send them altogether in the
follow-up patch which will add CAN-FD?
> Co-developed-by: Thomas Körper <thomas.koerper@esd.eu>
> Signed-off-by: Thomas Körper <thomas.koerper@esd.eu>
> Signed-off-by: Stefan Mätje <stefan.maetje@esd.eu>
> ---
> drivers/net/can/Kconfig | 1 +
> drivers/net/can/Makefile | 1 +
> drivers/net/can/esd/Kconfig | 12 +
> drivers/net/can/esd/Makefile | 7 +
> drivers/net/can/esd/esd_402_pci-core.c | 512 ++++++++++++++++
> drivers/net/can/esd/esdacc.c | 771 +++++++++++++++++++++++++
> drivers/net/can/esd/esdacc.h | 393 +++++++++++++
> 7 files changed, 1697 insertions(+)
> create mode 100644 drivers/net/can/esd/Kconfig
> create mode 100644 drivers/net/can/esd/Makefile
> create mode 100644 drivers/net/can/esd/esd_402_pci-core.c
> create mode 100644 drivers/net/can/esd/esdacc.c
> create mode 100644 drivers/net/can/esd/esdacc.h
>
> diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> index 649453a3c858..b9a65b44ccef 100644
> --- a/drivers/net/can/Kconfig
> +++ b/drivers/net/can/Kconfig
> @@ -217,6 +217,7 @@ config CAN_XILINXCAN
> source "drivers/net/can/c_can/Kconfig"
> source "drivers/net/can/cc770/Kconfig"
> source "drivers/net/can/ctucanfd/Kconfig"
> +source "drivers/net/can/esd/Kconfig"
> source "drivers/net/can/ifi_canfd/Kconfig"
> source "drivers/net/can/m_can/Kconfig"
> source "drivers/net/can/mscan/Kconfig"
> diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
> index ff8f76295d13..4669cd51e7bf 100644
> --- a/drivers/net/can/Makefile
> +++ b/drivers/net/can/Makefile
> @@ -8,6 +8,7 @@ obj-$(CONFIG_CAN_VXCAN) += vxcan.o
> obj-$(CONFIG_CAN_SLCAN) += slcan/
>
> obj-y += dev/
> +obj-y += esd/
> obj-y += rcar/
> obj-y += spi/
> obj-y += usb/
> diff --git a/drivers/net/can/esd/Kconfig b/drivers/net/can/esd/Kconfig
> new file mode 100644
> index 000000000000..54bfc366634c
> --- /dev/null
> +++ b/drivers/net/can/esd/Kconfig
> @@ -0,0 +1,12 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +config CAN_ESD_402_PCI
> + tristate "esd electronics gmbh CAN-PCI(e)/402 family"
> + depends on PCI && HAS_DMA
> + help
> + Support for C402 card family from esd electronics gmbh.
> + This card family is based on the ESDACC CAN controller and
> + available in several form factors: PCI, PCIe, PCIe Mini,
> + M.2 PCIe, CPCIserial, PMC, XMC (see https://esd.eu/en)
> +
> + This driver can also be built as a module. In this case the
> + module will be called esd_402_pci.
> diff --git a/drivers/net/can/esd/Makefile b/drivers/net/can/esd/Makefile
> new file mode 100644
> index 000000000000..5dd2d470c286
> --- /dev/null
> +++ b/drivers/net/can/esd/Makefile
> @@ -0,0 +1,7 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +#
> +# Makefile for esd gmbh ESDACC controller driver
> +#
> +esd_402_pci-objs := esdacc.o esd_402_pci-core.o
> +
> +obj-$(CONFIG_CAN_ESD_402_PCI) += esd_402_pci.o
> diff --git a/drivers/net/can/esd/esd_402_pci-core.c b/drivers/net/can/esd/esd_402_pci-core.c
> new file mode 100644
> index 000000000000..5793d41c17c2
> --- /dev/null
> +++ b/drivers/net/can/esd/esd_402_pci-core.c
> @@ -0,0 +1,512 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/* Copyright (C) 2015 - 2016 Thomas Körper, esd electronic system design gmbh
> + * Copyright (C) 2017 - 2022 Stefan Mätje, esd electronics gmbh
> + */
> +
> +#include <linux/can/dev.h>
> +#include <linux/can.h>
> +#include <linux/can/netlink.h>
> +#include <linux/delay.h>
> +#include <linux/dma-mapping.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/netdevice.h>
> +#include <linux/pci.h>
> +
> +#include "esdacc.h"
> +
> +#define ESD_PCI_DEVICE_ID_PCIE402 0x0402
> +
> +#define PCI402_FPGA_VER_MIN 0x003d
> +#define PCI402_MAX_CORES 6
> +#define PCI402_BAR 0
> +#define PCI402_IO_OV_OFFS 0
> +#define PCI402_IO_PCIEP_OFFS 0x10000
> +#define PCI402_IO_LEN_TOTAL 0x20000
> +#define PCI402_IO_LEN_CORE 0x2000
> +#define PCI402_PCICFG_MSICAP 0x50
> +
> +#define PCI402_DMA_MASK DMA_BIT_MASK(32)
> +#define PCI402_DMA_SIZE ALIGN(0x10000, PAGE_SIZE)
> +
> +#define PCI402_PCIEP_OF_INT_ENABLE 0x0050
> +#define PCI402_PCIEP_OF_BM_ADDR_LO 0x1000
> +#define PCI402_PCIEP_OF_BM_ADDR_HI 0x1004
> +#define PCI402_PCIEP_OF_MSI_ADDR_LO 0x1008
> +#define PCI402_PCIEP_OF_MSI_ADDR_HI 0x100c
> +
> +/* The BTR register capabilities described by the can_bittiming_const structures
> + * below are valid since ESDACC version 0x0032.
> + */
> +
> +/* Used if the ESDACC FPGA is built as CAN-Classic version. */
> +static const struct can_bittiming_const pci402_bittiming_const = {
> + .name = "esd_402",
> + .tseg1_min = 1,
> + .tseg1_max = 16,
> + .tseg2_min = 1,
> + .tseg2_max = 8,
> + .sjw_max = 4,
> + .brp_min = 1,
> + .brp_max = 512,
> + .brp_inc = 1,
> +};
> +
> +/* Used if the ESDACC FPGA is built as CAN-FD version. */
> +static const struct can_bittiming_const pci402_bittiming_const_canfd = {
> + .name = "esd_402fd",
> + .tseg1_min = 1,
> + .tseg1_max = 256,
> + .tseg2_min = 1,
> + .tseg2_max = 128,
> + .sjw_max = 128,
> + .brp_min = 1,
> + .brp_max = 256,
> + .brp_inc = 1,
> +};
> +
> +static const struct net_device_ops pci402_acc_netdev_ops = {
> + .ndo_open = acc_open,
> + .ndo_stop = acc_close,can_
> + .ndo_start_xmit = acc_start_xmit,
> + .ndo_change_mtu = can_change_mtu
^
Generic comment: add a comma after the last entry to have a cleaner
diff if members get added later on.
Please also populate net_device_ops.ndo_eth_ioctl() and
netdev->ethtool_ops for the hardware timestamp support. Use below
commit as a reference:
https://git.kernel.org/torvalds/c/1d46efa0008a
> +};
> +
> +struct pci402_card {
> + /* Actually mapped io space, all other iomem derived from this */
> + void __iomem *addr;
> + void __iomem *addr_pciep;
> +
> + void *dma_buf;
> + dma_addr_t dma_hnd;
> +
> + struct acc_ov ov;
> + struct acc_core *cores;
> +
> + bool msi_enabled;
> +};
> +
> +static irqreturn_t pci402_interrupt(int irq, void *dev_id)
> +{
> + struct pci_dev *pdev = dev_id;
> + struct pci402_card *card = pci_get_drvdata(pdev);
> + irqreturn_t irq_status;
> +
> + irq_status = acc_card_interrupt(&card->ov, card->cores);
> +
> + return irq_status;
> +}
> +
> +static int pci402_set_msiconfig(struct pci_dev *pdev)
> +{
> + struct pci402_card *card = pci_get_drvdata(pdev);
> + u32 addr_lo_offs = 0;
> + u32 addr_lo = 0;
> + u32 addr_hi = 0;
> + u32 data = 0;
> + u16 csr = 0;
> + int err;
> +
> + /* The FPGA hard IP PCIe core implements a 64-bit MSI Capability
> + * Register Format
> + */
> + err = pci_read_config_word(pdev, PCI402_PCICFG_MSICAP + PCI_MSI_FLAGS, &csr);
> + if (err)
> + goto failed;
> +
> + err = pci_read_config_dword(pdev, PCI402_PCICFG_MSICAP + PCI_MSI_ADDRESS_LO,
> + &addr_lo);
> + if (err)
> + goto failed;
> + err = pci_read_config_dword(pdev, PCI402_PCICFG_MSICAP + PCI_MSI_ADDRESS_HI,
> + &addr_hi);
> + if (err)
> + goto failed;
> +
> + err = pci_read_config_dword(pdev, PCI402_PCICFG_MSICAP + PCI_MSI_DATA_64,
> + &data);
> + if (err)
> + goto failed;
> +
> + addr_lo_offs = addr_lo & 0x0000ffff;
> + addr_lo &= 0xffff0000;
> +
> + if (addr_hi)
> + addr_lo |= 1; /* To enable 64-Bit addressing in PCIe endpoint */
> +
> + if (!(csr & PCI_MSI_FLAGS_ENABLE)) {
> + err = -EINVAL;
> + goto failed;
> + }
> +
> + iowrite32(addr_lo, card->addr_pciep + PCI402_PCIEP_OF_MSI_ADDR_LO);
> + iowrite32(addr_hi, card->addr_pciep + PCI402_PCIEP_OF_MSI_ADDR_HI);
> + acc_ov_write32(&card->ov, ACC_OV_OF_MSI_ADDRESSOFFSET, addr_lo_offs);
> + acc_ov_write32(&card->ov, ACC_OV_OF_MSI_DATA, data);
> +
> + return 0;
> +
> +failed:
> + pci_warn(pdev, "Error while setting MSI configuration:\n"
> + "CSR: 0x%.4x, addr: 0x%.8x%.8x, offs: 0x%.4x, data: 0x%.8x\n",
> + csr, addr_hi, addr_lo, addr_lo_offs, data);
> +
> + return err;
> +}
> +
> +static int pci402_init_card(struct pci_dev *pdev)
> +{
> + struct pci402_card *card = pci_get_drvdata(pdev);
> +
> + card->ov.addr = card->addr + PCI402_IO_OV_OFFS;
> + card->addr_pciep = card->addr + PCI402_IO_PCIEP_OFFS;
> +
> + acc_reset_fpga(&card->ov);
> + acc_init_ov(&card->ov, &pdev->dev);
> +
> + if (card->ov.version < PCI402_FPGA_VER_MIN) {
> + pci_err(pdev,
> + "ESDACC version (0x%.4x) outdated, please update\n",
> + card->ov.version);
> + return -EINVAL;
> + }
> +
> + if (card->ov.timestamp_frequency != ACC_TS_FREQ_80MHZ) {
> + pci_err(pdev,
> + "esdACC timestamp frequency of %uHz not supported by driver. Aborted.\n",
> + card->ov.timestamp_frequency);
> + return -EINVAL;
> + }
> +
> + if (card->ov.active_cores > PCI402_MAX_CORES) {
> + pci_err(pdev,
> + "Card has more active cores (%u) than supported by driver. Aborted.\n",
^^^^
From the Linux coding style:
Printing numbers in parentheses (%d) adds no value and should be avoided.
Ref: https://www.kernel.org/doc/html/v4.10/process/coding-style.html#printing-kernel-messages
> + card->ov.active_cores);
> + return -EINVAL;
> + }
> + card->cores = devm_kcalloc(&pdev->dev, card->ov.active_cores,
> + sizeof(struct acc_core), GFP_KERNEL);
> + if (!card->cores)
> + return -ENOMEM;
> +
> + if (card->ov.features & ACC_OV_REG_FEAT_MASK_CANFD) {
> + pci_warn(pdev,
> + "ESDACC with CAN-FD feature detected. This driver doesn't support CAN-FD yet.\n");
> + }
> +
> +#ifdef __LITTLE_ENDIAN
> + /* So card converts all busmastered data to LE for us: */
> + acc_ov_set_bits(&card->ov, ACC_OV_OF_MODE,
> + ACC_OV_REG_MODE_MASK_ENDIAN_LITTLE);
> +#endif
> +
> + return 0;
> +}
> +
> +static int pci402_init_interrupt(struct pci_dev *pdev)
> +{
> + struct pci402_card *card = pci_get_drvdata(pdev);
> + int err;
> +
> + err = pci_enable_msi(pdev);
> + if (!err) {
> + err = pci402_set_msiconfig(pdev);
> + if (!err) {
> + card->msi_enabled = true;
> + acc_ov_set_bits(&card->ov, ACC_OV_OF_MODE,
> + ACC_OV_REG_MODE_MASK_MSI_ENABLE);
> + pci_info(pdev, "MSI enabled\n");
Consider using dev_dbg() instead of dev_info() here.
> + }
> + }
> +
> + err = devm_request_irq(&pdev->dev, pdev->irq, pci402_interrupt,
> + IRQF_SHARED, dev_name(&pdev->dev), pdev);
> + if (err)
> + goto failure_msidis;
> +
> + iowrite32(1, card->addr_pciep + PCI402_PCIEP_OF_INT_ENABLE);
> +
> + return 0;
> +
> +failure_msidis:
> + if (card->msi_enabled) {
> + acc_ov_clear_bits(&card->ov, ACC_OV_OF_MODE,
> + ACC_OV_REG_MODE_MASK_MSI_ENABLE);
> + pci_disable_msi(pdev);
> + card->msi_enabled = false;
> + }
> +
> + return err;
> +}
> +
> +static void pci402_finish_interrupt(struct pci_dev *pdev)
> +{
> + struct pci402_card *card = pci_get_drvdata(pdev);
> +
> + iowrite32(0, card->addr_pciep + PCI402_PCIEP_OF_INT_ENABLE);
> + devm_free_irq(&pdev->dev, pdev->irq, pdev);
> +
> + if (card->msi_enabled) {
> + acc_ov_clear_bits(&card->ov, ACC_OV_OF_MODE,
> + ACC_OV_REG_MODE_MASK_MSI_ENABLE);
> + pci_disable_msi(pdev);
> + card->msi_enabled = false;
> + }
> +}
> +
> +static int pci402_init_dma(struct pci_dev *pdev)
> +{
> + struct pci402_card *card = pci_get_drvdata(pdev);
> + int err;
> +
> + err = dma_set_coherent_mask(&pdev->dev, PCI402_DMA_MASK);
> + if (err) {
> + pci_err(pdev, "DMA set mask failed!\n");
> + return err;
> + }
> +
> + /* The ESDACC DMA engine needs the DMA buffer aligned to a 64k
> + * boundary. The DMA API guarantees to align the returned buffer to the
> + * smallest PAGE_SIZE order which is greater than or equal to the
> + * requested size. With PCI402_DMA_SIZE == 64kB this suffices here.
> + */
> + card->dma_buf = dma_alloc_coherent(&pdev->dev, PCI402_DMA_SIZE,
> + &card->dma_hnd, GFP_KERNEL);
> + if (!card->dma_buf)
> + return -ENOMEM;
> +
> + acc_init_bm_ptr(&card->ov, card->cores, card->dma_buf);
> +
> + iowrite32(card->dma_hnd,
> + card->addr_pciep + PCI402_PCIEP_OF_BM_ADDR_LO);
> + iowrite32(0, card->addr_pciep + PCI402_PCIEP_OF_BM_ADDR_HI);
> +
> + pci_set_master(pdev);
> +
> + acc_ov_set_bits(&card->ov, ACC_OV_OF_MODE,
> + ACC_OV_REG_MODE_MASK_BM_ENABLE);
> +
> + return 0;
> +}
> +
> +static void pci402_finish_dma(struct pci_dev *pdev)
> +{
> + struct pci402_card *card = pci_get_drvdata(pdev);
> + int i;
> +
> + acc_ov_clear_bits(&card->ov, ACC_OV_OF_MODE,
> + ACC_OV_REG_MODE_MASK_BM_ENABLE);
> +
> + pci_clear_master(pdev);
> +
> + iowrite32(0, card->addr_pciep + PCI402_PCIEP_OF_BM_ADDR_LO);
> + iowrite32(0, card->addr_pciep + PCI402_PCIEP_OF_BM_ADDR_HI);
> +
> + card->ov.bmfifo.messages = NULL;
> + card->ov.bmfifo.irq_cnt = NULL;
> + for (i = 0; i < card->ov.active_cores; i++) {
> + struct acc_core *core = &card->cores[i];
> +
> + core->bmfifo.messages = NULL;
> + core->bmfifo.irq_cnt = NULL;
> + }
> +
> + dma_free_coherent(&pdev->dev, PCI402_DMA_SIZE, card->dma_buf,
> + card->dma_hnd);
> + card->dma_buf = NULL;
> +}
> +
> +static int pci402_init_cores(struct pci_dev *pdev)
> +{
> + struct pci402_card *card = pci_get_drvdata(pdev);
> + int err;
> + int i;
> +
> + for (i = 0; i < card->ov.active_cores; i++) {
> + struct acc_core *core = &card->cores[i];
> + struct acc_net_priv *priv;
> + struct net_device *netdev;
> + u32 fifo_config;
> +
> + core->addr = card->ov.addr + (i + 1) * PCI402_IO_LEN_CORE;
> +
> + fifo_config = acc_read32(core, ACC_CORE_OF_TXFIFO_CONFIG);
> + core->tx_fifo_size = (fifo_config >> 24);
> + if (core->tx_fifo_size <= 1) {
> + pci_err(pdev, "Invalid tx_fifo_size!\n");
> + err = -EINVAL;
> + goto failure;
> + }
> +
> + netdev = alloc_candev(sizeof(*priv), core->tx_fifo_size);
> + if (!netdev) {
> + err = -ENOMEM;
> + goto failure;
> + }
> + core->netdev = netdev;
> +
> + netdev->flags |= IFF_ECHO;
> + netdev->dev_port = i;
> + netdev->netdev_ops = &pci402_acc_netdev_ops;
> + SET_NETDEV_DEV(netdev, &pdev->dev);
> +
> + priv = netdev_priv(netdev);
> + priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
> + CAN_CTRLMODE_LISTENONLY |
> + CAN_CTRLMODE_BERR_REPORTING |
> + CAN_CTRLMODE_CC_LEN8_DLC;
> +
> + priv->can.clock.freq = card->ov.core_frequency;
> + if (card->ov.features & ACC_OV_REG_FEAT_MASK_CANFD)
> + priv->can.bittiming_const = &pci402_bittiming_const_canfd;
> + else
> + priv->can.bittiming_const = &pci402_bittiming_const;
> + priv->can.do_set_bittiming = acc_set_bittiming;
> + priv->can.do_set_mode = acc_set_mode;
> + priv->can.do_get_berr_counter = acc_get_berr_counter;
> +
> + priv->core = core;
> + priv->ov = &card->ov;
> +
> + err = register_candev(netdev);
> + if (err) {
> + free_candev(core->netdev);
> + core->netdev = NULL;
> + goto failure;
> + }
> +
> + netdev_info(netdev, "registered\n");
Isn't this already reported by the core? Please check and if
redundant, remove (same comment for the unregister below).
> + }
> +
> + return 0;
> +
> +failure:
> + for (i--; i >= 0; i--) {
> + struct acc_core *core = &card->cores[i];
> +
> + netdev_info(core->netdev, "unregistering...\n");
> + unregister_candev(core->netdev);
> +
> + free_candev(core->netdev);
> + core->netdev = NULL;
> + }
Nitpick: this cleanup loop has the same content as the loop in
pci402_finish_cores(). Might be worth factorizing the code in an
helper function that would free a single core.
> +
> + return err;
> +}
> +
> +static void pci402_finish_cores(struct pci_dev *pdev)
> +{
> + struct pci402_card *card = pci_get_drvdata(pdev);
> + int i;
> +
> + for (i = 0; i < card->ov.active_cores; i++) {
> + struct acc_core *core = &card->cores[i];
> +
> + netdev_info(core->netdev, "unregister\n");
> + unregister_candev(core->netdev);
> +
> + free_candev(core->netdev);
> + core->netdev = NULL;
> + }
> +}
> +
> +static int pci402_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
> +{
> + struct pci402_card *card = NULL;
> + int err;
> +
> + err = pci_enable_device(pdev);
> + if (err)
> + return err;
> +
> + card = devm_kzalloc(&pdev->dev, sizeof(*card), GFP_KERNEL);
> + if (!card) {
> + err = -ENOMEM;
> + goto failure_disable_pci;
> + }
> +
> + pci_set_drvdata(pdev, card);
> +
> + err = pci_request_regions(pdev, pci_name(pdev));
> + if (err)
> + goto failure_disable_pci;
> +
> + card->addr = pci_iomap(pdev, PCI402_BAR, PCI402_IO_LEN_TOTAL);
> + if (!card->addr) {
> + err = -ENOMEM;
> + goto failure_release_regions;
> + }
> +
> + err = pci402_init_card(pdev);
> + if (err)
> + goto failure_unmap;
> +
> + err = pci402_init_dma(pdev);
> + if (err)
> + goto failure_unmap;
> +
> + err = pci402_init_interrupt(pdev);
> + if (err)
> + goto failure_finish_dma;
> +
> + err = pci402_init_cores(pdev);
> + if (err)
> + goto failure_finish_interrupt;
> +
> + return 0;
> +
> +failure_finish_interrupt:
> + pci402_finish_interrupt(pdev);
> +
> +failure_finish_dma:
> + pci402_finish_dma(pdev);
> +
> +failure_unmap:
> + pci_iounmap(pdev, card->addr);
> +
> +failure_release_regions:
> + pci_release_regions(pdev);
> +
> +failure_disable_pci:
> + pci_disable_device(pdev);
> +
> + return err;
> +}
> +
> +static void pci402_remove(struct pci_dev *pdev)
> +{
> + struct pci402_card *card = pci_get_drvdata(pdev);
> +
> + pci402_finish_interrupt(pdev);
> + pci402_finish_cores(pdev);
> + pci402_finish_dma(pdev);
> + pci_iounmap(pdev, card->addr);
> + pci_release_regions(pdev);
> + pci_disable_device(pdev);
> +}
> +
> +static const struct pci_device_id pci402_tbl[] = {
> + {
> + .vendor = PCI_VENDOR_ID_ESDGMBH,
> + .device = ESD_PCI_DEVICE_ID_PCIE402,
> + .subvendor = PCI_VENDOR_ID_ESDGMBH,
> + .subdevice = PCI_ANY_ID,
> + },
> + { 0, }
> +};
> +MODULE_DEVICE_TABLE(pci, pci402_tbl);
> +
> +static struct pci_driver pci402_driver = {
> + .name = KBUILD_MODNAME,
> + .id_table = pci402_tbl,
> + .probe = pci402_probe,
> + .remove = pci402_remove,
> +};
> +module_pci_driver(pci402_driver);
> +
> +MODULE_DESCRIPTION("Socket-CAN driver for esd CAN 402 card family with esdACC core on PCIe");
> +MODULE_AUTHOR("Thomas Körper <socketcan@esd.eu>");
> +MODULE_AUTHOR("Stefan Mätje <stefan.maetje@esd.eu>");
> +MODULE_LICENSE("GPL");
> diff --git a/drivers/net/can/esd/esdacc.c b/drivers/net/can/esd/esdacc.c
> new file mode 100644
> index 000000000000..49017c986c70
> --- /dev/null
> +++ b/drivers/net/can/esd/esdacc.c
> @@ -0,0 +1,771 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/* Copyright (C) 2015 - 2016 Thomas Körper, esd electronic system design gmbh
> + * Copyright (C) 2017 - 2022 Stefan Mätje, esd electronics gmbh
^^^^
2023? (Same comment for other files)
> + */
> +
> +#include "esdacc.h"
> +
> +#include <linux/bitfield.h>
> +#include <linux/delay.h>
> +#include <linux/io.h>
> +#include <linux/ktime.h>
> +
> +/* ecc value of esdACC equals SJA1000's ECC register */
> +#define ACC_ECC_SEG 0x1f
> +#define ACC_ECC_DIR 0x20
> +#define ACC_ECC_BIT 0x00
> +#define ACC_ECC_FORM 0x40
> +#define ACC_ECC_STUFF 0x80
> +#define ACC_ECC_MASK 0xc0
> +
> +#define ACC_BM_IRQ_UNMASK_ALL 0x55555555U
> +#define ACC_BM_IRQ_MASK_ALL 0xaaaaaaaaU
> +#define ACC_BM_IRQ_MASK 0x2U
> +#define ACC_BM_IRQ_UNMASK 0x1U
> +#define ACC_BM_LENFLAG_TX 0x20
> +
> +#define ACC_REG_STATUS_IDX_STATUS_DOS 16
> +#define ACC_REG_STATUS_IDX_STATUS_ES 17
> +#define ACC_REG_STATUS_IDX_STATUS_EP 18
> +#define ACC_REG_STATUS_IDX_STATUS_BS 19
> +#define ACC_REG_STATUS_IDX_STATUS_RBS 20
> +#define ACC_REG_STATUS_IDX_STATUS_RS 21
> +#define ACC_REG_STATUS_MASK_STATUS_DOS BIT(ACC_REG_STATUS_IDX_STATUS_DOS)
> +#define ACC_REG_STATUS_MASK_STATUS_ES BIT(ACC_REG_STATUS_IDX_STATUS_ES)
> +#define ACC_REG_STATUS_MASK_STATUS_EP BIT(ACC_REG_STATUS_IDX_STATUS_EP)
> +#define ACC_REG_STATUS_MASK_STATUS_BS BIT(ACC_REG_STATUS_IDX_STATUS_BS)
> +#define ACC_REG_STATUS_MASK_STATUS_RBS BIT(ACC_REG_STATUS_IDX_STATUS_RBS)
> +#define ACC_REG_STATUS_MASK_STATUS_RS BIT(ACC_REG_STATUS_IDX_STATUS_RS)
Many of these macros are not used:
./include/linux/ctype.h:43:19: warning: declaration of ‘isdigit’
shadows a built-in function [-Wshadow]
43 | static inline int isdigit(int c)
| ^~~~~~~
drivers/net/can/esd/esdacc.c:24: warning: macro "ACC_BM_IRQ_UNMASK"
is not used [-Wunused-macros]
24 | #define ACC_BM_IRQ_UNMASK 0x1U
|
drivers/net/can/esd/esdacc.c:27: warning: macro
"ACC_REG_STATUS_IDX_STATUS_DOS" is not used [-Wunused-macros]
27 | #define ACC_REG_STATUS_IDX_STATUS_DOS 16
|
drivers/net/can/esd/esdacc.c:37: warning: macro
"ACC_REG_STATUS_MASK_STATUS_RBS" is not used [-Wunused-macros]
37 | #define ACC_REG_STATUS_MASK_STATUS_RBS
BIT(ACC_REG_STATUS_IDX_STATUS_RBS)
|
drivers/net/can/esd/esdacc.c:38: warning: macro
"ACC_REG_STATUS_MASK_STATUS_RS" is not used [-Wunused-macros]
38 | #define ACC_REG_STATUS_MASK_STATUS_RS
BIT(ACC_REG_STATUS_IDX_STATUS_RS)
|
drivers/net/can/esd/esdacc.c:32: warning: macro
"ACC_REG_STATUS_IDX_STATUS_RS" is not used [-Wunused-macros]
32 | #define ACC_REG_STATUS_IDX_STATUS_RS 21
|
drivers/net/can/esd/esdacc.c:31: warning: macro
"ACC_REG_STATUS_IDX_STATUS_RBS" is not used [-Wunused-macros]
31 | #define ACC_REG_STATUS_IDX_STATUS_RBS 20
|
drivers/net/can/esd/esdacc.c:33: warning: macro
"ACC_REG_STATUS_MASK_STATUS_DOS" is not used [-Wunused-macros]
33 | #define ACC_REG_STATUS_MASK_STATUS_DOS
BIT(ACC_REG_STATUS_IDX_STATUS_DOS)
|
drivers/net/can/esd/esdacc.c:22: warning: macro
"ACC_BM_IRQ_MASK_ALL" is not used [-Wunused-macros]
22 | #define ACC_BM_IRQ_MASK_ALL 0xaaaaaaaaU
> +static void acc_resetmode_enter(struct acc_core *core)
> +{
> + acc_set_bits(core, ACC_CORE_OF_CTRL_MODE,
> + ACC_REG_CONTROL_MASK_MODE_RESETMODE);
> +
> + /* Read back reset mode bit to flush PCI write posting */
> + acc_resetmode_entered(core);
> +}
> +
> +static void acc_resetmode_leave(struct acc_core *core)
> +{
> + acc_clear_bits(core, ACC_CORE_OF_CTRL_MODE,
> + ACC_REG_CONTROL_MASK_MODE_RESETMODE);
> +
> + /* Read back reset mode bit to flush PCI write posting */
> + acc_resetmode_entered(core);
> +}
> +
> +static void acc_txq_put(struct acc_core *core, u32 acc_id, u8 acc_dlc,
> + const void *data)
> +{
> + acc_write32_noswap(core, ACC_CORE_OF_TXFIFO_DATA_1,
> + *((const u32 *)(data + 4)));
> + acc_write32_noswap(core, ACC_CORE_OF_TXFIFO_DATA_0,
> + *((const u32 *)data));
> + acc_write32(core, ACC_CORE_OF_TXFIFO_DLC, acc_dlc);
> + /* CAN id must be written at last. This write starts TX. */
> + acc_write32(core, ACC_CORE_OF_TXFIFO_ID, acc_id);
> +}
> +
> +/* Convert timestamp from esdACC time stamp ticks to ns
> + *
> + * The conversion factor ts2ns from time stamp counts to ns is basically
> + * ts2ns = NSEC_PER_SEC / timestamp_frequency
> + *
> + * We handle here only a fixed timestamp frequency of 80MHz. The
> + * resulting ts2ns factor would be 12.5.
> + *
> + * At the end we multiply by 12 and add the half of the HW timestamp
> + * to get a multiplication by 12.5. This way any overflow is
> + * avoided until ktime_t itself overflows.
> + */
> +#define ACC_TS_FACTOR (NSEC_PER_SEC / ACC_TS_FREQ_80MHZ)
> +#define ACC_TS_80MHZ_SHIFT 1
> +
> +static ktime_t acc_ts2ktime(struct acc_ov *ov, u64 ts)
> +{
> + u64 ns;
> +
> + ns = (ts * ACC_TS_FACTOR) + (ts >> ACC_TS_80MHZ_SHIFT);
> +
> + return ns_to_ktime(ns);
> +}
> +
> +void acc_init_ov(struct acc_ov *ov, struct device *dev)
> +{
> + u32 temp;
> +
> + temp = acc_ov_read32(ov, ACC_OV_OF_VERSION);
> + ov->version = temp;
> + ov->features = (temp >> 16);
> +
> + temp = acc_ov_read32(ov, ACC_OV_OF_INFO);
> + ov->total_cores = temp;
> + ov->active_cores = (temp >> 8);
> +
> + ov->core_frequency = acc_ov_read32(ov, ACC_OV_OF_CANCORE_FREQ);
> + ov->timestamp_frequency = acc_ov_read32(ov, ACC_OV_OF_TS_FREQ_LO);
> +
> + /* Depending on ESDACC feature NEW_PSC enable the new prescaler
> + * or adjust core_frequency according to the implicit division by 2.
> + */
> + if (ov->features & ACC_OV_REG_FEAT_MASK_NEW_PSC) {
> + acc_ov_set_bits(ov, ACC_OV_OF_MODE,
> + ACC_OV_REG_MODE_MASK_NEW_PSC_ENABLE);
> + } else {
> + ov->core_frequency /= 2;
> + }
> +
> + dev_info(dev,
> + "ESDACC v%u, freq: %u/%u, feat/strap: 0x%x/0x%x, cores: %u/%u\n",
> + ov->version, ov->core_frequency, ov->timestamp_frequency,
> + ov->features, acc_ov_read32(ov, ACC_OV_OF_INFO) >> 16,
> + ov->active_cores, ov->total_cores);
Consider using dev_dbg() instead of dev_info() here.
> +}
> +
> +void acc_init_bm_ptr(struct acc_ov *ov, struct acc_core *cores, const void *mem)
> +{
> + unsigned int u;
> +
> + /* DMA buffer layout as follows where N is the number of CAN cores
> + * implemented in the FPGA, i.e. N = ov->total_cores
> + *
> + * Layout Section size
> + * +-----------------------+
> + * | FIFO Card/Overview | ACC_CORE_DMABUF_SIZE
> + * | |
> + * +-----------------------+
> + * | FIFO Core0 | ACC_CORE_DMABUF_SIZE
> + * | |
> + * +-----------------------+
> + * | ... | ...
> + * | |
> + * +-----------------------+
> + * | FIFO CoreN | ACC_CORE_DMABUF_SIZE
> + * | |
> + * +-----------------------+
> + * | irq_cnt Card/Overview | sizeof(u32)
> + * +-----------------------+
> + * | irq_cnt Core0 | sizeof(u32)
> + * +-----------------------+
> + * | ... | ...
> + * +-----------------------+
> + * | irq_cnt CoreN | sizeof(u32)
> + * +-----------------------+
Nitpick, instead of drawing all the cells in ascii art, please prefer
a more frugal style.
Example:
Layout Section size
---------------------------------------------
FIFO Card/Overview ACC_CORE_DMABUF_SIZE
FIFO Core0 ACC_CORE_DMABUF_SIZE
... ...
> + */
> + ov->bmfifo.messages = mem;
> + ov->bmfifo.irq_cnt = mem + (ov->total_cores + 1U) * ACC_CORE_DMABUF_SIZE;
> +
> + for (u = 0U; u < ov->active_cores; u++) {
> + struct acc_core *core = &cores[u];
> +
> + core->bmfifo.messages = mem + (u + 1U) * ACC_CORE_DMABUF_SIZE;
> + core->bmfifo.irq_cnt = ov->bmfifo.irq_cnt + (u + 1U);
> + }
> +}
> +
> +int acc_open(struct net_device *netdev)
> +{
> + struct acc_net_priv *priv = netdev_priv(netdev);
> + struct acc_core *core = priv->core;
> + u32 tx_fifo_status;
> + u32 ctrl_mode;
> + int err;
> +
> + /* Retry to enter RESET mode if out of sync. */
> + if (priv->can.state != CAN_STATE_STOPPED) {
> + netdev_warn(netdev, "Entered %s() with bad can.state: %s\n",
> + __func__, can_get_state_str(priv->can.state));
> + acc_resetmode_enter(core);
> + priv->can.state = CAN_STATE_STOPPED;
> + }
> +
> + err = open_candev(netdev);
> + if (err)
> + return err;
> +
> + ctrl_mode = ACC_REG_CONTROL_MASK_IE_RXTX |
> + ACC_REG_CONTROL_MASK_IE_TXERROR |
> + ACC_REG_CONTROL_MASK_IE_ERRWARN |
> + ACC_REG_CONTROL_MASK_IE_OVERRUN |
> + ACC_REG_CONTROL_MASK_IE_ERRPASS;
> +
> + if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
> + ctrl_mode |= ACC_REG_CONTROL_MASK_IE_BUSERR;
> +
> + if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
> + ctrl_mode |= ACC_REG_CONTROL_MASK_MODE_LOM;
> +
> + acc_set_bits(core, ACC_CORE_OF_CTRL_MODE, ctrl_mode);
> +
> + acc_resetmode_leave(core);
> + priv->can.state = CAN_STATE_ERROR_ACTIVE;
> +
> + /* Resync TX FIFO indices to HW state after (re-)start. */
> + tx_fifo_status = acc_read32(core, ACC_CORE_OF_TXFIFO_STATUS);
> + core->tx_fifo_head = tx_fifo_status & 0xff;
> + core->tx_fifo_tail = (tx_fifo_status >> 8) & 0xff;
> +
> + netif_start_queue(netdev);
> + return 0;
> +}
> +
> +int acc_close(struct net_device *netdev)
> +{
> + struct acc_net_priv *priv = netdev_priv(netdev);
> + struct acc_core *core = priv->core;
> +
> + acc_clear_bits(core, ACC_CORE_OF_CTRL_MODE,
> + ACC_REG_CONTROL_MASK_IE_RXTX |
> + ACC_REG_CONTROL_MASK_IE_TXERROR |
> + ACC_REG_CONTROL_MASK_IE_ERRWARN |
> + ACC_REG_CONTROL_MASK_IE_OVERRUN |
> + ACC_REG_CONTROL_MASK_IE_ERRPASS |
> + ACC_REG_CONTROL_MASK_IE_BUSERR);
> +
> + netif_stop_queue(netdev);
> + acc_resetmode_enter(core);
> + priv->can.state = CAN_STATE_STOPPED;
> +
> + /* Mark pending TX requests to be aborted after controller restart. */
> + acc_write32(core, ACC_CORE_OF_TX_ABORT_MASK, 0xffff);
> +
> + /* ACC_REG_CONTROL_MASK_MODE_LOM is only accessible in RESET mode */
> + acc_clear_bits(core, ACC_CORE_OF_CTRL_MODE,
> + ACC_REG_CONTROL_MASK_MODE_LOM);
> +
> + close_candev(netdev);
> + return 0;
> +}
> +
> +netdev_tx_t acc_start_xmit(struct sk_buff *skb, struct net_device *netdev)
> +{
> + struct acc_net_priv *priv = netdev_priv(netdev);
> + struct acc_core *core = priv->core;
> + struct can_frame *cf = (struct can_frame *)skb->data;
> + u8 tx_fifo_head = core->tx_fifo_head;
> + int fifo_usage;
> + u32 acc_id;
> + u8 acc_dlc;
> +
> + if (can_dropped_invalid_skb(netdev, skb))
> + return NETDEV_TX_OK;
> +
> + /* Access core->tx_fifo_tail only once because it may be changed
> + * from the interrupt level.
> + */
> + fifo_usage = tx_fifo_head - core->tx_fifo_tail;
> + if (fifo_usage < 0)
> + fifo_usage += core->tx_fifo_size;
> +
> + if (fifo_usage >= core->tx_fifo_size - 1) {
> + netdev_err(core->netdev,
> + "BUG: TX ring full when queue awake!\n");
> + netif_stop_queue(netdev);
> + return NETDEV_TX_BUSY;
> + }
> +
> + if (fifo_usage == core->tx_fifo_size - 2)
> + netif_stop_queue(netdev);
> +
> + acc_dlc = can_get_cc_dlc(cf, priv->can.ctrlmode);
> + if (cf->can_id & CAN_RTR_FLAG)
> + acc_dlc |= ACC_CAN_RTR_FLAG;
> +
> + if (cf->can_id & CAN_EFF_FLAG) {
> + acc_id = cf->can_id & CAN_EFF_MASK;
> + acc_id |= ACC_CAN_EFF_FLAG;
> + } else {
> + acc_id = cf->can_id & CAN_SFF_MASK;
> + }
> +
> + can_put_echo_skb(skb, netdev, core->tx_fifo_head, 0);
> +
> + tx_fifo_head++;
> + if (tx_fifo_head >= core->tx_fifo_size)
> + tx_fifo_head = 0U;
Those three lines are repeated several times when setting tx_fifo_head
or tx_fifo_tail. I suggest adding an helper function (e.g.
acc_inc_fifo_idx()) to factorize all that.
> + core->tx_fifo_head = tx_fifo_head;
> +
> + acc_txq_put(core, acc_id, acc_dlc, cf->data);
> +
> + return NETDEV_TX_OK;
> +}
> +
> +int acc_get_berr_counter(const struct net_device *netdev,
> + struct can_berr_counter *bec)
> +{
> + struct acc_net_priv *priv = netdev_priv(netdev);
> + u32 core_status = acc_read32(priv->core, ACC_CORE_OF_STATUS);
> +
> + bec->txerr = (core_status >> 8) & 0xff;
> + bec->rxerr = core_status & 0xff;
> +
> + return 0;
> +}
> +
> +int acc_set_mode(struct net_device *netdev, enum can_mode mode)
> +{
> + struct acc_net_priv *priv = netdev_priv(netdev);
> +
> + switch (mode) {
> + case CAN_MODE_START:
> + /* Paranoid FIFO index check. */
> + {
> + const u32 tx_fifo_status =
> + acc_read32(priv->core, ACC_CORE_OF_TXFIFO_STATUS);
> + const u8 hw_fifo_head = tx_fifo_status;
> +
> + if (hw_fifo_head != priv->core->tx_fifo_head ||
> + hw_fifo_head != priv->core->tx_fifo_tail) {
> + netdev_warn(netdev,
> + "TX FIFO mismatch: T %2u H %2u; TFHW %#08x\n",
> + priv->core->tx_fifo_tail,
> + priv->core->tx_fifo_head,
> + tx_fifo_status);
> + }
> + }
> + acc_resetmode_leave(priv->core);
> + /* To leave the bus-off state the esdACC controller begins
> + * here a grace period where it counts 128 "idle conditions" (each
> + * of 11 consecutive recessive bits) on the bus as required
> + * by the CAN spec.
> + *
> + * During this time the TX FIFO may still contain already
> + * aborted "zombie" frames that are only drained from the FIFO
> + * at the end of the grace period.
> + *
> + * To not to interfere with this drain process we don't
> + * call netif_wake_queue() here. When the controller reaches
> + * the error-active state again, it informs us about that
> + * with an acc_bmmsg_errstatechange message. Then
> + * netif_wake_queue() is called from
> + * handle_core_msg_errstatechange() instead.
> + */
> + break;
> +
> + default:
> + return -EOPNOTSUPP;
> + }
> +
> + return 0;
> +}
> +
> +int acc_set_bittiming(struct net_device *netdev)
> +{
> + struct acc_net_priv *priv = netdev_priv(netdev);
> + const struct can_bittiming *bt = &priv->can.bittiming;
> + u32 brp;
> + u32 btr;
> +
> + if (priv->ov->features & ACC_OV_REG_FEAT_MASK_CANFD) {
> + u32 fbtr = 0;
> +
> + netdev_dbg(netdev, "bit timing: brp %u, prop %u, ph1 %u ph2 %u, sjw %u\n",
> + bt->brp, bt->prop_seg,
> + bt->phase_seg1, bt->phase_seg2, bt->sjw);
> +
> + brp = FIELD_PREP(ACC_REG_BRP_FD_MASK_BRP, bt->brp - 1);
> +
> + btr = FIELD_PREP(ACC_REG_BTR_FD_MASK_TSEG1, bt->phase_seg1 + bt->prop_seg - 1);
> + btr |= FIELD_PREP(ACC_REG_BTR_FD_MASK_TSEG2, bt->phase_seg2 - 1);
> + btr |= FIELD_PREP(ACC_REG_BTR_FD_MASK_SJW, bt->sjw - 1);
> +
> + /* Keep order of accesses to ACC_CORE_OF_BRP and ACC_CORE_OF_BTR. */
> + acc_write32(priv->core, ACC_CORE_OF_BRP, brp);
> + acc_write32(priv->core, ACC_CORE_OF_BTR, btr);
> +
> + netdev_dbg(netdev, "ESDACC: BRP %u, NBTR 0x%08x, DBTR 0x%08x",
> + brp, btr, fbtr);
> + } else {
> + netdev_dbg(netdev, "bit timing: brp %u, prop %u, ph1 %u ph2 %u, sjw %u\n",
> + bt->brp, bt->prop_seg,
> + bt->phase_seg1, bt->phase_seg2, bt->sjw);
> +
> + brp = FIELD_PREP(ACC_REG_BRP_CL_MASK_BRP, bt->brp - 1);
> +
> + btr = FIELD_PREP(ACC_REG_BTR_CL_MASK_TSEG1, bt->phase_seg1 + bt->prop_seg - 1);
> + btr |= FIELD_PREP(ACC_REG_BTR_CL_MASK_TSEG2, bt->phase_seg2 - 1);
> + btr |= FIELD_PREP(ACC_REG_BTR_CL_MASK_SJW, bt->sjw - 1);
> +
> + /* Keep order of accesses to ACC_CORE_OF_BRP and ACC_CORE_OF_BTR. */
> + acc_write32(priv->core, ACC_CORE_OF_BRP, brp);
> + acc_write32(priv->core, ACC_CORE_OF_BTR, btr);
> +
> + netdev_dbg(netdev, "ESDACC: BRP %u, BTR 0x%08x", brp, btr);
> + }
> +
> + return 0;
> +}
> +
> +static void handle_core_msg_rxtxdone(struct acc_core *core,
> + const struct acc_bmmsg_rxtxdone *msg)
> +{
> + struct acc_net_priv *priv = netdev_priv(core->netdev);
> + struct net_device_stats *stats = &core->netdev->stats;
> + struct sk_buff *skb;
> +
> + if (msg->dlc.rxtx.len & ACC_BM_LENFLAG_TX) {
> + u8 tx_fifo_tail = core->tx_fifo_tail;
> +
> + if (core->tx_fifo_head == tx_fifo_tail) {
> + netdev_warn(core->netdev,
> + "TX interrupt, but queue is empty!?\n");
> + return;
> + }
> +
> + /* Direct access echo skb to attach HW time stamp. */
> + skb = priv->can.echo_skb[tx_fifo_tail];
> + if (skb) {
> + skb_hwtstamps(skb)->hwtstamp =
> + acc_ts2ktime(priv->ov, msg->ts);
> + }
> +
> + stats->tx_packets++;
> + stats->tx_bytes += can_get_echo_skb(core->netdev, tx_fifo_tail,
> + NULL);
> +
> + tx_fifo_tail++;
> + if (tx_fifo_tail >= core->tx_fifo_size)
> + tx_fifo_tail = 0U;
> + core->tx_fifo_tail = tx_fifo_tail;
> +
> + netif_wake_queue(core->netdev);
> +
> + } else {
> + struct can_frame *cf;
> +
> + skb = alloc_can_skb(core->netdev, &cf);
> + if (!skb) {
> + stats->rx_dropped++;
> + return;
> + }
> +
> + cf->can_id = msg->id & CAN_EFF_MASK;
Semantically, you want the exclude the EFF, RTR and ERR flags, right?
If so, use CAN_ERR_MASK instead of CAN_EFF_MASK.
https://elixir.bootlin.com/linux/v6.6/source/include/uapi/linux/can.h#L63
Please also check the other use of CAN_EFF_MASK throughout the driver.
> + if (msg->id & ACC_CAN_EFF_FLAG)
> + cf->can_id |= CAN_EFF_FLAG;
> +
> + can_frame_set_cc_len(cf, msg->dlc.rx.len & ACC_CAN_DLC_MASK,
> + priv->can.ctrlmode);
> +
> + if (msg->dlc.rx.len & ACC_CAN_RTR_FLAG) {
> + cf->can_id |= CAN_RTR_FLAG;
> + } else {
> + memcpy(cf->data, msg->data, cf->len);
> + stats->rx_bytes += cf->len;
> + }
> + stats->rx_packets++;
> +
> + skb_hwtstamps(skb)->hwtstamp = acc_ts2ktime(priv->ov, msg->ts);
> +
> + netif_rx(skb);
> + }
> +}
> +
> +static void handle_core_msg_txabort(struct acc_core *core,
> + const struct acc_bmmsg_txabort *msg)
> +{
> + struct net_device_stats *stats = &core->netdev->stats;
> + u8 tx_fifo_tail = core->tx_fifo_tail;
> + u32 abort_mask = msg->abort_mask; /* u32 extend to avoid warnings later */
> +
> + /* The abort_mask shows which frames were aborted in ESDACC's FIFO. */
> + while (tx_fifo_tail != core->tx_fifo_head && (abort_mask)) {
> + const u32 tail_mask = (1U << tx_fifo_tail);
> +
> + if (!(abort_mask & tail_mask))
> + break;
> + abort_mask &= ~tail_mask;
> +
> + can_free_echo_skb(core->netdev, tx_fifo_tail, NULL);
> + stats->tx_dropped++;
> + stats->tx_aborted_errors++;
> +
> + tx_fifo_tail++;
> + if (tx_fifo_tail >= core->tx_fifo_size)
> + tx_fifo_tail = 0;
> + }
> + core->tx_fifo_tail = tx_fifo_tail;
> + if (abort_mask)
> + netdev_warn(core->netdev, "Unhandled aborted messages\n");
> +
> + if (!acc_resetmode_entered(core))
> + netif_wake_queue(core->netdev);
> +}
> +
> +static void handle_core_msg_overrun(struct acc_core *core,
> + const struct acc_bmmsg_overrun *msg)
> +{
> + struct acc_net_priv *priv = netdev_priv(core->netdev);
> + struct net_device_stats *stats = &core->netdev->stats;
> + struct can_frame *cf;
> + struct sk_buff *skb;
> +
> + /* lost_cnt may be 0 if not supported by ESDACC version */
> + if (msg->lost_cnt) {
> + stats->rx_errors += msg->lost_cnt;
> + stats->rx_over_errors += msg->lost_cnt;
> + } else {
> + stats->rx_errors++;
> + stats->rx_over_errors++;
> + }
> +
> + skb = alloc_can_err_skb(core->netdev, &cf);
> + if (!skb) {
> + stats->rx_dropped++;
> + return;
> + }
> +
> + cf->can_id |= CAN_ERR_CRTL;
> + cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
> +
> + skb_hwtstamps(skb)->hwtstamp = acc_ts2ktime(priv->ov, msg->ts);
> +
> + netif_rx(skb);
> +}
> +
> +static void handle_core_msg_buserr(struct acc_core *core,
> + const struct acc_bmmsg_buserr *msg)
> +{
> + struct acc_net_priv *priv = netdev_priv(core->netdev);
> + struct net_device_stats *stats = &core->netdev->stats;
> + struct can_frame *cf;
> + struct sk_buff *skb;
> + const u32 reg_status = msg->reg_status;
> + const u8 rxerr = reg_status;
> + const u8 txerr = (reg_status >> 8);
> + u8 can_err_prot_type = 0U;
> +
> + priv->can.can_stats.bus_error++;
> +
> + /* Error occurred during transmission? */
> + if ((msg->ecc & ACC_ECC_DIR) == 0) {
> + can_err_prot_type |= CAN_ERR_PROT_TX;
> + stats->tx_errors++;
> + } else {
> + stats->rx_errors++;
> + }
Nitpick: check the "boolean true" branch first:
if (msg->ecc & ACC_ECC_DIR) {
stats->rx_errors++;
} else {
can_err_prot_type |= CAN_ERR_PROT_TX;
stats->tx_errors++;
}
> + /* Determine error type */
> + switch (msg->ecc & ACC_ECC_MASK) {
> + case ACC_ECC_BIT:
> + can_err_prot_type |= CAN_ERR_PROT_BIT;
> + break;
> + case ACC_ECC_FORM:
> + can_err_prot_type |= CAN_ERR_PROT_FORM;
> + break;
> + case ACC_ECC_STUFF:
> + can_err_prot_type |= CAN_ERR_PROT_STUFF;
> + break;
> + default:
> + can_err_prot_type |= CAN_ERR_PROT_UNSPEC;
> + break;
> + }
> +
> + skb = alloc_can_err_skb(core->netdev, &cf);
> + if (!skb) {
> + stats->rx_dropped++;
The CAN err skb is a socket CAN concept. It does not represent an
actual CAN frame. So no need to count that one as an rx_dropped.
> + return;
> + }
> +
> + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
Set the CAN_ERR_CNT flag to inform the userland that the error
counters are available.
> +
> + /* Set protocol error type */
> + cf->data[2] = can_err_prot_type;
> + /* Set error location */
> + cf->data[3] = msg->ecc & ACC_ECC_SEG;
> +
> + /* Insert CAN TX and RX error counters. */
> + cf->data[6] = txerr;
> + cf->data[7] = rxerr;
> +
> + skb_hwtstamps(skb)->hwtstamp = acc_ts2ktime(priv->ov, msg->ts);
> +
> + netif_rx(skb);
> +}
> +
> +static void
> +handle_core_msg_errstatechange(struct acc_core *core,
> + const struct acc_bmmsg_errstatechange *msg)
> +{
> + struct acc_net_priv *priv = netdev_priv(core->netdev);
> + struct net_device_stats *stats = &core->netdev->stats;
> + struct can_frame *cf = NULL;
> + struct sk_buff *skb;
> + const u32 reg_status = msg->reg_status;
> + const u8 rxerr = reg_status;
> + const u8 txerr = (reg_status >> 8);
> + enum can_state new_state;
> +
> + if (reg_status & ACC_REG_STATUS_MASK_STATUS_BS) {
> + new_state = CAN_STATE_BUS_OFF;
> + } else if (reg_status & ACC_REG_STATUS_MASK_STATUS_EP) {
> + new_state = CAN_STATE_ERROR_PASSIVE;
> + } else if (reg_status & ACC_REG_STATUS_MASK_STATUS_ES) {
> + new_state = CAN_STATE_ERROR_WARNING;
> + } else {
> + new_state = CAN_STATE_ERROR_ACTIVE;
> + if (priv->can.state == CAN_STATE_BUS_OFF) {
> + /* See comment in acc_set_mode() for CAN_MODE_START */
> + netif_wake_queue(core->netdev);
> + }
> + }
> +
> + skb = alloc_can_err_skb(core->netdev, &cf);
> +
> + if (new_state != priv->can.state) {
> + enum can_state tx_state, rx_state;
> +
> + tx_state = (txerr >= rxerr) ?
> + new_state : CAN_STATE_ERROR_ACTIVE;
> + rx_state = (rxerr >= txerr) ?
> + new_state : CAN_STATE_ERROR_ACTIVE;
> +
> + /* Always call can_change_state() to update the state
> + * even if alloc_can_err_skb() may have failed.
> + * can_change_state() can cope with a NULL cf pointer.
> + */
> + can_change_state(core->netdev, cf, tx_state, rx_state);
> + }
> +
> + if (skb) {
> + cf->data[6] = txerr;
> + cf->data[7] = rxerr;
Set the CAN_ERR_CNT flag to inform the userland that the error
counters are available.
> +
> + skb_hwtstamps(skb)->hwtstamp = acc_ts2ktime(priv->ov, msg->ts);
> +
> + netif_rx(skb);
> + } else {
> + stats->rx_dropped++;
The CAN err skb is a socket CAN concept. It does not represent an
actual CAN frame. So no need to count that one as an rx_dropped.
> + }
> +
> + if (new_state == CAN_STATE_BUS_OFF) {
> + acc_write32(core, ACC_CORE_OF_TX_ABORT_MASK, 0xffff);
> + can_bus_off(core->netdev);
> + }
> +}
> +
> +static void handle_core_interrupt(struct acc_core *core)
> +{
> + u32 msg_fifo_head = core->bmfifo.local_irq_cnt & 0xff;
> +
> + while (core->bmfifo.msg_fifo_tail != msg_fifo_head) {
> + const union acc_bmmsg *msg =
> + &core->bmfifo.messages[core->bmfifo.msg_fifo_tail];
> +
> + switch (msg->msg_id) {
> + case BM_MSG_ID_RXTXDONE:
> + handle_core_msg_rxtxdone(core, &msg->rxtxdone);
> + break;
> +
> + case BM_MSG_ID_TXABORT:
> + handle_core_msg_txabort(core, &msg->txabort);
> + break;
> +
> + case BM_MSG_ID_OVERRUN:
> + handle_core_msg_overrun(core, &msg->overrun);
> + break;
> +
> + case BM_MSG_ID_BUSERR:
> + handle_core_msg_buserr(core, &msg->buserr);
> + break;
> +
> + case BM_MSG_ID_ERRPASSIVE:
> + case BM_MSG_ID_ERRWARN:
> + handle_core_msg_errstatechange(core,
> + &msg->errstatechange);
> + break;
> +
> + default:
> + /* Ignore all other BM messages (like the CAN-FD messages) */
> + break;
> + }
> +
> + core->bmfifo.msg_fifo_tail =
> + (core->bmfifo.msg_fifo_tail + 1) & 0xff;
> + }
> +}
> +
> +/**
> + * acc_card_interrupt() - handle the interrupts of an esdACC FPGA
> + *
> + * @ov: overview module structure
> + * @cores: array of core structures
> + *
> + * This function handles all interrupts pending for the overview module and the
> + * CAN cores of the esdACC FPGA.
> + *
> + * It examines for all cores (the overview module core and the CAN cores)
> + * the bmfifo.irq_cnt and compares it with the previously saved
> + * bmfifo.local_irq_cnt. An IRQ is pending if they differ. The esdACC FPGA
> + * updates the bmfifo.irq_cnt values by DMA.
> + *
> + * The pending interrupts are masked by writing to the IRQ mask register at
> + * ACC_OV_OF_BM_IRQ_MASK. This register has for each core a two bit command
> + * field evaluated as follows:
> + *
> + * Define, bit pattern: meaning
> + * 00: no action
> + * ACC_BM_IRQ_UNMASK, 01: unmask interrupt
> + * ACC_BM_IRQ_MASK, 10: mask interrupt
> + * 11: no action
> + *
> + * For each CAN core with a pending IRQ handle_core_interrupt() handles all
> + * busmaster messages from the message FIFO. The last handled message (FIFO
> + * index) is written to the CAN core to acknowledge its handling.
> + *
> + * Last step is to unmask all interrupts in the FPGA using
> + * ACC_BM_IRQ_UNMASK_ALL.
If using kdoc style, then also document the return value. c.f. this
W=2 error message:
drivers/net/can/esd/esdacc.c:719: warning: No description found for
return value of 'acc_card_interrupt'
> + */
> +irqreturn_t acc_card_interrupt(struct acc_ov *ov, struct acc_core *cores)
> +{
> + u32 irqmask;
> + int i;
> +
> + /* First we look for whom interrupts are pending, card/overview
> + * or any of the cores. Two bits in irqmask are used for each;
> + * Each two bit field is set to ACC_BM_IRQ_MASK if an IRQ is
> + * pending.
> + */
> + irqmask = 0;
> + if (READ_ONCE(*ov->bmfifo.irq_cnt) != ov->bmfifo.local_irq_cnt) {
> + irqmask |= ACC_BM_IRQ_MASK;
> + ov->bmfifo.local_irq_cnt = READ_ONCE(*ov->bmfifo.irq_cnt);
> + }
> +
> + for (i = 0; i < ov->active_cores; i++) {
> + struct acc_core *core = &cores[i];
> +
> + if (READ_ONCE(*core->bmfifo.irq_cnt) != core->bmfifo.local_irq_cnt) {
> + irqmask |= (ACC_BM_IRQ_MASK << (2 * (i + 1)));
> + core->bmfifo.local_irq_cnt = READ_ONCE(*core->bmfifo.irq_cnt);
> + }
> + }
> +
> + if (!irqmask)
> + return IRQ_NONE;
> +
> + /* At second we tell the card we're working on them by writing irqmask,
> + * call handle_{ov|core}_interrupt and then acknowledge the
> + * interrupts by writing irq_cnt:
> + */
> + acc_ov_write32(ov, ACC_OV_OF_BM_IRQ_MASK, irqmask);
> +
> + if (irqmask & ACC_BM_IRQ_MASK) {
> + /* handle_ov_interrupt(); - no use yet. */
> + acc_ov_write32(ov, ACC_OV_OF_BM_IRQ_COUNTER,
> + ov->bmfifo.local_irq_cnt);
> + }
> +
> + for (i = 0; i < ov->active_cores; i++) {
> + struct acc_core *core = &cores[i];
> +
> + if (irqmask & (ACC_BM_IRQ_MASK << (2 * (i + 1)))) {
> + handle_core_interrupt(core);
> + acc_write32(core, ACC_OV_OF_BM_IRQ_COUNTER,
> + core->bmfifo.local_irq_cnt);
> + }
> + }
> +
> + acc_ov_write32(ov, ACC_OV_OF_BM_IRQ_MASK, ACC_BM_IRQ_UNMASK_ALL);
> +
> + return IRQ_HANDLED;
> +}
> diff --git a/drivers/net/can/esd/esdacc.h b/drivers/net/can/esd/esdacc.h
> new file mode 100644
> index 000000000000..73651bc1d52c
> --- /dev/null
> +++ b/drivers/net/can/esd/esdacc.h
> @@ -0,0 +1,393 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/* Copyright (C) 2015 - 2016 Thomas Körper, esd electronic system design gmbh
> + * Copyright (C) 2017 - 2022 Stefan Mätje, esd electronics gmbh
> + */
> +
> +#include <linux/bits.h>
> +#include <linux/can/dev.h>
> +#include <linux/kernel.h>
> +#include <linux/netdevice.h>
> +#include <linux/units.h>
> +
> +#define ACC_TS_FREQ_80MHZ (80 * HZ_PER_MHZ)
> +
> +#define ACC_CAN_EFF_FLAG 0x20000000
> +#define ACC_CAN_RTR_FLAG 0x10
> +#define ACC_CAN_DLC_MASK 0x0f
> +
> +#define ACC_OV_OF_PROBE 0x0000
> +#define ACC_OV_OF_VERSION 0x0004
> +#define ACC_OV_OF_INFO 0x0008
> +#define ACC_OV_OF_CANCORE_FREQ 0x000c
> +#define ACC_OV_OF_TS_FREQ_LO 0x0010
> +#define ACC_OV_OF_TS_FREQ_HI 0x0014
> +#define ACC_OV_OF_IRQ_STATUS_CORES 0x0018
> +#define ACC_OV_OF_TS_CURR_LO 0x001c
> +#define ACC_OV_OF_TS_CURR_HI 0x0020
> +#define ACC_OV_OF_IRQ_STATUS 0x0028
> +#define ACC_OV_OF_MODE 0x002c
> +#define ACC_OV_OF_BM_IRQ_COUNTER 0x0070
> +#define ACC_OV_OF_BM_IRQ_MASK 0x0074
> +#define ACC_OV_OF_MSI_DATA 0x0080
> +#define ACC_OV_OF_MSI_ADDRESSOFFSET 0x0084
The #define indentation style is not consistant between the different
files. Please pick one (I suggest the single space to make it easier
to add more defines later on).
> +/* Feature flags are contained in the upper 16 bit of the version
> + * register at ACC_OV_OF_VERSION but only used with these masks after
> + * extraction into an extra variable => (xx - 16).
> + */
> +#define ACC_OV_REG_FEAT_IDX_CANFD (27 - 16)
> +#define ACC_OV_REG_FEAT_IDX_NEW_PSC (28 - 16)
> +#define ACC_OV_REG_FEAT_MASK_CANFD BIT(ACC_OV_REG_FEAT_IDX_CANFD)
> +#define ACC_OV_REG_FEAT_MASK_NEW_PSC BIT(ACC_OV_REG_FEAT_IDX_NEW_PSC)
> +
> +#define ACC_OV_REG_MODE_MASK_ENDIAN_LITTLE 0x00000001
> +#define ACC_OV_REG_MODE_MASK_BM_ENABLE 0x00000002
> +#define ACC_OV_REG_MODE_MASK_MODE_LED 0x00000004
> +#define ACC_OV_REG_MODE_MASK_TIMER 0x00000070
> +#define ACC_OV_REG_MODE_MASK_TIMER_ENABLE 0x00000010
> +#define ACC_OV_REG_MODE_MASK_TIMER_ONE_SHOT 0x00000020
> +#define ACC_OV_REG_MODE_MASK_TIMER_ABSOLUTE 0x00000040
> +#define ACC_OV_REG_MODE_MASK_TS_SRC 0x00000180
> +#define ACC_OV_REG_MODE_MASK_I2C_ENABLE 0x00000800
> +#define ACC_OV_REG_MODE_MASK_MSI_ENABLE 0x00004000
> +#define ACC_OV_REG_MODE_MASK_NEW_PSC_ENABLE 0x00008000
> +#define ACC_OV_REG_MODE_MASK_FPGA_RESET 0x80000000
> +
> +#define ACC_CORE_OF_CTRL_MODE 0x0000
> +#define ACC_CORE_OF_STATUS_IRQ 0x0008
> +#define ACC_CORE_OF_BRP 0x000c
> +#define ACC_CORE_OF_BTR 0x0010
> +#define ACC_CORE_OF_FBTR 0x0014
> +#define ACC_CORE_OF_STATUS 0x0030
> +#define ACC_CORE_OF_TXFIFO_CONFIG 0x0048
> +#define ACC_CORE_OF_TXFIFO_STATUS 0x004c
> +#define ACC_CORE_OF_TX_STATUS_IRQ 0x0050
> +#define ACC_CORE_OF_TX_ABORT_MASK 0x0054
> +#define ACC_CORE_OF_BM_IRQ_COUNTER 0x0070
> +#define ACC_CORE_OF_TXFIFO_ID 0x00c0
> +#define ACC_CORE_OF_TXFIFO_DLC 0x00c4
> +#define ACC_CORE_OF_TXFIFO_DATA_0 0x00c8
> +#define ACC_CORE_OF_TXFIFO_DATA_1 0x00cc
> +
> +#define ACC_REG_CONTROL_IDX_MODE_RESETMODE 0
> +#define ACC_REG_CONTROL_IDX_MODE_LOM 1
> +#define ACC_REG_CONTROL_IDX_MODE_STM 2
> +#define ACC_REG_CONTROL_IDX_MODE_TRANSEN 5
> +#define ACC_REG_CONTROL_IDX_MODE_TS 6
> +#define ACC_REG_CONTROL_IDX_MODE_SCHEDULE 7
> +#define ACC_REG_CONTROL_MASK_MODE_RESETMODE \
> + BIT(ACC_REG_CONTROL_IDX_MODE_RESETMODE)
> +#define ACC_REG_CONTROL_MASK_MODE_LOM \
> + BIT(ACC_REG_CONTROL_IDX_MODE_LOM)
> +#define ACC_REG_CONTROL_MASK_MODE_STM \
> + BIT(ACC_REG_CONTROL_IDX_MODE_STM)
> +#define ACC_REG_CONTROL_MASK_MODE_TRANSEN \
> + BIT(ACC_REG_CONTROL_IDX_MODE_TRANSEN)
> +#define ACC_REG_CONTROL_MASK_MODE_TS \
> + BIT(ACC_REG_CONTROL_IDX_MODE_TS)
> +#define ACC_REG_CONTROL_MASK_MODE_SCHEDULE \
> + BIT(ACC_REG_CONTROL_IDX_MODE_SCHEDULE)
> +
> +#define ACC_REG_CONTROL_IDX_IE_RXTX 8
> +#define ACC_REG_CONTROL_IDX_IE_TXERROR 9
> +#define ACC_REG_CONTROL_IDX_IE_ERRWARN 10
> +#define ACC_REG_CONTROL_IDX_IE_OVERRUN 11
> +#define ACC_REG_CONTROL_IDX_IE_TSI 12
> +#define ACC_REG_CONTROL_IDX_IE_ERRPASS 13
> +#define ACC_REG_CONTROL_IDX_IE_BUSERR 15
> +#define ACC_REG_CONTROL_MASK_IE_RXTX BIT(ACC_REG_CONTROL_IDX_IE_RXTX)
> +#define ACC_REG_CONTROL_MASK_IE_TXERROR BIT(ACC_REG_CONTROL_IDX_IE_TXERROR)
> +#define ACC_REG_CONTROL_MASK_IE_ERRWARN BIT(ACC_REG_CONTROL_IDX_IE_ERRWARN)
> +#define ACC_REG_CONTROL_MASK_IE_OVERRUN BIT(ACC_REG_CONTROL_IDX_IE_OVERRUN)
> +#define ACC_REG_CONTROL_MASK_IE_TSI BIT(ACC_REG_CONTROL_IDX_IE_TSI)
> +#define ACC_REG_CONTROL_MASK_IE_ERRPASS BIT(ACC_REG_CONTROL_IDX_IE_ERRPASS)
> +#define ACC_REG_CONTROL_MASK_IE_BUSERR BIT(ACC_REG_CONTROL_IDX_IE_BUSERR)
> +
> +/* BRP and BTR register layout for CAN-Classic version */
> +#define ACC_REG_BRP_CL_MASK_BRP GENMASK(8, 0)
> +#define ACC_REG_BTR_CL_MASK_TSEG1 GENMASK(3, 0)
> +#define ACC_REG_BTR_CL_MASK_TSEG2 GENMASK(18, 16)
> +#define ACC_REG_BTR_CL_MASK_SJW GENMASK(25, 24)
> +
> +/* BRP and BTR register layout for CAN-FD version */
> +#define ACC_REG_BRP_FD_MASK_BRP GENMASK(7, 0)
> +#define ACC_REG_BTR_FD_MASK_TSEG1 GENMASK(7, 0)
> +#define ACC_REG_BTR_FD_MASK_TSEG2 GENMASK(22, 16)
> +#define ACC_REG_BTR_FD_MASK_SJW GENMASK(30, 24)
> +
> +/* 256 BM_MSGs of 32 byte size */
> +#define ACC_CORE_DMAMSG_SIZE 32U
> +#define ACC_CORE_DMABUF_SIZE (256U * ACC_CORE_DMAMSG_SIZE)
> +
> +enum acc_bmmsg_id {
> + BM_MSG_ID_RXTXDONE = 0x01,
> + BM_MSG_ID_TXABORT = 0x02,
> + BM_MSG_ID_OVERRUN = 0x03,
> + BM_MSG_ID_BUSERR = 0x04,
> + BM_MSG_ID_ERRPASSIVE = 0x05,
> + BM_MSG_ID_ERRWARN = 0x06,
> + BM_MSG_ID_TIMESLICE = 0x07,
> + BM_MSG_ID_HWTIMER = 0x08,
> + BM_MSG_ID_HOTPLUG = 0x09,
> +};
> +
> +/* The struct acc_bmmsg_* structure declarations that follow here provide
> + * access to the ring buffer of bus master messages maintained by the FPGA
> + * bus master engine. All bus master messages have the same size of
> + * ACC_CORE_DMAMSG_SIZE and a minimum alignment of ACC_CORE_DMAMSG_SIZE in
> + * memory.
> + *
> + * All structure members are natural aligned. Therefore we should not need
> + * a __packed attribute. All struct acc_bmmsg_* declarations have at least
> + * reserved* members to fill the structure to the full ACC_CORE_DMAMSG_SIZE.
> + *
> + * A failure of this property due padding will be detected at compile time
> + * by static_assert(sizeof(union acc_bmmsg) == ACC_CORE_DMAMSG_SIZE).
> + */
> +
> +struct acc_bmmsg_rxtxdone {
> + u8 msg_id;
> + u8 txfifo_level;
> + u8 reserved1[2];
> + u8 txtsfifo_level;
> + u8 reserved2[3];
> + u32 id;
> + union {
> + struct {
> + u8 len;
> + u8 reserved0;
Technically, this one is not reserved because is it used in both rx
and tx structures.
> + u8 bits;
> + u8 state;
> + } rxtx;
> + struct {
> + u8 len;
> + u8 msg_lost;
> + u8 bits;
> + u8 state;
> + } rx;
> + struct {
> + u8 len;
> + u8 txfifo_idx;
> + u8 bits;
> + u8 state;
> + } tx;
> + } dlc;
^^^
This looks like a misnomer to me: the union contains more than the dlc.
What about:
struct {
u8 len;
union {
u8 rx_msg_lost;
u8 tx_fifo_idx;
} __packed;
u8 bits;
u8 state;
} rxtx;
in place of that union?
> + u8 data[8];
Nitpick:
u8 data[CAN_MAX_DLEN];
> + /* Time stamps in struct acc_ov::timestamp_frequency ticks. */
> + u64 ts;
> +};
> +
> +struct acc_bmmsg_txabort {
> + u8 msg_id;
> + u8 txfifo_level;
> + u16 abort_mask;
> + u8 txtsfifo_level;
> + u8 reserved2[1];
> + u16 abort_mask_txts;
> + u64 ts;
> + u32 reserved3[4];
> +};
> +
> +struct acc_bmmsg_overrun {
> + u8 msg_id;
> + u8 txfifo_level;
> + u8 lost_cnt;
> + u8 reserved1;
> + u8 txtsfifo_level;
> + u8 reserved2[3];
> + u64 ts;
> + u32 reserved3[4];
> +};
> +
> +struct acc_bmmsg_buserr {
> + u8 msg_id;
> + u8 txfifo_level;
> + u8 ecc;
> + u8 reserved1;
> + u8 txtsfifo_level;
> + u8 reserved2[3];
> + u64 ts;
> + u32 reg_status;
> + u32 reg_btr;
> + u32 reserved3[2];
> +};
> +
> +struct acc_bmmsg_errstatechange {
> + u8 msg_id;
> + u8 txfifo_level;
> + u8 reserved1[2];
> + u8 txtsfifo_level;
> + u8 reserved2[3];
> + u64 ts;
> + u32 reg_status;
> + u32 reserved3[3];
> +};
> +
> +struct acc_bmmsg_timeslice {
> + u8 msg_id;
> + u8 txfifo_level;
> + u8 reserved1[2];
> + u8 txtsfifo_level;
> + u8 reserved2[3];
> + u64 ts;
> + u32 reserved3[4];
> +};
> +
> +struct acc_bmmsg_hwtimer {
> + u8 msg_id;
> + u8 reserved1[3];
> + u32 reserved2[1];
> + u64 timer;
> + u32 reserved3[4];
> +};
> +
> +struct acc_bmmsg_hotplug {
> + u8 msg_id;
> + u8 reserved1[3];
> + u32 reserved2[7];
> +};
> +
> +union acc_bmmsg {
> + u8 msg_id;
> + struct acc_bmmsg_rxtxdone rxtxdone;
> + struct acc_bmmsg_txabort txabort;
> + struct acc_bmmsg_overrun overrun;
> + struct acc_bmmsg_buserr buserr;
> + struct acc_bmmsg_errstatechange errstatechange;
> + struct acc_bmmsg_timeslice timeslice;
> + struct acc_bmmsg_hwtimer hwtimer;
> +};
> +
> +/* Check size of union acc_bmmsg to be of expected size. */
> +static_assert(sizeof(union acc_bmmsg) == ACC_CORE_DMAMSG_SIZE);
> +
> +struct acc_bmfifo {
> + const union acc_bmmsg *messages;
> + /* irq_cnt points to an u32 value where the ESDACC FPGA deposits
> + * the bm_fifo head index in coherent DMA memory. Only bits 7..0
> + * are valid. Use READ_ONCE() to access this memory location.
> + */
> + const u32 *irq_cnt;
> + u32 local_irq_cnt;
> + u32 msg_fifo_tail;
> +};
> +
> +struct acc_core {
> + void __iomem *addr;
> + struct net_device *netdev;
> + struct acc_bmfifo bmfifo;
> + u8 tx_fifo_size;
> + u8 tx_fifo_head;
> + u8 tx_fifo_tail;
> +};
> +
> +struct acc_ov {
> + void __iomem *addr;
> + struct acc_bmfifo bmfifo;
> + u32 timestamp_frequency;
> + u32 core_frequency;
> + u16 version;
> + u16 features;
> + u8 total_cores;
> + u8 active_cores;
> +};
> +
> +struct acc_net_priv {
> + struct can_priv can; /* must be the first member! */
> + struct acc_core *core;
> + struct acc_ov *ov;
> +};
> +
> +static inline u32 acc_read32(struct acc_core *core, unsigned short offs)
> +{
> + return ioread32be(core->addr + offs);
> +}
> +
> +static inline void acc_write32(struct acc_core *core,
> + unsigned short offs, u32 v)
> +{
> + iowrite32be(v, core->addr + offs);
> +}
> +
> +static inline void acc_write32_noswap(struct acc_core *core,
> + unsigned short offs, u32 v)
> +{
> + iowrite32(v, core->addr + offs);
> +}
> +
> +static inline void acc_set_bits(struct acc_core *core,
> + unsigned short offs, u32 mask)
> +{
> + u32 v = acc_read32(core, offs);
> +
> + v |= mask;
> + acc_write32(core, offs, v);
> +}
> +
> +static inline void acc_clear_bits(struct acc_core *core,
> + unsigned short offs, u32 mask)
> +{
> + u32 v = acc_read32(core, offs);
> +
> + v &= ~mask;
> + acc_write32(core, offs, v);
> +}
> +
> +static inline int acc_resetmode_entered(struct acc_core *core)
> +{
> + u32 ctrl = acc_read32(core, ACC_CORE_OF_CTRL_MODE);
> +
> + return (ctrl & ACC_REG_CONTROL_MASK_MODE_RESETMODE) != 0;
> +}
> +
> +static inline u32 acc_ov_read32(struct acc_ov *ov, unsigned short offs)
> +{
> + return ioread32be(ov->addr + offs);
> +}
> +
> +static inline void acc_ov_write32(struct acc_ov *ov,
> + unsigned short offs, u32 v)
> +{
> + iowrite32be(v, ov->addr + offs);
> +}
> +
> +static inline void acc_ov_set_bits(struct acc_ov *ov,
> + unsigned short offs, u32 b)
> +{
> + u32 v = acc_ov_read32(ov, offs);
> +
> + v |= b;
> + acc_ov_write32(ov, offs, v);
> +}
> +
> +static inline void acc_ov_clear_bits(struct acc_ov *ov,
> + unsigned short offs, u32 b)
> +{
> + u32 v = acc_ov_read32(ov, offs);.
> +
> + v &= ~b;
> + acc_ov_write32(ov, offs, v);
> +}
> +
> +static inline void acc_reset_fpga(struct acc_ov *ov)
> +{
> + acc_ov_write32(ov, ACC_OV_OF_MODE, ACC_OV_REG_MODE_MASK_FPGA_RESET);
> +
> + /* Also reset I^2C, to re-detect card addons at every driver start: */
> + acc_ov_clear_bits(ov, ACC_OV_OF_MODE, ACC_OV_REG_MODE_MASK_I2C_ENABLE);
> + mdelay(2);
> + acc_ov_set_bits(ov, ACC_OV_OF_MODE, ACC_OV_REG_MODE_MASK_I2C_ENABLE);
> + mdelay(10);
Maybe add a macro to replace those two delays magic numbers?
> +}
> +
> +void acc_init_ov(struct acc_ov *ov, struct device *dev);
> +void acc_init_bm_ptr(struct acc_ov *ov, struct acc_core *cores,
> + const void *mem);
> +int acc_open(struct net_device *netdev);
> +int acc_close(struct net_device *netdev);
> +netdev_tx_t acc_start_xmit(struct sk_buff *skb, struct net_device *netdev);
> +int acc_get_berr_counter(const struct net_device *netdev,
> + struct can_berr_counter *bec);
> +int acc_set_mode(struct net_device *netdev, enum can_mode mode);
> +int acc_set_bittiming(struct net_device *netdev);
> +irqreturn_t acc_card_interrupt(struct acc_ov *ov, struct acc_core *cores);
> --
> 2.34.1
>
>
^ permalink raw reply
* EIO on send with UDP_SEGMENT
From: Jakub Sitnicki @ 2023-11-08 10:58 UTC (permalink / raw)
To: Willem de Bruijn; +Cc: netdev, kernel-team
Hi Willem et al,
We have hit the EIO error path in udp_send_skb introduced in commit bec1f6f69736
("udp: generate gso with UDP_SEGMENT") [0]:
if (skb->ip_summed != CHECKSUM_PARTIAL || ...) {
kfree_skb(skb);
return -EIO;
}
... when attempting to send a GSO packet, using UDP_SEGMENT option, from
a TUN device which didn't have any offloads enabled (the default case).
A trivial reproducer for that would be:
ip tuntap add dev tun0 mode tun
ip addr add dev tun0 192.0.2.1/24
ip link set dev tun0 up
strace -e %net python -c '
from socket import *
s = socket(AF_INET, SOCK_DGRAM)
s.setsockopt(SOL_UDP, 103, 1200)
s.sendto(b"x" * 3000, ("192.0.2.2", 9))
'
which yields:
socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_IP) = 3
setsockopt(3, SOL_UDP, UDP_SEGMENT, [1200], 4) = 0
sendto(3, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"..., 3000, 0, {sa_family=AF_INET, sin_port=htons(9), sin_addr=inet_addr("192.0.2.2")}, 16) = -1 EIO (Input/output error)
This has been a surprise and caused us some pain. I think it comes down
to that anyone using UDP_SEGMENT has to implement a segmentation
fallback in user-space. Just to be on the safe side. We can't really
assume that any TUN/TAP interface, which happens to be our egress
device, has at least checksum offload enabled and implemented.
Which is not ideal.
So it made us wonder if anything can be done about it?
As it turns out, skb_segment() in GSO path implements a software
fallback not only for segmentation but also for checksumming [1].
What is more, when we removed the skb->ip_summed == CHECKSUM_PARTIAL
restriction in udp_send, as an experiment, we were able to observe fully
checksummed segments in packet capture.
Which brings me to my question -
Do you think the restriction in udp_send_skb can be lifted or tweaked?
Thanks,
Jakub
[0] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=bec1f6f697362c5bc635dacd7ac8499d0a10a4e7
[1] https://elixir.bootlin.com/linux/v6.6/source/net/core/skbuff.c#L4626
^ permalink raw reply
* Re: [PATCH] selftests: bpf: xskxceiver: ksft_print_msg: fix format type error
From: Anders Roxell @ 2023-11-08 11:21 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: bjorn, magnus.karlsson, maciej.fijalkowski, netdev, bpf,
linux-kernel
In-Reply-To: <CAEf4BzahAuskkD9YqxQpZDaUcu_jTuNAfbkkwP4dzJH=cTaVKA@mail.gmail.com>
On Fri, 3 Nov 2023 at 17:26, Andrii Nakryiko <andrii.nakryiko@gmail.com> wrote:
>
> On Fri, Nov 3, 2023 at 4:23 AM Anders Roxell <anders.roxell@linaro.org> wrote:
> >
> > Crossbuilding selftests/bpf for architecture arm64, format specifies
> > type error show up like.
> >
> > xskxceiver.c:912:34: error: format specifies type 'int' but the argument
> > has type '__u64' (aka 'unsigned long long') [-Werror,-Wformat]
> > ksft_print_msg("[%s] expected meta_count [%d], got meta_count [%d]\n",
> > ~~
> > %llu
> > __func__, pkt->pkt_nb, meta->count);
> > ^~~~~~~~~~~
> > xskxceiver.c:929:55: error: format specifies type 'unsigned long long' but
> > the argument has type 'u64' (aka 'unsigned long') [-Werror,-Wformat]
> > ksft_print_msg("Frag invalid addr: %llx len: %u\n", addr, len);
> > ~~~~ ^~~~
> >
>
> With u64s it might be %llx or %lx, depending on architecture, so best
> is to force cast to (long long) or (unsigned long long) and then use
> %llx.
Thank you Andrii,
v2 posted https://lore.kernel.org/bpf/20231108110048.1988128-1-anders.roxell@linaro.org/T/#u
Cheers,
Anders
>
> > Fixing the issues by using the proposed format specifiers by the
> > compilor.
> >
> > Signed-off-by: Anders Roxell <anders.roxell@linaro.org>
> > ---
> > tools/testing/selftests/bpf/xskxceiver.c | 10 +++++-----
> > 1 file changed, 5 insertions(+), 5 deletions(-)
> >
> > diff --git a/tools/testing/selftests/bpf/xskxceiver.c b/tools/testing/selftests/bpf/xskxceiver.c
> > index 591ca9637b23..dc03692f34d8 100644
> > --- a/tools/testing/selftests/bpf/xskxceiver.c
> > +++ b/tools/testing/selftests/bpf/xskxceiver.c
> > @@ -908,7 +908,7 @@ static bool is_metadata_correct(struct pkt *pkt, void *buffer, u64 addr)
> > struct xdp_info *meta = data - sizeof(struct xdp_info);
> >
> > if (meta->count != pkt->pkt_nb) {
> > - ksft_print_msg("[%s] expected meta_count [%d], got meta_count [%d]\n",
> > + ksft_print_msg("[%s] expected meta_count [%d], got meta_count [%llu]\n",
> > __func__, pkt->pkt_nb, meta->count);
> > return false;
> > }
> > @@ -926,11 +926,11 @@ static bool is_frag_valid(struct xsk_umem_info *umem, u64 addr, u32 len, u32 exp
> >
> > if (addr >= umem->num_frames * umem->frame_size ||
> > addr + len > umem->num_frames * umem->frame_size) {
> > - ksft_print_msg("Frag invalid addr: %llx len: %u\n", addr, len);
> > + ksft_print_msg("Frag invalid addr: %lx len: %u\n", addr, len);
> > return false;
> > }
> > if (!umem->unaligned_mode && addr % umem->frame_size + len > umem->frame_size) {
> > - ksft_print_msg("Frag crosses frame boundary addr: %llx len: %u\n", addr, len);
> > + ksft_print_msg("Frag crosses frame boundary addr: %lx len: %u\n", addr, len);
> > return false;
> > }
> >
> > @@ -1029,7 +1029,7 @@ static int complete_pkts(struct xsk_socket_info *xsk, int batch_size)
> > u64 addr = *xsk_ring_cons__comp_addr(&xsk->umem->cq, idx + rcvd - 1);
> >
> > ksft_print_msg("[%s] Too many packets completed\n", __func__);
> > - ksft_print_msg("Last completion address: %llx\n", addr);
> > + ksft_print_msg("Last completion address: %lx\n", addr);
> > return TEST_FAILURE;
> > }
> >
> > @@ -1513,7 +1513,7 @@ static int validate_tx_invalid_descs(struct ifobject *ifobject)
> > }
> >
> > if (stats.tx_invalid_descs != ifobject->xsk->pkt_stream->nb_pkts / 2) {
> > - ksft_print_msg("[%s] tx_invalid_descs incorrect. Got [%u] expected [%u]\n",
> > + ksft_print_msg("[%s] tx_invalid_descs incorrect. Got [%llu] expected [%u]\n",
> > __func__, stats.tx_invalid_descs,
> > ifobject->xsk->pkt_stream->nb_pkts);
> > return TEST_FAILURE;
> > --
> > 2.42.0
> >
> >
^ permalink raw reply
* [RFC PATCH net-next] net/smc: Introduce IPPROTO_SMC for smc
From: D. Wythe @ 2023-11-08 11:25 UTC (permalink / raw)
To: kgraul, wenjia, jaka, wintera; +Cc: kuba, davem, netdev, linux-s390, linux-rdma
From: "D. Wythe" <alibuda@linux.alibaba.com>
This patch attempts to initiate a discussion on creating smc socket
via AF_INET, similar to the following code snippet:
/* create v4 smc sock */
v4 = socket(AF_INET, SOCK_STREAM, IPPROTO_SMC);
/* create v6 smc sock */
v6 = socket(AF_INET6, SOCK_STREAM, IPPROTO_SMC);
As we all know, the way we currently create an SMC socket as
follows.
/* create v4 smc sock */
v4 = socket(AF_SMC, SOCK_STREAM, SMCPROTO_SMC);
/* create v6 smc sock */
v6 = socket(AF_SMC, SOCK_STREAM, SMCPROTO_SMC6);
Note: This is not to suggest removing the SMC path, but rather to propose
adding a new path (inet path).
There are several reasons why we believe it is much better than AF_SMC:
Semantics:
SMC extends the TCP protocol and switches it's data path to RDMA path if
RDMA link is ready. Otherwise, SMC should always try its best to degrade to
TCP. From this perspective, SMC is a protocol derived from TCP and can also
fallback to TCP, It should be considered as part of the same protocol
family as TCP (AF_INET and AF_INET6).
Compatibility & Scalability:
Due to the presence of fallback, we needs to handle it very carefully to
keep the consistent with the TCP sockets. SMC has done a lot of work to
ensure that, but still, there are quite a few issues left, such as:
1. The "ss" command cannot display the process name and ID associated with
the fallback socket.
2. The linger option is ineffective when user try’s to close the fallback
socket.
3. Some eBPF attach points related to INET_SOCK are ineffective under
fallback socket, such as BPF_CGROUP_INET_SOCK_RELEASE.
4. SO_PEEK_OFF is a un-supported sock option for fallback sockets, while
it’s of course supported for tcp sockets.
Of course, we can fix each issue one by one, but it is not a fundamental
solution. Any changes on the inet path may require re-synchronization,
including bug fixes, security fixes, tracing, new features and more. For
example, there is a commit which we think is very valueable:
commit 0dd061a6a115 ("bpf: Add update_socket_protocol hook")
This commit allows users to modify dynamically the protocol before socket
created through eBPF programs, which provides a more flexible approach
than smc_run (LP_PRELOAD). It does not require the process restart
and allows for controlling replacement at the connection level, whereas
smc_run operates at the process level.
However, to benefit from it under the SMC path requires additional
code submission while nothing changes requires to do under inet path.
I'm not saying that these issues cannot be fixed under smc path, however,
the solution for these issues often involves duplicating work that already
done on inet path. Thats to say, if we can be under the inet path, we can
easily reuse the existing infrastructure.
Performance:
In order to ensure consistency between fallback sockets and TCP sockets,
SMC creates an additional TCP socket. This introduces additional overhead
of approximately 15%-20% for the establishment and destruction of fallback
sockets. In fact, for the users we have contacted who have shown interest
in SMC, ensuring consistency in performance between fallback and TCP has
always been their top priority. Since no one can guarantee the
availability of RDMA links, support for SMC on both sides, or if the
user's environment is 100% suitable for SMC. Fallback is the only way to
address those issues, but the additional performance overhead is
unacceptable, as fallback cannot provide the benefits of RDMA and only
brings burden right now.
In inet path, we can embed TCP sock into SMC sock, when fallback occurs,
the socket behaves exactly like a TCP socket. In our POC, the performance
of fallback socket under inet path is almost indistinguishable from of
tcp socket, with less than 1% loss. Additionally, and more importantly,
it has full feature compatibility with TCP socket.
Of course, it is also possible under smc path, but in that way, it
would require a significant amount of work to ensure compatibility with
tcp sockets, which most of them has already been done in inet path.
And still, any changes in inet path may require re-synchronization.
I also noticed that there have been some discussions on this issue before.
Link: https://lore.kernel.org/stable/4a873ea1-ba83-1506-9172-e955d5f9ae16@redhat.com/
And I saw some supportive opinions here, maybe it is time to continue
discussing this matter now.
Signed-off-by: D. Wythe <alibuda@linux.alibaba.com>
---
include/uapi/linux/in.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/include/uapi/linux/in.h b/include/uapi/linux/in.h
index e682ab6..0c6322b 100644
--- a/include/uapi/linux/in.h
+++ b/include/uapi/linux/in.h
@@ -83,6 +83,8 @@ enum {
#define IPPROTO_RAW IPPROTO_RAW
IPPROTO_MPTCP = 262, /* Multipath TCP connection */
#define IPPROTO_MPTCP IPPROTO_MPTCP
+ IPPROTO_SMC = 263, /* Shared Memory Communications */
+#define IPPROTO_SMC IPPROTO_SMC
IPPROTO_MAX
};
#endif
--
1.8.3.1
^ permalink raw reply related
* Re: [RFC PATCH v3 08/12] net: support non paged skb frags
From: Yunsheng Lin @ 2023-11-08 11:25 UTC (permalink / raw)
To: Mina Almasry
Cc: netdev, linux-kernel, linux-arch, linux-kselftest, linux-media,
dri-devel, linaro-mm-sig, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Jesper Dangaard Brouer,
Ilias Apalodimas, Arnd Bergmann, David Ahern, Willem de Bruijn,
Shuah Khan, Sumit Semwal, Christian König, Shakeel Butt,
Jeroen de Borst, Praveen Kaligineedi
In-Reply-To: <CAHS8izPGa99LyEc=AeqNaK8X68b7dovxCHOLbR=hnbaybN_zgQ@mail.gmail.com>
On 2023/11/8 5:19, Mina Almasry wrote:
>>
>>
>
> My personal immediate reaction is that this may just introduce code
> churn without significant benefit. If an unsuspecting caller call
> skb_frag_page() on devmem frag and doesn't correctly handle NULL
> return, it will crash or error out anyway, and likely in some obvious
> way, so maybe the BUG_ON() isn't so useful that it's worth changing
If it will always crash or error out, then I agree that BUG_ON() is
unnecessary.
> all the call sites. But if there is consensus on adding a change like
> you propose, I have no problem adding it.
One obvious benefit I forget to mention is that, it provides a better
semantic that if a caller need to do the return checking:
1. For the old helper, the semantic is not to do the checking if the caller
has ensure that it has passed a readable frag to skb_frag_page(), which
avoid adding some overhead for non-devmen supported drivers.
2. For the new helper, the semantic is to do the checking and we may provide
a compiler '__must_check' function-attribute to ensure the caller to do
the checking.
>
^ permalink raw reply
* [PATCH v2 2/3] net: phy: at803x: Add qca8084_config_init function
From: Luo Jie @ 2023-11-08 11:34 UTC (permalink / raw)
To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni
Cc: netdev, linux-kernel
In-Reply-To: <20231108113445.24825-1-quic_luoj@quicinc.com>
Configure MSE detect threshold and ADC clock edge invert.
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
---
drivers/net/phy/at803x.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index f2a0d1688159..6bea6e31caaa 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -280,6 +280,15 @@
#define QCA8081_PHY_SERDES_MMD1_FIFO_CTRL 0x9072
#define QCA8081_PHY_FIFO_RSTN BIT(11)
+/* QCA8084 ADC clock edge */
+#define QCA8084_ADC_CLK_SEL 0x8b80
+#define QCA8084_ADC_CLK_SEL_ACLK GENMASK(7, 4)
+#define QCA8084_ADC_CLK_SEL_ACLK_FALL 0xf
+#define QCA8084_ADC_CLK_SEL_ACLK_RISE 0x0
+
+#define QCA8084_MSE_THRESHOLD 0x800a
+#define QCA8084_MSE_THRESHOLD_2P5G_VAL 0x51c6
+
MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
@@ -2077,6 +2086,23 @@ static void qca808x_link_change_notify(struct phy_device *phydev)
QCA8081_PHY_FIFO_RSTN, phydev->link ? QCA8081_PHY_FIFO_RSTN : 0);
}
+static int qca8084_config_init(struct phy_device *phydev)
+{
+ int ret;
+
+ /* Invert ADC clock edge */
+ ret = at803x_debug_reg_mask(phydev, QCA8084_ADC_CLK_SEL,
+ QCA8084_ADC_CLK_SEL_ACLK,
+ FIELD_PREP(QCA8084_ADC_CLK_SEL_ACLK,
+ QCA8084_ADC_CLK_SEL_ACLK_FALL));
+ if (ret < 0)
+ return ret;
+
+ /* Adjust MSE threshold value to avoid link issue with some link partner */
+ return phy_write_mmd(phydev, MDIO_MMD_PMAPMD,
+ QCA8084_MSE_THRESHOLD, QCA8084_MSE_THRESHOLD_2P5G_VAL);
+}
+
static struct phy_driver at803x_driver[] = {
{
/* Qualcomm Atheros AR8035 */
@@ -2274,6 +2300,7 @@ static struct phy_driver at803x_driver[] = {
.soft_reset = qca808x_soft_reset,
.cable_test_start = qca808x_cable_test_start,
.cable_test_get_status = qca808x_cable_test_get_status,
+ .config_init = qca8084_config_init,
}, };
module_phy_driver(at803x_driver);
--
2.42.0
^ permalink raw reply related
* [PATCH v2 1/3] net: phy: at803x: add QCA8084 ethernet phy support
From: Luo Jie @ 2023-11-08 11:34 UTC (permalink / raw)
To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni
Cc: netdev, linux-kernel
In-Reply-To: <20231108113445.24825-1-quic_luoj@quicinc.com>
Add qca8084 PHY support, which is four-port PHY with maximum
link capability 2.5G, the features of each port is almost same
as QCA8081 and slave seed config is not needed.
Three kind of interface modes supported by qca8084.
PHY_INTERFACE_MODE_QUSGMII, PHY_INTERFACE_MODE_2500BASEX and
PHY_INTERFACE_MODE_SGMII.
The PCS(serdes) and clock are also needed to be configured to
bringup qca8084 PHY, which will be added in the pcs driver.
The additional CDT configurations used for qca8084.
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
---
drivers/net/phy/at803x.c | 48 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 37fb033e1c29..f2a0d1688159 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -176,6 +176,7 @@
#define AT8030_PHY_ID_MASK 0xffffffef
#define QCA8081_PHY_ID 0x004dd101
+#define QCA8084_PHY_ID 0x004dd180
#define QCA8327_A_PHY_ID 0x004dd033
#define QCA8327_B_PHY_ID 0x004dd034
@@ -1760,6 +1761,9 @@ static bool qca808x_is_prefer_master(struct phy_device *phydev)
static bool qca808x_has_fast_retrain_or_slave_seed(struct phy_device *phydev)
{
+ if (phydev_id_compare(phydev, QCA8084_PHY_ID))
+ return false;
+
return linkmode_test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported);
}
@@ -1824,6 +1828,21 @@ static int qca808x_read_status(struct phy_device *phydev)
return ret;
if (phydev->link) {
+ /* There are two PCSs available for QCA8084, which support the following
+ * interface modes.
+ *
+ * 1. PHY_INTERFACE_MODE_QUSGMII utilizes PCS1 for all available 4 ports,
+ * which is for all link speeds.
+ *
+ * 2. PHY_INTERFACE_MODE_2500BASEX utilizes PCS0 for the fourth port,
+ * which is only for the link speed 2500M same as QCA8081.
+ *
+ * 3. PHY_INTERFACE_MODE_SGMII utilizes PCS0 for the fourth port,
+ * which is for the link speed 10M, 100M and 1000M same as QCA8081.
+ */
+ if (phydev->interface == PHY_INTERFACE_MODE_QUSGMII)
+ return 0;
+
if (phydev->speed == SPEED_2500)
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
else
@@ -1958,6 +1977,14 @@ static int qca808x_cable_test_start(struct phy_device *phydev)
phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807a, 0xc060);
phy_write_mmd(phydev, MDIO_MMD_PCS, 0x807e, 0xb060);
+ if (phydev_id_compare(phydev, QCA8084_PHY_ID)) {
+ /* Adjust the positive and negative pulse thereshold of CDT */
+ phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8075, 0xa060);
+
+ /* Disable the near echo bypass */
+ phy_modify_mmd(phydev, MDIO_MMD_PCS, 0x807f, BIT(15), 0);
+ }
+
return 0;
}
@@ -2227,6 +2254,26 @@ static struct phy_driver at803x_driver[] = {
.cable_test_start = qca808x_cable_test_start,
.cable_test_get_status = qca808x_cable_test_get_status,
.link_change_notify = qca808x_link_change_notify,
+}, {
+ /* Qualcomm QCA8084 */
+ PHY_ID_MATCH_MODEL(QCA8084_PHY_ID),
+ .name = "Qualcomm QCA8084",
+ .flags = PHY_POLL_CABLE_TEST,
+ .probe = at803x_probe,
+ .config_intr = at803x_config_intr,
+ .handle_interrupt = at803x_handle_interrupt,
+ .get_tunable = at803x_get_tunable,
+ .set_tunable = at803x_set_tunable,
+ .set_wol = at803x_set_wol,
+ .get_wol = at803x_get_wol,
+ .get_features = qca808x_get_features,
+ .config_aneg = at803x_config_aneg,
+ .suspend = genphy_suspend,
+ .resume = genphy_resume,
+ .read_status = qca808x_read_status,
+ .soft_reset = qca808x_soft_reset,
+ .cable_test_start = qca808x_cable_test_start,
+ .cable_test_get_status = qca808x_cable_test_get_status,
}, };
module_phy_driver(at803x_driver);
@@ -2242,6 +2289,7 @@ static struct mdio_device_id __maybe_unused atheros_tbl[] = {
{ PHY_ID_MATCH_EXACT(QCA8327_B_PHY_ID) },
{ PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) },
{ PHY_ID_MATCH_EXACT(QCA8081_PHY_ID) },
+ { PHY_ID_MATCH_MODEL(QCA8084_PHY_ID) },
{ }
};
--
2.42.0
^ permalink raw reply related
* [PATCH v2 0/3] add qca8084 ethernet phy driver
From: Luo Jie @ 2023-11-08 11:34 UTC (permalink / raw)
To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni
Cc: netdev, linux-kernel
QCA8084 is four-port PHY with maximum link capability 2.5G,
which supports the interface mode qusgmii and sgmii mode,
there are two PCSs available to connected with ethernet port.
QCA8084 can work in switch mode or PHY mode.
For switch mode, both PCS0 and PCS1 work on sgmii mode.
For PHY mode, PCS1 works on qusgmii mode, the last port
(the fourth port) works on sgmii mode.
Besides this PHY driver patches, the PCS driver is also needed
to bring up the qca8084 device, which mainly configurs PCS
and clocks.
Luo Jie (3):
net: phy: at803x: add QCA8084 ethernet phy support
net: phy: at803x: Add qca8084_config_init function
net: phy: qca8084: add qca8084_link_change_notify
drivers/net/phy/at803x.c | 112 +++++++++++++++++++++++++++++++++++++++
1 file changed, 112 insertions(+)
base-commit: 2220f68f4504aa1ccce0fac721ccdb301e9da32f
--
2.42.0
^ permalink raw reply
* [PATCH v2 3/3] net: phy: qca8084: add qca8084_link_change_notify
From: Luo Jie @ 2023-11-08 11:34 UTC (permalink / raw)
To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni
Cc: netdev, linux-kernel
In-Reply-To: <20231108113445.24825-1-quic_luoj@quicinc.com>
When the link is changed, qca8084 needs to do the fifo reset and
adjust the IPG level for the qusgmii link speed 1000M.
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
---
drivers/net/phy/at803x.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 6bea6e31caaa..4906775770b3 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -289,6 +289,13 @@
#define QCA8084_MSE_THRESHOLD 0x800a
#define QCA8084_MSE_THRESHOLD_2P5G_VAL 0x51c6
+#define QCA8084_FIFO_CONTROL 0x19
+#define QCA8084_FIFO_MAC_2_PHY BIT(1)
+#define QCA8084_FIFO_PHY_2_MAC BIT(0)
+
+#define QCA8084_MMD7_IPG_OP 0x901d
+#define QCA8084_IPG_10_TO_11_EN BIT(0)
+
MODULE_DESCRIPTION("Qualcomm Atheros AR803x and QCA808X PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
@@ -2103,6 +2110,35 @@ static int qca8084_config_init(struct phy_device *phydev)
QCA8084_MSE_THRESHOLD, QCA8084_MSE_THRESHOLD_2P5G_VAL);
}
+static void qca8084_link_change_notify(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = phy_modify(phydev, QCA8084_FIFO_CONTROL,
+ QCA8084_FIFO_MAC_2_PHY | QCA8084_FIFO_PHY_2_MAC,
+ 0);
+ if (ret)
+ return;
+
+ /* If the PHY works on PHY_INTERFACE_MODE_QUSGMII mode, the fifo needs to
+ * be kept as reset state in link down status.
+ */
+ if (phydev->interface != PHY_INTERFACE_MODE_QUSGMII || phydev->link) {
+ msleep(50);
+ ret = phy_modify(phydev, QCA8084_FIFO_CONTROL,
+ QCA8084_FIFO_MAC_2_PHY | QCA8084_FIFO_PHY_2_MAC,
+ QCA8084_FIFO_MAC_2_PHY | QCA8084_FIFO_PHY_2_MAC);
+ if (ret)
+ return;
+ }
+
+ /* Enable IPG 10 to 11 tuning on link speed 1000M of QUSGMII mode. */
+ if (phydev->interface == PHY_INTERFACE_MODE_QUSGMII)
+ phy_modify_mmd(phydev, MDIO_MMD_AN, QCA8084_MMD7_IPG_OP,
+ QCA8084_IPG_10_TO_11_EN,
+ phydev->speed == SPEED_1000 ? QCA8084_IPG_10_TO_11_EN : 0);
+}
+
static struct phy_driver at803x_driver[] = {
{
/* Qualcomm Atheros AR8035 */
@@ -2301,6 +2337,7 @@ static struct phy_driver at803x_driver[] = {
.cable_test_start = qca808x_cable_test_start,
.cable_test_get_status = qca808x_cable_test_get_status,
.config_init = qca8084_config_init,
+ .link_change_notify = qca8084_link_change_notify,
}, };
module_phy_driver(at803x_driver);
--
2.42.0
^ permalink raw reply related
* Re: [PATCH net 1/3] dpll: fix pin dump crash after module unbind
From: Przemek Kitszel @ 2023-11-08 11:36 UTC (permalink / raw)
To: Arkadiusz Kubalewski, netdev
Cc: vadim.fedorenko, jiri, michal.michalik, milena.olech, pabeni,
kuba
In-Reply-To: <20231108103226.1168500-2-arkadiusz.kubalewski@intel.com>
On 11/8/23 11:32, Arkadiusz Kubalewski wrote:
> Disallow dump of unregistered parent pins, it is possible when parent
> pin and dpll device registerer kernel module instance unbinds, and
> other kernel module instances of the same dpll device have pins
> registered with the parent pin. The user can invoke a pin-dump but as
> the parent was unregistered, thus shall not be accessed by the
> userspace, prevent that by checking if parent pin is still registered.
>
> Fixes: 9d71b54b65b1 ("dpll: netlink: Add DPLL framework base functions")
> Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
> ---
> drivers/dpll/dpll_netlink.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
> index a6dc3997bf5c..93fc6c4b8a78 100644
> --- a/drivers/dpll/dpll_netlink.c
> +++ b/drivers/dpll/dpll_netlink.c
> @@ -328,6 +328,13 @@ dpll_msg_add_pin_parents(struct sk_buff *msg, struct dpll_pin *pin,
> void *parent_priv;
>
> ppin = ref->pin;
> + /*
> + * dump parent only if it is registered, thus prevent crash on
> + * pin dump called when driver which registered the pin unbinds
> + * and different instance registered pin on that parent pin
> + */
> + if (!xa_get_mark(&dpll_pin_xa, ppin->id, DPLL_REGISTERED))
> + continue;
What if unregister/unbind would happen right [here]?
[here]
> parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, ppin);
> ret = ops->state_on_pin_get(pin,
> dpll_pin_on_pin_priv(ppin, pin),
^ permalink raw reply
* RE: [PATCH net 1/3] dpll: fix pin dump crash after module unbind
From: Kubalewski, Arkadiusz @ 2023-11-08 12:08 UTC (permalink / raw)
To: Kitszel, Przemyslaw, netdev@vger.kernel.org
Cc: vadim.fedorenko@linux.dev, jiri@resnulli.us, Michalik, Michal,
Olech, Milena, pabeni@redhat.com, kuba@kernel.org
In-Reply-To: <a0d2089d-9392-3028-1265-efcfbfad7ab1@intel.com>
>From: Kitszel, Przemyslaw <przemyslaw.kitszel@intel.com>
>Sent: Wednesday, November 8, 2023 12:36 PM
>
>On 11/8/23 11:32, Arkadiusz Kubalewski wrote:
>> Disallow dump of unregistered parent pins, it is possible when parent
>> pin and dpll device registerer kernel module instance unbinds, and
>> other kernel module instances of the same dpll device have pins
>> registered with the parent pin. The user can invoke a pin-dump but as
>> the parent was unregistered, thus shall not be accessed by the
>> userspace, prevent that by checking if parent pin is still registered.
>>
>> Fixes: 9d71b54b65b1 ("dpll: netlink: Add DPLL framework base functions")
>> Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
>> ---
>> drivers/dpll/dpll_netlink.c | 7 +++++++
>> 1 file changed, 7 insertions(+)
>>
>> diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c
>> index a6dc3997bf5c..93fc6c4b8a78 100644
>> --- a/drivers/dpll/dpll_netlink.c
>> +++ b/drivers/dpll/dpll_netlink.c
>> @@ -328,6 +328,13 @@ dpll_msg_add_pin_parents(struct sk_buff *msg, struct
>dpll_pin *pin,
>> void *parent_priv;
>>
>> ppin = ref->pin;
>> + /*
>> + * dump parent only if it is registered, thus prevent crash on
>> + * pin dump called when driver which registered the pin unbinds
>> + * and different instance registered pin on that parent pin
>> + */
>> + if (!xa_get_mark(&dpll_pin_xa, ppin->id, DPLL_REGISTERED))
>> + continue;
>
>What if unregister/unbind would happen right [here]?
>[here]
There is a "global" mutex lock which guards the pin/dpll registration and all
netlink requests. For netlink requests in this case it is acquired in the
dpll_pin_pre_doit(..), while all the dpll subsystem interaction from kernel
modules are guarded in dpll_core.c api functions with the same lock.
So after all this use case is protected, just "higher" in the stack.
Thank you!
Arkadiusz
>
>> parent_priv = dpll_pin_on_dpll_priv(dpll_ref->dpll, ppin);
>> ret = ops->state_on_pin_get(pin,
>> dpll_pin_on_pin_priv(ppin, pin),
^ permalink raw reply
* Re: [PATCH v2 1/3] net: phy: at803x: add QCA8084 ethernet phy support
From: Maxime Chevallier @ 2023-11-08 12:12 UTC (permalink / raw)
To: Luo Jie
Cc: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
linux-kernel
In-Reply-To: <20231108113445.24825-2-quic_luoj@quicinc.com>
Hello,
On Wed, 8 Nov 2023 19:34:43 +0800
Luo Jie <quic_luoj@quicinc.com> wrote:
> Add qca8084 PHY support, which is four-port PHY with maximum
> link capability 2.5G, the features of each port is almost same
> as QCA8081 and slave seed config is not needed.
>
> Three kind of interface modes supported by qca8084.
> PHY_INTERFACE_MODE_QUSGMII, PHY_INTERFACE_MODE_2500BASEX and
> PHY_INTERFACE_MODE_SGMII.
>
> The PCS(serdes) and clock are also needed to be configured to
> bringup qca8084 PHY, which will be added in the pcs driver.
>
> The additional CDT configurations used for qca8084.
>
> Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
> ---
> drivers/net/phy/at803x.c | 48 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 48 insertions(+)
[...]
> @@ -1824,6 +1828,21 @@ static int qca808x_read_status(struct phy_device *phydev)
> return ret;
>
> if (phydev->link) {
> + /* There are two PCSs available for QCA8084, which support the following
> + * interface modes.
> + *
> + * 1. PHY_INTERFACE_MODE_QUSGMII utilizes PCS1 for all available 4 ports,
> + * which is for all link speeds.
> + *
> + * 2. PHY_INTERFACE_MODE_2500BASEX utilizes PCS0 for the fourth port,
> + * which is only for the link speed 2500M same as QCA8081.
> + *
> + * 3. PHY_INTERFACE_MODE_SGMII utilizes PCS0 for the fourth port,
> + * which is for the link speed 10M, 100M and 1000M same as QCA8081.
> + */
> + if (phydev->interface == PHY_INTERFACE_MODE_QUSGMII)
> + return 0;
> +
What I understand from this is that this PHY can be used either as a
switch, in which case port 4 would be connected to the host interface
at up to 2.5G, or as a quad-phy, but since it uses QUSGMII the link
speed would be limited to 1G per-port, is that correct ?
However the get_features function seems to build the supported modes
set by reading some capabilities registers :
static int qca808x_get_features(struct phy_device *phydev)
{
[...]
ret = phy_read_mmd(phydev, MDIO_MMD_AN, QCA808X_PHY_MMD7_CHIP_TYPE);
if (ret < 0)
return ret;
if (QCA808X_PHY_CHIP_TYPE_1G & ret)
linkmode_clear_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, phydev->supported);
[...]
}
Wouldn't port 4 report 2.5G capabilities then ? Maybe you need to
mask-out the 2.5G bit if the interface is qusgmii.
Best regards,
Maxime
^ permalink raw reply
* Re: [ANN] netdev development stats for 6.7
From: Hangbin Liu @ 2023-11-08 12:22 UTC (permalink / raw)
To: Jakub Kicinski
Cc: netdev, netdev-driver-reviewers, Stanislav Fomichev, Simon Horman,
Toke Høiland-Jørgensen
In-Reply-To: <20231101162906.59631ffa@kernel.org>
Hi Jakub,
On Wed, Nov 01, 2023 at 04:29:06PM -0700, Jakub Kicinski wrote:
> Top reviewers (thr): Top reviewers (msg):
> 1 ( +2) [42] RedHat 1 ( +2) [71] RedHat
> 2 ( ) [27] Meta 2 ( -1) [52] Meta
> 3 ( +2) [23] Intel 3 ( +2) [46] Intel
> 4 ( +2) [15] Google 4 ( +2) [33] Andrew Lunn
> 5 ( -1) [12] nVidia 5 ( +2) [29] Google
> 6 ( +1) [12] Andrew Lunn 6 ( -2) [23] nVidia
> 7 ( +3) [ 7] Enfabrica 7 ( +4) [14] Broadcom
I just noticed this stats report from Simon. Thanks for your work and
sharing. I want to know if there is a way to bind my personal email
with my company so my review could increase my company's score :)
I think there are some other company developers who use their own email
also curious.
Thanks and Best Regards
Hangbin
^ permalink raw reply
* [syzbot] [wireless?] [net?] WARNING in ieee80211_rfkill_poll
From: syzbot @ 2023-11-08 12:38 UTC (permalink / raw)
To: davem, edumazet, johannes, kuba, linux-kernel, linux-usb,
linux-wireless, netdev, pabeni, syzkaller-bugs
Hello,
syzbot found the following issue on:
HEAD commit: 90b0c2b2edd1 Merge tag 'pinctrl-v6.7-1' of git://git.kerne..
git tree: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-testing
console output: https://syzkaller.appspot.com/x/log.txt?x=1437f47b680000
kernel config: https://syzkaller.appspot.com/x/.config?x=b0220f5f3436eb1a
dashboard link: https://syzkaller.appspot.com/bug?extid=7e59a5bfc7a897247e18
compiler: gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=13c670c0e80000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=1310d47b680000
Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/38f32e2d2d96/disk-90b0c2b2.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/ec454d0d1d26/vmlinux-90b0c2b2.xz
kernel image: https://storage.googleapis.com/syzbot-assets/110137c447a9/bzImage-90b0c2b2.xz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+7e59a5bfc7a897247e18@syzkaller.appspotmail.com
------------[ cut here ]------------
WARNING: CPU: 1 PID: 732 at net/mac80211/driver-ops.h:688 drv_rfkill_poll net/mac80211/driver-ops.h:688 [inline]
WARNING: CPU: 1 PID: 732 at net/mac80211/driver-ops.h:688 ieee80211_rfkill_poll+0x134/0x170 net/mac80211/cfg.c:3100
Modules linked in:
CPU: 1 PID: 732 Comm: kworker/1:2 Not tainted 6.6.0-syzkaller-14142-g90b0c2b2edd1 #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/09/2023
Workqueue: events_power_efficient rfkill_poll
RIP: 0010:drv_rfkill_poll net/mac80211/driver-ops.h:688 [inline]
RIP: 0010:ieee80211_rfkill_poll+0x134/0x170 net/mac80211/cfg.c:3100
Code: 60 07 00 00 be ff ff ff ff 48 8d 78 68 e8 44 f4 38 00 31 ff 89 c5 89 c6 e8 89 59 39 fb 85 ed 0f 85 44 ff ff ff e8 0c 5e 39 fb <0f> 0b e9 38 ff ff ff e8 00 5e 39 fb 0f 0b 48 c7 c7 f8 16 34 89 e8
RSP: 0018:ffffc90001cafc90 EFLAGS: 00010293
RAX: 0000000000000000 RBX: ffff888100ff0700 RCX: ffffffff8614b267
RDX: ffff888107368000 RSI: ffffffff8614b274 RDI: 0000000000000005
RBP: 0000000000000000 R08: 0000000000000005 R09: 0000000000000000
R10: 0000000000000000 R11: 1ffffffff15c0565 R12: ffff888100ff0700
R13: 0000000000000001 R14: ffffc90001cafd80 R15: ffff8881f673ad40
FS: 0000000000000000(0000) GS:ffff8881f6700000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f6477ad0e40 CR3: 00000001122fe000 CR4: 00000000003506f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
<TASK>
rdev_rfkill_poll net/wireless/rdev-ops.h:636 [inline]
cfg80211_rfkill_poll+0xc9/0x240 net/wireless/core.c:224
rfkill_poll+0x8d/0x110 net/rfkill/core.c:1037
process_one_work+0x884/0x15c0 kernel/workqueue.c:2630
process_scheduled_works kernel/workqueue.c:2703 [inline]
worker_thread+0x8b9/0x1290 kernel/workqueue.c:2784
kthread+0x33c/0x440 kernel/kthread.c:388
ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:147
ret_from_fork_asm+0x11/0x20 arch/x86/entry/entry_64.S:242
</TASK>
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup
^ permalink raw reply
* [PATCH 00/22] -Wmissing-prototype warning fixes
From: Arnd Bergmann @ 2023-11-08 12:58 UTC (permalink / raw)
To: Andrew Morton, linux-kernel, Masahiro Yamada, linux-kbuild
Cc: Arnd Bergmann, Matt Turner, Vineet Gupta, Russell King,
Catalin Marinas, Will Deacon, Steven Rostedt, Masami Hiramatsu,
Mark Rutland, Guo Ren, Peter Zijlstra, Ard Biesheuvel,
Huacai Chen, Greg Ungerer, Michal Simek, Thomas Bogendoerfer,
Dinh Nguyen, Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Geoff Levand, Palmer Dabbelt, Heiko Carstens,
John Paul Adrian Glaubitz, David S. Miller, Andy Lutomirski,
Thomas Gleixner, Ingo Molnar, x86, Helge Deller, Sudip Mukherjee,
Greg Kroah-Hartman, Timur Tabi, Kent Overstreet, David Woodhouse,
Naveen N. Rao, Anil S Keshavamurthy, Kees Cook, Vincenzo Frascino,
Juri Lelli, Vincent Guittot, Nathan Chancellor, Nick Desaulniers,
Nicolas Schier, Al Viro, Uwe Kleine-König, linux-alpha,
linux-snps-arc, linux-arm-kernel, linux-trace-kernel, linux-csky,
loongarch, linux-m68k, linux-mips, linuxppc-dev, linux-riscv,
linux-s390, linux-sh, sparclinux, netdev, linux-parisc, linux-usb,
linux-fbdev, dri-devel, linux-bcachefs, linux-mtd
From: Arnd Bergmann <arnd@arndb.de>
I slightly dropped the ball on this since last sending the series in
August, but a number of warning fixes have made it into the kernel in
the meantime, both from my earlier submission and from architecture
maintainers.
I have none patches that remain from the previous submission, with
two of them reworked according to comments. The additional patches
are from more testing across architectures and configurations that
I had previously missed.
At least one patch is for a newly added warning in recent kernels.
Regarding the regressions in terms of added warnings, there are
now only five architectures left that add warnings (alpha, mips,
nios2, sh and sparc) rather than 15, so I think we can apply
the Kbuild change directly and have the architecture maintainers
take care of the warnings just like the others did already.
As before, my preference would be for the patches to make it
through the respective subsystem maintainer trees, though I
can apply the architecture specific ones to the asm-generic
tree as well.
Sorry for posting these during the merge window, I wanted to
get them out before LPC so we can have them in linux-next
as early as possible.
Arnd
Link: https://lore.kernel.org/lkml/20230810141947.1236730-1-arnd@kernel.org/
Arnd Bergmann (22):
[RESEND^2] ida: make 'ida_dump' static
[RESEND^2] jffs2: mark __jffs2_dbg_superblock_counts() static
[RESEND] kprobes: unify kprobes_exceptions_nofify() prototypes
[RESEND] time: make sysfs_get_uname() function visible in header
[RESEND] parport: gsc: mark init function static
[RESEND] stackleak: add declarations for global functions
[RESEND] sched: fair: move unused stub functions to header
[v2] arch: consolidate arch_irq_work_raise prototypes
[v2] arch: fix asm-offsets.c building with -Wmissing-prototypes
microblaze: include linux/cpu.h for trap_init() prototype
x86: sta2x11: include header for sta2x11_get_instance() prototype
csky: fix arch_jump_label_transform_static override
arch: add do_page_fault prototypes
arch: add missing prepare_ftrace_return() prototypes
arch: vdso: consolidate gettime prototypes
bcachefs: mark bch2_target_to_text_sb() static
powerpc: ps3: move udbg_shutdown_ps3gelic prototype
powerpc: pasemi: mark pas_shutdown() static
powerpc: powermac: mark smp_psurge_{give,take}_timebase static
usb: fsl-mph-dr-of: mark fsl_usb2_mpc5121_init() static
fbdev/fsl-diu-fb: mark wr_reg_wa() static
Makefile.extrawarn: turn on missing-prototypes globally
arch/alpha/include/asm/mmu_context.h | 2 ++
arch/alpha/kernel/asm-offsets.c | 2 +-
arch/alpha/kernel/traps.c | 1 +
arch/arc/include/asm/kprobes.h | 3 ---
arch/arm/include/asm/irq_work.h | 2 --
arch/arm/include/asm/kprobes.h | 2 --
arch/arm/include/asm/vdso.h | 5 ----
arch/arm/vdso/vgettimeofday.c | 1 +
arch/arm64/include/asm/irq_work.h | 2 --
arch/arm64/include/asm/kprobes.h | 2 --
arch/arm64/kernel/vdso32/vgettimeofday.c | 1 +
arch/csky/include/asm/ftrace.h | 4 +++
arch/csky/include/asm/irq_work.h | 2 +-
arch/csky/include/asm/jump_label.h | 5 ++++
arch/csky/include/asm/traps.h | 2 +-
arch/csky/kernel/traps.c | 1 +
arch/csky/kernel/vdso/vgettimeofday.c | 11 +--------
arch/loongarch/kernel/asm-offsets.c | 26 ++++++++++----------
arch/loongarch/vdso/vgettimeofday.c | 7 +-----
arch/m68k/coldfire/vectors.c | 3 +--
arch/m68k/coldfire/vectors.h | 3 ---
arch/microblaze/include/asm/ftrace.h | 1 +
arch/microblaze/kernel/traps.c | 1 +
arch/mips/include/asm/ftrace.h | 4 +++
arch/mips/include/asm/kprobes.h | 2 --
arch/mips/include/asm/traps.h | 3 +++
arch/mips/vdso/vgettimeofday.c | 1 +
arch/nios2/include/asm/traps.h | 2 ++
arch/powerpc/include/asm/irq_work.h | 1 -
arch/powerpc/include/asm/kprobes.h | 2 --
arch/powerpc/include/asm/ps3.h | 6 +++++
arch/powerpc/platforms/pasemi/setup.c | 2 +-
arch/powerpc/platforms/powermac/smp.c | 4 +--
arch/powerpc/platforms/ps3/gelic_udbg.c | 1 +
arch/riscv/include/asm/irq_work.h | 2 +-
arch/riscv/kernel/vdso/vgettimeofday.c | 7 +-----
arch/s390/include/asm/irq_work.h | 2 --
arch/s390/include/asm/kprobes.h | 2 --
arch/sh/include/asm/kprobes.h | 2 --
arch/sh/include/asm/traps_32.h | 3 +++
arch/sparc/include/asm/kprobes.h | 2 --
arch/sparc/kernel/asm-offsets.c | 6 ++---
arch/sparc/kernel/traps_32.c | 1 +
arch/sparc/kernel/traps_64.c | 1 +
arch/x86/entry/vdso/vclock_gettime.c | 10 +-------
arch/x86/include/asm/irq_work.h | 1 -
arch/x86/include/asm/kprobes.h | 2 --
arch/x86/include/asm/traps.h | 1 -
arch/x86/include/asm/vdso/gettimeofday.h | 2 --
arch/x86/kernel/traps.c | 1 +
arch/x86/pci/sta2x11-fixup.c | 1 +
arch/x86/um/vdso/um_vdso.c | 1 +
drivers/net/ethernet/toshiba/ps3_gelic_net.h | 6 -----
drivers/parport/parport_gsc.c | 2 +-
drivers/usb/host/fsl-mph-dr-of.c | 2 +-
drivers/video/fbdev/fsl-diu-fb.c | 2 +-
fs/bcachefs/disk_groups.c | 2 +-
fs/jffs2/debug.c | 2 +-
include/linux/irq_work.h | 3 +++
include/linux/kprobes.h | 4 +++
include/linux/stackleak.h | 6 +++++
include/vdso/gettime.h | 23 +++++++++++++++++
kernel/sched/fair.c | 13 ----------
kernel/sched/sched.h | 11 +++++++++
kernel/time/tick-internal.h | 3 ++-
lib/test_ida.c | 2 +-
scripts/Makefile.extrawarn | 4 +--
67 files changed, 127 insertions(+), 122 deletions(-)
delete mode 100644 arch/m68k/coldfire/vectors.h
create mode 100644 include/vdso/gettime.h
--
2.39.2
Cc: Matt Turner <mattst88@gmail.com>
Cc: Vineet Gupta <vgupta@kernel.org>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Guo Ren <guoren@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ard Biesheuvel <ardb@kernel.org>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Greg Ungerer <gerg@linux-m68k.org>
Cc: Michal Simek <monstr@monstr.eu>
Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Cc: Dinh Nguyen <dinguyen@kernel.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Christophe Leroy <christophe.leroy@csgroup.eu>
Cc: Geoff Levand <geoff@infradead.org>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: x86@kernel.org
Cc: Helge Deller <deller@gmx.de>
Cc: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Timur Tabi <timur@kernel.org>
Cc: Kent Overstreet <kent.overstreet@linux.dev>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: "Naveen N. Rao" <naveen.n.rao@linux.ibm.com>
Cc: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nick Desaulniers <ndesaulniers@google.com>
Cc: Nicolas Schier <nicolas@fjasle.eu>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: "Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>
Cc: linux-alpha@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-snps-arc@lists.infradead.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-trace-kernel@vger.kernel.org
Cc: linux-csky@vger.kernel.org
Cc: loongarch@lists.linux.dev
Cc: linux-m68k@lists.linux-m68k.org
Cc: linux-mips@vger.kernel.org
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-riscv@lists.infradead.org
Cc: linux-s390@vger.kernel.org
Cc: linux-sh@vger.kernel.org
Cc: sparclinux@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: linux-parisc@vger.kernel.org
Cc: linux-usb@vger.kernel.org
Cc: linux-fbdev@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linux-bcachefs@vger.kernel.org
Cc: linux-mtd@lists.infradead.org
Cc: linux-kbuild@vger.kernel.org
^ permalink raw reply
* [PATCH 01/22] [RESEND^2] ida: make 'ida_dump' static
From: Arnd Bergmann @ 2023-11-08 12:58 UTC (permalink / raw)
To: Andrew Morton, linux-kernel, Masahiro Yamada, linux-kbuild
Cc: Arnd Bergmann, Matt Turner, Vineet Gupta, Russell King,
Catalin Marinas, Will Deacon, Steven Rostedt, Masami Hiramatsu,
Mark Rutland, Guo Ren, Peter Zijlstra, Ard Biesheuvel,
Huacai Chen, Greg Ungerer, Michal Simek, Thomas Bogendoerfer,
Dinh Nguyen, Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Geoff Levand, Palmer Dabbelt, Heiko Carstens,
John Paul Adrian Glaubitz, David S. Miller, Andy Lutomirski,
Thomas Gleixner, Ingo Molnar, x86, Helge Deller, Sudip Mukherjee,
Greg Kroah-Hartman, Timur Tabi, Kent Overstreet, David Woodhouse,
Naveen N. Rao, Anil S Keshavamurthy, Kees Cook, Vincenzo Frascino,
Juri Lelli, Vincent Guittot, Nathan Chancellor, Nick Desaulniers,
Nicolas Schier, Al Viro, Uwe Kleine-König, linux-alpha,
linux-snps-arc, linux-arm-kernel, linux-trace-kernel, linux-csky,
loongarch, linux-m68k, linux-mips, linuxppc-dev, linux-riscv,
linux-s390, linux-sh, sparclinux, netdev, linux-parisc, linux-usb,
linux-fbdev, dri-devel, linux-bcachefs, linux-mtd
In-Reply-To: <20231108125843.3806765-1-arnd@kernel.org>
From: Arnd Bergmann <arnd@arndb.de>
There is no global declaration for ida_dump() and no other
callers, so make it static to avoid this warning:
lib/test_ida.c:16:6: error: no previous prototype for 'ida_dump'
Fixes: 8ab8ba38d488 ("ida: Start new test_ida module")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
lib/test_ida.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/test_ida.c b/lib/test_ida.c
index b06880625961..f946c80ced8b 100644
--- a/lib/test_ida.c
+++ b/lib/test_ida.c
@@ -13,7 +13,7 @@ static unsigned int tests_run;
static unsigned int tests_passed;
#ifdef __KERNEL__
-void ida_dump(struct ida *ida) { }
+static void ida_dump(struct ida *ida) { }
#endif
#define IDA_BUG_ON(ida, x) do { \
tests_run++; \
--
2.39.2
^ permalink raw reply related
* [PATCH 02/22] [RESEND^2] jffs2: mark __jffs2_dbg_superblock_counts() static
From: Arnd Bergmann @ 2023-11-08 12:58 UTC (permalink / raw)
To: Andrew Morton, linux-kernel, Masahiro Yamada, linux-kbuild
Cc: Arnd Bergmann, Matt Turner, Vineet Gupta, Russell King,
Catalin Marinas, Will Deacon, Steven Rostedt, Masami Hiramatsu,
Mark Rutland, Guo Ren, Peter Zijlstra, Ard Biesheuvel,
Huacai Chen, Greg Ungerer, Michal Simek, Thomas Bogendoerfer,
Dinh Nguyen, Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Geoff Levand, Palmer Dabbelt, Heiko Carstens,
John Paul Adrian Glaubitz, David S. Miller, Andy Lutomirski,
Thomas Gleixner, Ingo Molnar, x86, Helge Deller, Sudip Mukherjee,
Greg Kroah-Hartman, Timur Tabi, Kent Overstreet, David Woodhouse,
Naveen N. Rao, Anil S Keshavamurthy, Kees Cook, Vincenzo Frascino,
Juri Lelli, Vincent Guittot, Nathan Chancellor, Nick Desaulniers,
Nicolas Schier, Al Viro, Uwe Kleine-König, linux-alpha,
linux-snps-arc, linux-arm-kernel, linux-trace-kernel, linux-csky,
loongarch, linux-m68k, linux-mips, linuxppc-dev, linux-riscv,
linux-s390, linux-sh, sparclinux, netdev, linux-parisc, linux-usb,
linux-fbdev, dri-devel, linux-bcachefs, linux-mtd, Tudor Ambarus
In-Reply-To: <20231108125843.3806765-1-arnd@kernel.org>
From: Arnd Bergmann <arnd@arndb.de>
This function is only called locally and does not need to be
global. Since there is no external prototype, gcc warns about
the non-static definition:
fs/jffs2/debug.c:160:6: error: no previous prototype for '__jffs2_dbg_superblock_counts' [-Werror=missing-prototypes]
Reviewed-by: Tudor Ambarus <tudor.ambarus@linaro.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
fs/jffs2/debug.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c
index 9d26b1b9fc01..0925caab23c4 100644
--- a/fs/jffs2/debug.c
+++ b/fs/jffs2/debug.c
@@ -157,7 +157,7 @@ __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c,
kfree(buf);
}
-void __jffs2_dbg_superblock_counts(struct jffs2_sb_info *c)
+static void __jffs2_dbg_superblock_counts(struct jffs2_sb_info *c)
{
struct jffs2_eraseblock *jeb;
uint32_t free = 0, dirty = 0, used = 0, wasted = 0,
--
2.39.2
^ permalink raw reply related
* [PATCH 03/22] [RESEND] kprobes: unify kprobes_exceptions_nofify() prototypes
From: Arnd Bergmann @ 2023-11-08 12:58 UTC (permalink / raw)
To: Andrew Morton, linux-kernel, Masahiro Yamada, linux-kbuild
Cc: Arnd Bergmann, Matt Turner, Vineet Gupta, Russell King,
Catalin Marinas, Will Deacon, Steven Rostedt, Masami Hiramatsu,
Mark Rutland, Guo Ren, Peter Zijlstra, Ard Biesheuvel,
Huacai Chen, Greg Ungerer, Michal Simek, Thomas Bogendoerfer,
Dinh Nguyen, Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Geoff Levand, Palmer Dabbelt, Heiko Carstens,
John Paul Adrian Glaubitz, David S. Miller, Andy Lutomirski,
Thomas Gleixner, Ingo Molnar, x86, Helge Deller, Sudip Mukherjee,
Greg Kroah-Hartman, Timur Tabi, Kent Overstreet, David Woodhouse,
Naveen N. Rao, Anil S Keshavamurthy, Kees Cook, Vincenzo Frascino,
Juri Lelli, Vincent Guittot, Nathan Chancellor, Nick Desaulniers,
Nicolas Schier, Al Viro, Uwe Kleine-König, linux-alpha,
linux-snps-arc, linux-arm-kernel, linux-trace-kernel, linux-csky,
loongarch, linux-m68k, linux-mips, linuxppc-dev, linux-riscv,
linux-s390, linux-sh, sparclinux, netdev, linux-parisc, linux-usb,
linux-fbdev, dri-devel, linux-bcachefs, linux-mtd
In-Reply-To: <20231108125843.3806765-1-arnd@kernel.org>
From: Arnd Bergmann <arnd@arndb.de>
Most architectures that support kprobes declare this function in their
own asm/kprobes.h header and provide an override, but some are missing
the prototype, which causes a warning for the __weak stub implementation:
kernel/kprobes.c:1865:12: error: no previous prototype for 'kprobe_exceptions_notify' [-Werror=missing-prototypes]
1865 | int __weak kprobe_exceptions_notify(struct notifier_block *self,
Move the prototype into linux/kprobes.h so it is visible to all
the definitions.
Acked-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/arc/include/asm/kprobes.h | 3 ---
arch/arm/include/asm/kprobes.h | 2 --
arch/arm64/include/asm/kprobes.h | 2 --
arch/mips/include/asm/kprobes.h | 2 --
arch/powerpc/include/asm/kprobes.h | 2 --
arch/s390/include/asm/kprobes.h | 2 --
arch/sh/include/asm/kprobes.h | 2 --
arch/sparc/include/asm/kprobes.h | 2 --
arch/x86/include/asm/kprobes.h | 2 --
include/linux/kprobes.h | 4 ++++
10 files changed, 4 insertions(+), 19 deletions(-)
diff --git a/arch/arc/include/asm/kprobes.h b/arch/arc/include/asm/kprobes.h
index de1566e32cb8..68e8301c0df2 100644
--- a/arch/arc/include/asm/kprobes.h
+++ b/arch/arc/include/asm/kprobes.h
@@ -32,9 +32,6 @@ struct kprobe;
void arch_remove_kprobe(struct kprobe *p);
-int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
-
struct prev_kprobe {
struct kprobe *kp;
unsigned long status;
diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index e26a278d301a..5b8dbf1b0be4 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -40,8 +40,6 @@ struct kprobe_ctlblk {
void arch_remove_kprobe(struct kprobe *);
int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
-int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
/* optinsn template addresses */
extern __visible kprobe_opcode_t optprobe_template_entry[];
diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 05cd82eeca13..be7a3680dadf 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -37,8 +37,6 @@ struct kprobe_ctlblk {
void arch_remove_kprobe(struct kprobe *);
int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
-int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
void __kretprobe_trampoline(void);
void __kprobes *trampoline_probe_handler(struct pt_regs *regs);
diff --git a/arch/mips/include/asm/kprobes.h b/arch/mips/include/asm/kprobes.h
index 68b1e5d458cf..bc27d99c9436 100644
--- a/arch/mips/include/asm/kprobes.h
+++ b/arch/mips/include/asm/kprobes.h
@@ -71,8 +71,6 @@ struct kprobe_ctlblk {
struct prev_kprobe prev_kprobe;
};
-extern int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
#endif /* CONFIG_KPROBES */
#endif /* _ASM_KPROBES_H */
diff --git a/arch/powerpc/include/asm/kprobes.h b/arch/powerpc/include/asm/kprobes.h
index c8e4b4fd4e33..4525a9c68260 100644
--- a/arch/powerpc/include/asm/kprobes.h
+++ b/arch/powerpc/include/asm/kprobes.h
@@ -84,8 +84,6 @@ struct arch_optimized_insn {
kprobe_opcode_t *insn;
};
-extern int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
extern int kprobe_handler(struct pt_regs *regs);
extern int kprobe_post_handler(struct pt_regs *regs);
diff --git a/arch/s390/include/asm/kprobes.h b/arch/s390/include/asm/kprobes.h
index 21b9e5290c04..01f1682a73b7 100644
--- a/arch/s390/include/asm/kprobes.h
+++ b/arch/s390/include/asm/kprobes.h
@@ -73,8 +73,6 @@ struct kprobe_ctlblk {
void arch_remove_kprobe(struct kprobe *p);
int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
-int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
#define flush_insn_slot(p) do { } while (0)
diff --git a/arch/sh/include/asm/kprobes.h b/arch/sh/include/asm/kprobes.h
index eeba83e0a7d2..65d4c3316a5b 100644
--- a/arch/sh/include/asm/kprobes.h
+++ b/arch/sh/include/asm/kprobes.h
@@ -46,8 +46,6 @@ struct kprobe_ctlblk {
};
extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
-extern int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
extern int kprobe_handle_illslot(unsigned long pc);
#else
diff --git a/arch/sparc/include/asm/kprobes.h b/arch/sparc/include/asm/kprobes.h
index 06c2bc767ef7..aec742cd898f 100644
--- a/arch/sparc/include/asm/kprobes.h
+++ b/arch/sparc/include/asm/kprobes.h
@@ -47,8 +47,6 @@ struct kprobe_ctlblk {
struct prev_kprobe prev_kprobe;
};
-int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
asmlinkage void __kprobes kprobe_trap(unsigned long trap_level,
struct pt_regs *regs);
diff --git a/arch/x86/include/asm/kprobes.h b/arch/x86/include/asm/kprobes.h
index a2e9317aad49..5939694dfb28 100644
--- a/arch/x86/include/asm/kprobes.h
+++ b/arch/x86/include/asm/kprobes.h
@@ -113,8 +113,6 @@ struct kprobe_ctlblk {
};
extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
-extern int kprobe_exceptions_notify(struct notifier_block *self,
- unsigned long val, void *data);
extern int kprobe_int3_handler(struct pt_regs *regs);
#else
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index 365eb092e9c4..ab1da3142b06 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -445,6 +445,10 @@ int kprobe_get_kallsym(unsigned int symnum, unsigned long *value, char *type,
int arch_kprobe_get_kallsym(unsigned int *symnum, unsigned long *value,
char *type, char *sym);
+
+int kprobe_exceptions_notify(struct notifier_block *self,
+ unsigned long val, void *data);
+
#else /* !CONFIG_KPROBES: */
static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
--
2.39.2
^ permalink raw reply related
* [PATCH 04/22] [RESEND] time: make sysfs_get_uname() function visible in header
From: Arnd Bergmann @ 2023-11-08 12:58 UTC (permalink / raw)
To: Andrew Morton, linux-kernel, Masahiro Yamada, linux-kbuild
Cc: Arnd Bergmann, Matt Turner, Vineet Gupta, Russell King,
Catalin Marinas, Will Deacon, Steven Rostedt, Masami Hiramatsu,
Mark Rutland, Guo Ren, Peter Zijlstra, Ard Biesheuvel,
Huacai Chen, Greg Ungerer, Michal Simek, Thomas Bogendoerfer,
Dinh Nguyen, Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Geoff Levand, Palmer Dabbelt, Heiko Carstens,
John Paul Adrian Glaubitz, David S. Miller, Andy Lutomirski,
Thomas Gleixner, Ingo Molnar, x86, Helge Deller, Sudip Mukherjee,
Greg Kroah-Hartman, Timur Tabi, Kent Overstreet, David Woodhouse,
Naveen N. Rao, Anil S Keshavamurthy, Kees Cook, Vincenzo Frascino,
Juri Lelli, Vincent Guittot, Nathan Chancellor, Nick Desaulniers,
Nicolas Schier, Al Viro, Uwe Kleine-König, linux-alpha,
linux-snps-arc, linux-arm-kernel, linux-trace-kernel, linux-csky,
loongarch, linux-m68k, linux-mips, linuxppc-dev, linux-riscv,
linux-s390, linux-sh, sparclinux, netdev, linux-parisc, linux-usb,
linux-fbdev, dri-devel, linux-bcachefs, linux-mtd
In-Reply-To: <20231108125843.3806765-1-arnd@kernel.org>
From: Arnd Bergmann <arnd@arndb.de>
This function is defined globally in clocksource.c and used conditionally
in clockevent.c, which the declaration hidden when clockevent support
is disabled. This causes a harmless warning in the definition:
kernel/time/clocksource.c:1324:9: warning: no previous prototype for 'sysfs_get_uname' [-Wmissing-prototypes]
1324 | ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt)
Move the declaration out of the #ifdef so it is always visible.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
kernel/time/tick-internal.h | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h
index 649f2b48e8f0..481b7ab65e2c 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -56,7 +56,6 @@ extern int clockevents_program_event(struct clock_event_device *dev,
ktime_t expires, bool force);
extern void clockevents_handle_noop(struct clock_event_device *dev);
extern int __clockevents_update_freq(struct clock_event_device *dev, u32 freq);
-extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
/* Broadcasting support */
# ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
@@ -197,3 +196,5 @@ void hrtimers_resume_local(void);
#else
#define JIFFIES_SHIFT 8
#endif
+
+extern ssize_t sysfs_get_uname(const char *buf, char *dst, size_t cnt);
--
2.39.2
^ permalink raw reply related
* [PATCH 05/22] [RESEND] parport: gsc: mark init function static
From: Arnd Bergmann @ 2023-11-08 12:58 UTC (permalink / raw)
To: Andrew Morton, linux-kernel, Masahiro Yamada, linux-kbuild
Cc: Arnd Bergmann, Matt Turner, Vineet Gupta, Russell King,
Catalin Marinas, Will Deacon, Steven Rostedt, Masami Hiramatsu,
Mark Rutland, Guo Ren, Peter Zijlstra, Ard Biesheuvel,
Huacai Chen, Greg Ungerer, Michal Simek, Thomas Bogendoerfer,
Dinh Nguyen, Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Geoff Levand, Palmer Dabbelt, Heiko Carstens,
John Paul Adrian Glaubitz, David S. Miller, Andy Lutomirski,
Thomas Gleixner, Ingo Molnar, x86, Helge Deller, Sudip Mukherjee,
Greg Kroah-Hartman, Timur Tabi, Kent Overstreet, David Woodhouse,
Naveen N. Rao, Anil S Keshavamurthy, Kees Cook, Vincenzo Frascino,
Juri Lelli, Vincent Guittot, Nathan Chancellor, Nick Desaulniers,
Nicolas Schier, Al Viro, Uwe Kleine-König, linux-alpha,
linux-snps-arc, linux-arm-kernel, linux-trace-kernel, linux-csky,
loongarch, linux-m68k, linux-mips, linuxppc-dev, linux-riscv,
linux-s390, linux-sh, sparclinux, netdev, linux-parisc, linux-usb,
linux-fbdev, dri-devel, linux-bcachefs, linux-mtd
In-Reply-To: <20231108125843.3806765-1-arnd@kernel.org>
From: Arnd Bergmann <arnd@arndb.de>
This is only used locally, so mark it static to avoid a warning:
drivers/parport/parport_gsc.c:395:5: error: no previous prototype for 'parport_gsc_init' [-Werror=missing-prototypes]
Acked-by: Helge Deller <deller@gmx.de>
Acked-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/parport/parport_gsc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c
index 5e4475254bd0..c7e18382dc01 100644
--- a/drivers/parport/parport_gsc.c
+++ b/drivers/parport/parport_gsc.c
@@ -392,7 +392,7 @@ static struct parisc_driver parport_driver __refdata = {
.remove = __exit_p(parport_remove_chip),
};
-int parport_gsc_init(void)
+static int parport_gsc_init(void)
{
return register_parisc_driver(&parport_driver);
}
--
2.39.2
^ permalink raw reply related
* [PATCH 06/22] [RESEND] stackleak: add declarations for global functions
From: Arnd Bergmann @ 2023-11-08 12:58 UTC (permalink / raw)
To: Andrew Morton, linux-kernel, Masahiro Yamada, linux-kbuild
Cc: Arnd Bergmann, Matt Turner, Vineet Gupta, Russell King,
Catalin Marinas, Will Deacon, Steven Rostedt, Masami Hiramatsu,
Mark Rutland, Guo Ren, Peter Zijlstra, Ard Biesheuvel,
Huacai Chen, Greg Ungerer, Michal Simek, Thomas Bogendoerfer,
Dinh Nguyen, Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Geoff Levand, Palmer Dabbelt, Heiko Carstens,
John Paul Adrian Glaubitz, David S. Miller, Andy Lutomirski,
Thomas Gleixner, Ingo Molnar, x86, Helge Deller, Sudip Mukherjee,
Greg Kroah-Hartman, Timur Tabi, Kent Overstreet, David Woodhouse,
Naveen N. Rao, Anil S Keshavamurthy, Kees Cook, Vincenzo Frascino,
Juri Lelli, Vincent Guittot, Nathan Chancellor, Nick Desaulniers,
Nicolas Schier, Al Viro, Uwe Kleine-König, linux-alpha,
linux-snps-arc, linux-arm-kernel, linux-trace-kernel, linux-csky,
loongarch, linux-m68k, linux-mips, linuxppc-dev, linux-riscv,
linux-s390, linux-sh, sparclinux, netdev, linux-parisc, linux-usb,
linux-fbdev, dri-devel, linux-bcachefs, linux-mtd
In-Reply-To: <20231108125843.3806765-1-arnd@kernel.org>
From: Arnd Bergmann <arnd@arndb.de>
With -Wmissing-prototypes enabled, the stackleak code produces a couple of
warnings that have no declarations because they are only called from assembler:
stackleak.c:127:25: error: no previous prototype for 'stackleak_erase' [-Werror=missing-prototypes]
stackleak.c:139:25: error: no previous prototype for 'stackleak_erase_on_task_stack' [-Werror=missing-prototypes]
stackleak.c:151:25: error: no previous prototype for 'stackleak_erase_off_task_stack' [-Werror=missing-prototypes]
stackleak.c:159:49: error: no previous prototype for 'stackleak_track_stack' [-Werror=missing-prototypes]
Add declarations to the stackleak header to shut up the warnings.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
include/linux/stackleak.h | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/include/linux/stackleak.h b/include/linux/stackleak.h
index c36e7a3b45e7..3be2cb564710 100644
--- a/include/linux/stackleak.h
+++ b/include/linux/stackleak.h
@@ -14,6 +14,7 @@
#ifdef CONFIG_GCC_PLUGIN_STACKLEAK
#include <asm/stacktrace.h>
+#include <linux/linkage.h>
/*
* The lowest address on tsk's stack which we can plausibly erase.
@@ -76,6 +77,11 @@ static inline void stackleak_task_init(struct task_struct *t)
# endif
}
+asmlinkage void noinstr stackleak_erase(void);
+asmlinkage void noinstr stackleak_erase_on_task_stack(void);
+asmlinkage void noinstr stackleak_erase_off_task_stack(void);
+void __no_caller_saved_registers noinstr stackleak_track_stack(void);
+
#else /* !CONFIG_GCC_PLUGIN_STACKLEAK */
static inline void stackleak_task_init(struct task_struct *t) { }
#endif
--
2.39.2
^ permalink raw reply related
* [PATCH 07/22] [RESEND] sched: fair: move unused stub functions to header
From: Arnd Bergmann @ 2023-11-08 12:58 UTC (permalink / raw)
To: Andrew Morton, linux-kernel, Masahiro Yamada, linux-kbuild
Cc: Arnd Bergmann, Matt Turner, Vineet Gupta, Russell King,
Catalin Marinas, Will Deacon, Steven Rostedt, Masami Hiramatsu,
Mark Rutland, Guo Ren, Peter Zijlstra, Ard Biesheuvel,
Huacai Chen, Greg Ungerer, Michal Simek, Thomas Bogendoerfer,
Dinh Nguyen, Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Geoff Levand, Palmer Dabbelt, Heiko Carstens,
John Paul Adrian Glaubitz, David S. Miller, Andy Lutomirski,
Thomas Gleixner, Ingo Molnar, x86, Helge Deller, Sudip Mukherjee,
Greg Kroah-Hartman, Timur Tabi, Kent Overstreet, David Woodhouse,
Naveen N. Rao, Anil S Keshavamurthy, Kees Cook, Vincenzo Frascino,
Juri Lelli, Vincent Guittot, Nathan Chancellor, Nick Desaulniers,
Nicolas Schier, Al Viro, Uwe Kleine-König, linux-alpha,
linux-snps-arc, linux-arm-kernel, linux-trace-kernel, linux-csky,
loongarch, linux-m68k, linux-mips, linuxppc-dev, linux-riscv,
linux-s390, linux-sh, sparclinux, netdev, linux-parisc, linux-usb,
linux-fbdev, dri-devel, linux-bcachefs, linux-mtd
In-Reply-To: <20231108125843.3806765-1-arnd@kernel.org>
From: Arnd Bergmann <arnd@arndb.de>
These four functions have a normal definition for CONFIG_FAIR_GROUP_SCHED,
and empty one that is only referenced when FAIR_GROUP_SCHED is disabled
but CGROUP_SCHED is still enabled. If both are turned off, the functions
are still defined but the misisng prototype causes a W=1 warning:
kernel/sched/fair.c:12544:6: error: no previous prototype for 'free_fair_sched_group'
kernel/sched/fair.c:12546:5: error: no previous prototype for 'alloc_fair_sched_group'
kernel/sched/fair.c:12553:6: error: no previous prototype for 'online_fair_sched_group'
kernel/sched/fair.c:12555:6: error: no previous prototype for 'unregister_fair_sched_group'
Move the alternatives into the header as static inline functions with
the correct combination of #ifdef checks to avoid the warning without
adding even more complexity.
[A different patch with the same description got applied by accident
and was later reverted, but the original patch is still missing]
Fixes: 7aa55f2a5902 ("sched/fair: Move unused stub functions to header")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
A patch with the same commit log has
---
kernel/sched/fair.c | 13 -------------
kernel/sched/sched.h | 11 +++++++++++
2 files changed, 11 insertions(+), 13 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 2048138ce54b..82b82fa1d81b 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -12927,19 +12927,6 @@ int sched_group_set_idle(struct task_group *tg, long idle)
return 0;
}
-#else /* CONFIG_FAIR_GROUP_SCHED */
-
-void free_fair_sched_group(struct task_group *tg) { }
-
-int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
-{
- return 1;
-}
-
-void online_fair_sched_group(struct task_group *tg) { }
-
-void unregister_fair_sched_group(struct task_group *tg) { }
-
#endif /* CONFIG_FAIR_GROUP_SCHED */
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 2e5a95486a42..8f5df5250b8d 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -436,10 +436,21 @@ static inline int walk_tg_tree(tg_visitor down, tg_visitor up, void *data)
extern int tg_nop(struct task_group *tg, void *data);
+#ifdef CONFIG_FAIR_GROUP_SCHED
extern void free_fair_sched_group(struct task_group *tg);
extern int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent);
extern void online_fair_sched_group(struct task_group *tg);
extern void unregister_fair_sched_group(struct task_group *tg);
+#else
+static inline void free_fair_sched_group(struct task_group *tg) { }
+static inline int alloc_fair_sched_group(struct task_group *tg, struct task_group *parent)
+{
+ return 1;
+}
+static inline void online_fair_sched_group(struct task_group *tg) { }
+static inline void unregister_fair_sched_group(struct task_group *tg) { }
+#endif
+
extern void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq,
struct sched_entity *se, int cpu,
struct sched_entity *parent);
--
2.39.2
^ permalink raw reply related
* [PATCH 08/22] [v2] arch: consolidate arch_irq_work_raise prototypes
From: Arnd Bergmann @ 2023-11-08 12:58 UTC (permalink / raw)
To: Andrew Morton, linux-kernel, Masahiro Yamada, linux-kbuild
Cc: Arnd Bergmann, Matt Turner, Vineet Gupta, Russell King,
Catalin Marinas, Will Deacon, Steven Rostedt, Masami Hiramatsu,
Mark Rutland, Guo Ren, Peter Zijlstra, Ard Biesheuvel,
Huacai Chen, Greg Ungerer, Michal Simek, Thomas Bogendoerfer,
Dinh Nguyen, Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Geoff Levand, Palmer Dabbelt, Heiko Carstens,
John Paul Adrian Glaubitz, David S. Miller, Andy Lutomirski,
Thomas Gleixner, Ingo Molnar, x86, Helge Deller, Sudip Mukherjee,
Greg Kroah-Hartman, Timur Tabi, Kent Overstreet, David Woodhouse,
Naveen N. Rao, Anil S Keshavamurthy, Kees Cook, Vincenzo Frascino,
Juri Lelli, Vincent Guittot, Nathan Chancellor, Nick Desaulniers,
Nicolas Schier, Al Viro, Uwe Kleine-König, linux-alpha,
linux-snps-arc, linux-arm-kernel, linux-trace-kernel, linux-csky,
loongarch, linux-m68k, linux-mips, linuxppc-dev, linux-riscv,
linux-s390, linux-sh, sparclinux, netdev, linux-parisc, linux-usb,
linux-fbdev, dri-devel, linux-bcachefs, linux-mtd, Palmer Dabbelt,
Alexander Gordeev
In-Reply-To: <20231108125843.3806765-1-arnd@kernel.org>
From: Arnd Bergmann <arnd@arndb.de>
The prototype was hidden in an #ifdef on x86, which causes a warning:
kernel/irq_work.c:72:13: error: no previous prototype for 'arch_irq_work_raise' [-Werror=missing-prototypes]
Some architectures have a working prototype, while others don't.
Fix this by providing it in only one place that is always visible.
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Acked-by: Palmer Dabbelt <palmer@rivosinc.com>
Acked-by: Guo Ren <guoren@kernel.org>
Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
v2: clarify changelog text
---
arch/arm/include/asm/irq_work.h | 2 --
arch/arm64/include/asm/irq_work.h | 2 --
arch/csky/include/asm/irq_work.h | 2 +-
arch/powerpc/include/asm/irq_work.h | 1 -
arch/riscv/include/asm/irq_work.h | 2 +-
arch/s390/include/asm/irq_work.h | 2 --
arch/x86/include/asm/irq_work.h | 1 -
include/linux/irq_work.h | 3 +++
8 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/arch/arm/include/asm/irq_work.h b/arch/arm/include/asm/irq_work.h
index 3149e4dc1b54..8895999834cc 100644
--- a/arch/arm/include/asm/irq_work.h
+++ b/arch/arm/include/asm/irq_work.h
@@ -9,6 +9,4 @@ static inline bool arch_irq_work_has_interrupt(void)
return is_smp();
}
-extern void arch_irq_work_raise(void);
-
#endif /* _ASM_ARM_IRQ_WORK_H */
diff --git a/arch/arm64/include/asm/irq_work.h b/arch/arm64/include/asm/irq_work.h
index 81bbfa3a035b..a1020285ea75 100644
--- a/arch/arm64/include/asm/irq_work.h
+++ b/arch/arm64/include/asm/irq_work.h
@@ -2,8 +2,6 @@
#ifndef __ASM_IRQ_WORK_H
#define __ASM_IRQ_WORK_H
-extern void arch_irq_work_raise(void);
-
static inline bool arch_irq_work_has_interrupt(void)
{
return true;
diff --git a/arch/csky/include/asm/irq_work.h b/arch/csky/include/asm/irq_work.h
index 33aaf39d6f94..d39fcc1f5395 100644
--- a/arch/csky/include/asm/irq_work.h
+++ b/arch/csky/include/asm/irq_work.h
@@ -7,5 +7,5 @@ static inline bool arch_irq_work_has_interrupt(void)
{
return true;
}
-extern void arch_irq_work_raise(void);
+
#endif /* __ASM_CSKY_IRQ_WORK_H */
diff --git a/arch/powerpc/include/asm/irq_work.h b/arch/powerpc/include/asm/irq_work.h
index b8b0be8f1a07..c6d3078bd8c3 100644
--- a/arch/powerpc/include/asm/irq_work.h
+++ b/arch/powerpc/include/asm/irq_work.h
@@ -6,6 +6,5 @@ static inline bool arch_irq_work_has_interrupt(void)
{
return true;
}
-extern void arch_irq_work_raise(void);
#endif /* _ASM_POWERPC_IRQ_WORK_H */
diff --git a/arch/riscv/include/asm/irq_work.h b/arch/riscv/include/asm/irq_work.h
index b53891964ae0..b27a4d64fc6a 100644
--- a/arch/riscv/include/asm/irq_work.h
+++ b/arch/riscv/include/asm/irq_work.h
@@ -6,5 +6,5 @@ static inline bool arch_irq_work_has_interrupt(void)
{
return IS_ENABLED(CONFIG_SMP);
}
-extern void arch_irq_work_raise(void);
+
#endif /* _ASM_RISCV_IRQ_WORK_H */
diff --git a/arch/s390/include/asm/irq_work.h b/arch/s390/include/asm/irq_work.h
index 603783766d0a..f00c9f610d5a 100644
--- a/arch/s390/include/asm/irq_work.h
+++ b/arch/s390/include/asm/irq_work.h
@@ -7,6 +7,4 @@ static inline bool arch_irq_work_has_interrupt(void)
return true;
}
-void arch_irq_work_raise(void);
-
#endif /* _ASM_S390_IRQ_WORK_H */
diff --git a/arch/x86/include/asm/irq_work.h b/arch/x86/include/asm/irq_work.h
index 800ffce0db29..6b4d36c95165 100644
--- a/arch/x86/include/asm/irq_work.h
+++ b/arch/x86/include/asm/irq_work.h
@@ -9,7 +9,6 @@ static inline bool arch_irq_work_has_interrupt(void)
{
return boot_cpu_has(X86_FEATURE_APIC);
}
-extern void arch_irq_work_raise(void);
#else
static inline bool arch_irq_work_has_interrupt(void)
{
diff --git a/include/linux/irq_work.h b/include/linux/irq_work.h
index 8cd11a223260..136f2980cba3 100644
--- a/include/linux/irq_work.h
+++ b/include/linux/irq_work.h
@@ -66,6 +66,9 @@ void irq_work_sync(struct irq_work *work);
void irq_work_run(void);
bool irq_work_needs_cpu(void);
void irq_work_single(void *arg);
+
+void arch_irq_work_raise(void);
+
#else
static inline bool irq_work_needs_cpu(void) { return false; }
static inline void irq_work_run(void) { }
--
2.39.2
^ permalink raw reply related
* [PATCH 09/22] [v2] arch: fix asm-offsets.c building with -Wmissing-prototypes
From: Arnd Bergmann @ 2023-11-08 12:58 UTC (permalink / raw)
To: Andrew Morton, linux-kernel, Masahiro Yamada, linux-kbuild
Cc: Arnd Bergmann, Matt Turner, Vineet Gupta, Russell King,
Catalin Marinas, Will Deacon, Steven Rostedt, Masami Hiramatsu,
Mark Rutland, Guo Ren, Peter Zijlstra, Ard Biesheuvel,
Huacai Chen, Greg Ungerer, Michal Simek, Thomas Bogendoerfer,
Dinh Nguyen, Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Geoff Levand, Palmer Dabbelt, Heiko Carstens,
John Paul Adrian Glaubitz, David S. Miller, Andy Lutomirski,
Thomas Gleixner, Ingo Molnar, x86, Helge Deller, Sudip Mukherjee,
Greg Kroah-Hartman, Timur Tabi, Kent Overstreet, David Woodhouse,
Naveen N. Rao, Anil S Keshavamurthy, Kees Cook, Vincenzo Frascino,
Juri Lelli, Vincent Guittot, Nathan Chancellor, Nick Desaulniers,
Nicolas Schier, Al Viro, Uwe Kleine-König, linux-alpha,
linux-snps-arc, linux-arm-kernel, linux-trace-kernel, linux-csky,
loongarch, linux-m68k, linux-mips, linuxppc-dev, linux-riscv,
linux-s390, linux-sh, sparclinux, netdev, linux-parisc, linux-usb,
linux-fbdev, dri-devel, linux-bcachefs, linux-mtd
In-Reply-To: <20231108125843.3806765-1-arnd@kernel.org>
From: Arnd Bergmann <arnd@arndb.de>
When -Wmissing-prototypes is enabled, the some asm-offsets.c files fail
to build, even when this warning is disabled in the Makefile for normal
files:
arch/sparc/kernel/asm-offsets.c:22:5: error: no previous prototype for 'sparc32_foo' [-Werror=missing-prototypes]
arch/sparc/kernel/asm-offsets.c:48:5: error: no previous prototype for 'foo' [-Werror=missing-prototypes]
Address this by making use of the same trick as x86, marking these
functions as 'static __used' to avoid the need for a prototype
by not drop them in dead-code elimination.
Suggested-by: Masahiro Yamada <masahiroy@kernel.org>
Link: https://lore.kernel.org/lkml/CAK7LNARfEmFk0Du4Hed19eX_G6tUC5wG0zP+L1AyvdpOF4ybXQ@mail.gmail.com/
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
v2: rewrite using a different approach
---
arch/alpha/kernel/asm-offsets.c | 2 +-
arch/loongarch/kernel/asm-offsets.c | 26 +++++++++++++-------------
arch/sparc/kernel/asm-offsets.c | 6 +++---
3 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c
index b121294bee26..bf1eedd27cf7 100644
--- a/arch/alpha/kernel/asm-offsets.c
+++ b/arch/alpha/kernel/asm-offsets.c
@@ -12,7 +12,7 @@
#include <linux/kbuild.h>
#include <asm/io.h>
-void foo(void)
+static void __used foo(void)
{
DEFINE(TI_TASK, offsetof(struct thread_info, task));
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
diff --git a/arch/loongarch/kernel/asm-offsets.c b/arch/loongarch/kernel/asm-offsets.c
index 173fe514fc9e..bee9f7a3108f 100644
--- a/arch/loongarch/kernel/asm-offsets.c
+++ b/arch/loongarch/kernel/asm-offsets.c
@@ -15,7 +15,7 @@
#include <asm/processor.h>
#include <asm/ftrace.h>
-void output_ptreg_defines(void)
+static void __used output_ptreg_defines(void)
{
COMMENT("LoongArch pt_regs offsets.");
OFFSET(PT_R0, pt_regs, regs[0]);
@@ -62,7 +62,7 @@ void output_ptreg_defines(void)
BLANK();
}
-void output_task_defines(void)
+static void __used output_task_defines(void)
{
COMMENT("LoongArch task_struct offsets.");
OFFSET(TASK_STATE, task_struct, __state);
@@ -77,7 +77,7 @@ void output_task_defines(void)
BLANK();
}
-void output_thread_info_defines(void)
+static void __used output_thread_info_defines(void)
{
COMMENT("LoongArch thread_info offsets.");
OFFSET(TI_TASK, thread_info, task);
@@ -93,7 +93,7 @@ void output_thread_info_defines(void)
BLANK();
}
-void output_thread_defines(void)
+static void __used output_thread_defines(void)
{
COMMENT("LoongArch specific thread_struct offsets.");
OFFSET(THREAD_REG01, task_struct, thread.reg01);
@@ -129,7 +129,7 @@ void output_thread_defines(void)
BLANK();
}
-void output_thread_fpu_defines(void)
+static void __used output_thread_fpu_defines(void)
{
OFFSET(THREAD_FPR0, loongarch_fpu, fpr[0]);
OFFSET(THREAD_FPR1, loongarch_fpu, fpr[1]);
@@ -170,7 +170,7 @@ void output_thread_fpu_defines(void)
BLANK();
}
-void output_thread_lbt_defines(void)
+static void __used output_thread_lbt_defines(void)
{
OFFSET(THREAD_SCR0, loongarch_lbt, scr0);
OFFSET(THREAD_SCR1, loongarch_lbt, scr1);
@@ -180,7 +180,7 @@ void output_thread_lbt_defines(void)
BLANK();
}
-void output_mm_defines(void)
+static void __used output_mm_defines(void)
{
COMMENT("Size of struct page");
DEFINE(STRUCT_PAGE_SIZE, sizeof(struct page));
@@ -212,7 +212,7 @@ void output_mm_defines(void)
BLANK();
}
-void output_sc_defines(void)
+static void __used output_sc_defines(void)
{
COMMENT("Linux sigcontext offsets.");
OFFSET(SC_REGS, sigcontext, sc_regs);
@@ -220,7 +220,7 @@ void output_sc_defines(void)
BLANK();
}
-void output_signal_defines(void)
+static void __used output_signal_defines(void)
{
COMMENT("Linux signal numbers.");
DEFINE(_SIGHUP, SIGHUP);
@@ -258,7 +258,7 @@ void output_signal_defines(void)
}
#ifdef CONFIG_SMP
-void output_smpboot_defines(void)
+static void __used output_smpboot_defines(void)
{
COMMENT("Linux smp cpu boot offsets.");
OFFSET(CPU_BOOT_STACK, secondary_data, stack);
@@ -268,7 +268,7 @@ void output_smpboot_defines(void)
#endif
#ifdef CONFIG_HIBERNATION
-void output_pbe_defines(void)
+static void __used output_pbe_defines(void)
{
COMMENT("Linux struct pbe offsets.");
OFFSET(PBE_ADDRESS, pbe, address);
@@ -280,7 +280,7 @@ void output_pbe_defines(void)
#endif
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
-void output_fgraph_ret_regs_defines(void)
+static void __used output_fgraph_ret_regs_defines(void)
{
COMMENT("LoongArch fgraph_ret_regs offsets.");
OFFSET(FGRET_REGS_A0, fgraph_ret_regs, regs[0]);
@@ -291,7 +291,7 @@ void output_fgraph_ret_regs_defines(void)
}
#endif
-void output_kvm_defines(void)
+static void __used output_kvm_defines(void)
{
COMMENT("KVM/LoongArch Specific offsets.");
diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c
index 5784f2df489a..3d9b9855dce9 100644
--- a/arch/sparc/kernel/asm-offsets.c
+++ b/arch/sparc/kernel/asm-offsets.c
@@ -19,14 +19,14 @@
#include <asm/hibernate.h>
#ifdef CONFIG_SPARC32
-int sparc32_foo(void)
+static int __used sparc32_foo(void)
{
DEFINE(AOFF_thread_fork_kpsr,
offsetof(struct thread_struct, fork_kpsr));
return 0;
}
#else
-int sparc64_foo(void)
+static int __used sparc64_foo(void)
{
#ifdef CONFIG_HIBERNATION
BLANK();
@@ -45,7 +45,7 @@ int sparc64_foo(void)
}
#endif
-int foo(void)
+static int __used foo(void)
{
BLANK();
DEFINE(AOFF_task_thread, offsetof(struct task_struct, thread));
--
2.39.2
^ permalink raw reply related
* [PATCH 10/22] microblaze: include linux/cpu.h for trap_init() prototype
From: Arnd Bergmann @ 2023-11-08 12:58 UTC (permalink / raw)
To: Andrew Morton, linux-kernel, Masahiro Yamada, linux-kbuild
Cc: Arnd Bergmann, Matt Turner, Vineet Gupta, Russell King,
Catalin Marinas, Will Deacon, Steven Rostedt, Masami Hiramatsu,
Mark Rutland, Guo Ren, Peter Zijlstra, Ard Biesheuvel,
Huacai Chen, Greg Ungerer, Michal Simek, Thomas Bogendoerfer,
Dinh Nguyen, Michael Ellerman, Nicholas Piggin, Christophe Leroy,
Geoff Levand, Palmer Dabbelt, Heiko Carstens,
John Paul Adrian Glaubitz, David S. Miller, Andy Lutomirski,
Thomas Gleixner, Ingo Molnar, x86, Helge Deller, Sudip Mukherjee,
Greg Kroah-Hartman, Timur Tabi, Kent Overstreet, David Woodhouse,
Naveen N. Rao, Anil S Keshavamurthy, Kees Cook, Vincenzo Frascino,
Juri Lelli, Vincent Guittot, Nathan Chancellor, Nick Desaulniers,
Nicolas Schier, Al Viro, Uwe Kleine-König, linux-alpha,
linux-snps-arc, linux-arm-kernel, linux-trace-kernel, linux-csky,
loongarch, linux-m68k, linux-mips, linuxppc-dev, linux-riscv,
linux-s390, linux-sh, sparclinux, netdev, linux-parisc, linux-usb,
linux-fbdev, dri-devel, linux-bcachefs, linux-mtd
In-Reply-To: <20231108125843.3806765-1-arnd@kernel.org>
From: Arnd Bergmann <arnd@arndb.de>
Microblaze runs into a single -Wmissing-prototypes warning when that is
enabled:
arch/microblaze/kernel/traps.c:21:6: warning: no previous prototype for 'trap_init' [-Wmissing-prototypes]
Include the right header to avoid this.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/alpha/kernel/traps.c | 1 +
arch/csky/include/asm/traps.h | 2 --
arch/csky/kernel/traps.c | 1 +
arch/m68k/coldfire/vectors.c | 3 +--
arch/m68k/coldfire/vectors.h | 3 ---
arch/microblaze/kernel/traps.c | 1 +
arch/sparc/kernel/traps_32.c | 1 +
arch/sparc/kernel/traps_64.c | 1 +
arch/x86/include/asm/traps.h | 1 -
arch/x86/kernel/traps.c | 1 +
10 files changed, 7 insertions(+), 8 deletions(-)
delete mode 100644 arch/m68k/coldfire/vectors.h
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index d9a67b370e04..7fc72aeb7398 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -9,6 +9,7 @@
* This file initializes the trap entry points
*/
+#include <linux/cpu.h>
#include <linux/jiffies.h>
#include <linux/mm.h>
#include <linux/sched/signal.h>
diff --git a/arch/csky/include/asm/traps.h b/arch/csky/include/asm/traps.h
index 732c4aaa2e26..495ce318d569 100644
--- a/arch/csky/include/asm/traps.h
+++ b/arch/csky/include/asm/traps.h
@@ -55,6 +55,4 @@ asmlinkage void trap_c(struct pt_regs *regs);
asmlinkage void do_notify_resume(struct pt_regs *regs,
unsigned long thread_info_flags);
-void trap_init(void);
-
#endif /* __ASM_CSKY_TRAPS_H */
diff --git a/arch/csky/kernel/traps.c b/arch/csky/kernel/traps.c
index 6e426fba0119..c2246b07cc9c 100644
--- a/arch/csky/kernel/traps.c
+++ b/arch/csky/kernel/traps.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
+#include <linux/cpu.h>
#include <linux/sched.h>
#include <linux/signal.h>
#include <linux/kernel.h>
diff --git a/arch/m68k/coldfire/vectors.c b/arch/m68k/coldfire/vectors.c
index c26c255b530d..4321fd89d83e 100644
--- a/arch/m68k/coldfire/vectors.c
+++ b/arch/m68k/coldfire/vectors.c
@@ -12,14 +12,13 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/irq.h>
+#include <linux/cpu.h>
#include <asm/traps.h>
#include <asm/machdep.h>
#include <asm/coldfire.h>
#include <asm/mcfsim.h>
#include <asm/mcfwdebug.h>
-#include "vectors.h"
-
/***************************************************************************/
#ifdef TRAP_DBG_INTERRUPT
diff --git a/arch/m68k/coldfire/vectors.h b/arch/m68k/coldfire/vectors.h
deleted file mode 100644
index 0b01450a4353..000000000000
--- a/arch/m68k/coldfire/vectors.h
+++ /dev/null
@@ -1,3 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-void trap_init(void);
diff --git a/arch/microblaze/kernel/traps.c b/arch/microblaze/kernel/traps.c
index 94b6fe93147d..080aa769218d 100644
--- a/arch/microblaze/kernel/traps.c
+++ b/arch/microblaze/kernel/traps.c
@@ -8,6 +8,7 @@
* for more details.
*/
+#include <linux/cpu.h>
#include <linux/export.h>
#include <linux/kernel.h>
#include <linux/kallsyms.h>
diff --git a/arch/sparc/kernel/traps_32.c b/arch/sparc/kernel/traps_32.c
index 179aabfa712e..bb149f6cc34b 100644
--- a/arch/sparc/kernel/traps_32.c
+++ b/arch/sparc/kernel/traps_32.c
@@ -10,6 +10,7 @@
* I hate traps on the sparc, grrr...
*/
+#include <linux/cpu.h>
#include <linux/sched/mm.h>
#include <linux/sched/debug.h>
#include <linux/mm_types.h>
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index 08ffd17d5ec3..3631899f2394 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -9,6 +9,7 @@
* I like traps on v9, :))))
*/
+#include <linux/cpu.h>
#include <linux/extable.h>
#include <linux/sched/mm.h>
#include <linux/sched/debug.h>
diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
index b1c9cea6ba88..1f1deaecd364 100644
--- a/arch/x86/include/asm/traps.h
+++ b/arch/x86/include/asm/traps.h
@@ -14,7 +14,6 @@
asmlinkage __visible notrace struct pt_regs *sync_regs(struct pt_regs *eregs);
asmlinkage __visible notrace
struct pt_regs *fixup_bad_iret(struct pt_regs *bad_regs);
-void __init trap_init(void);
asmlinkage __visible noinstr struct pt_regs *vc_switch_off_ist(struct pt_regs *eregs);
#endif
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index c876f1d36a81..b0737a15c470 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -37,6 +37,7 @@
#include <linux/nmi.h>
#include <linux/mm.h>
#include <linux/smp.h>
+#include <linux/cpu.h>
#include <linux/io.h>
#include <linux/hardirq.h>
#include <linux/atomic.h>
--
2.39.2
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox