From 462a088c474832b19ff2730de1e6bea66d399c23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Ko=C4=8D=C3=AD?= Date: Sat, 15 Oct 2022 23:01:29 +0200 Subject: Add Turris kernel (includes patches from OpenWrt) --- ...ropagate-errors-when-updating-PCI_IO_BASE.patch | 195 +++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 pkgs/patches-linux-5.15/0011-PCI-mvebu-Propagate-errors-when-updating-PCI_IO_BASE.patch (limited to 'pkgs/patches-linux-5.15/0011-PCI-mvebu-Propagate-errors-when-updating-PCI_IO_BASE.patch') diff --git a/pkgs/patches-linux-5.15/0011-PCI-mvebu-Propagate-errors-when-updating-PCI_IO_BASE.patch b/pkgs/patches-linux-5.15/0011-PCI-mvebu-Propagate-errors-when-updating-PCI_IO_BASE.patch new file mode 100644 index 0000000..225965c --- /dev/null +++ b/pkgs/patches-linux-5.15/0011-PCI-mvebu-Propagate-errors-when-updating-PCI_IO_BASE.patch @@ -0,0 +1,195 @@ +From 14d8c749e493bd09b00e5766ba96631794e1a109 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pali=20Roh=C3=A1r?= +Date: Fri, 17 Sep 2021 11:34:50 +0200 +Subject: [PATCH 11/90] PCI: mvebu: Propagate errors when updating PCI_IO_BASE + and PCI_MEM_BASE registers +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Properly propagate failure from mvebu_pcie_add_windows() function back to +the caller mvebu_pci_bridge_emul_base_conf_write() and correctly updates +PCI_IO_BASE, PCI_MEM_BASE and PCI_IO_BASE_UPPER16 registers on error. +On error set base value higher than limit value which indicates that +address range is disabled. When IO is unsupported then let IO registers +zeroed as required by PCIe base specification. + +Signed-off-by: Pali Rohár +Cc: stable@vger.kernel.org +--- + drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++++++---------- + 1 file changed, 55 insertions(+), 27 deletions(-) + +diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c +index 0a8b552364aa..32aa78059e96 100644 +--- a/drivers/pci/controller/pci-mvebu.c ++++ b/drivers/pci/controller/pci-mvebu.c +@@ -329,7 +329,7 @@ static void mvebu_pcie_del_windows(struct mvebu_pcie_port *port, + * areas each having a power of two size. We start from the largest + * one (i.e highest order bit set in the size). + */ +-static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port, ++static int mvebu_pcie_add_windows(struct mvebu_pcie_port *port, + unsigned int target, unsigned int attribute, + phys_addr_t base, size_t size, + phys_addr_t remap) +@@ -350,7 +350,7 @@ static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port, + &base, &end, ret); + mvebu_pcie_del_windows(port, base - size_mapped, + size_mapped); +- return; ++ return ret; + } + + size -= sz; +@@ -359,16 +359,20 @@ static void mvebu_pcie_add_windows(struct mvebu_pcie_port *port, + if (remap != MVEBU_MBUS_NO_REMAP) + remap += sz; + } ++ ++ return 0; + } + +-static void mvebu_pcie_set_window(struct mvebu_pcie_port *port, ++static int mvebu_pcie_set_window(struct mvebu_pcie_port *port, + unsigned int target, unsigned int attribute, + const struct mvebu_pcie_window *desired, + struct mvebu_pcie_window *cur) + { ++ int ret; ++ + if (desired->base == cur->base && desired->remap == cur->remap && + desired->size == cur->size) +- return; ++ return 0; + + if (cur->size != 0) { + mvebu_pcie_del_windows(port, cur->base, cur->size); +@@ -383,30 +387,35 @@ static void mvebu_pcie_set_window(struct mvebu_pcie_port *port, + } + + if (desired->size == 0) +- return; ++ return 0; ++ ++ ret = mvebu_pcie_add_windows(port, target, attribute, desired->base, ++ desired->size, desired->remap); ++ if (ret) { ++ cur->size = 0; ++ cur->base = 0; ++ return ret; ++ } + +- mvebu_pcie_add_windows(port, target, attribute, desired->base, +- desired->size, desired->remap); + *cur = *desired; ++ return 0; + } + +-static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) ++static int mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) + { + struct mvebu_pcie_window desired = {}; + struct pci_bridge_emul_conf *conf = &port->bridge.conf; + + /* Are the new iobase/iolimit values invalid? */ + if (conf->iolimit < conf->iobase || +- conf->iolimitupper < conf->iobaseupper) { +- mvebu_pcie_set_window(port, port->io_target, port->io_attr, +- &desired, &port->iowin); +- return; +- } ++ conf->iolimitupper < conf->iobaseupper) ++ return mvebu_pcie_set_window(port, port->io_target, port->io_attr, ++ &desired, &port->iowin); + + if (!mvebu_has_ioport(port)) { + dev_WARN(&port->pcie->pdev->dev, + "Attempt to set IO when IO is disabled\n"); +- return; ++ return -EOPNOTSUPP; + } + + /* +@@ -424,21 +433,19 @@ static void mvebu_pcie_handle_iobase_change(struct mvebu_pcie_port *port) + desired.remap) + + 1; + +- mvebu_pcie_set_window(port, port->io_target, port->io_attr, &desired, +- &port->iowin); ++ return mvebu_pcie_set_window(port, port->io_target, port->io_attr, &desired, ++ &port->iowin); + } + +-static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) ++static int mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) + { + struct mvebu_pcie_window desired = {.remap = MVEBU_MBUS_NO_REMAP}; + struct pci_bridge_emul_conf *conf = &port->bridge.conf; + + /* Are the new membase/memlimit values invalid? */ +- if (conf->memlimit < conf->membase) { +- mvebu_pcie_set_window(port, port->mem_target, port->mem_attr, +- &desired, &port->memwin); +- return; +- } ++ if (conf->memlimit < conf->membase) ++ return mvebu_pcie_set_window(port, port->mem_target, port->mem_attr, ++ &desired, &port->memwin); + + /* + * We read the PCI-to-PCI bridge emulated registers, and +@@ -450,8 +457,8 @@ static void mvebu_pcie_handle_membase_change(struct mvebu_pcie_port *port) + desired.size = (((conf->memlimit & 0xFFF0) << 16) | 0xFFFFF) - + desired.base + 1; + +- mvebu_pcie_set_window(port, port->mem_target, port->mem_attr, &desired, +- &port->memwin); ++ return mvebu_pcie_set_window(port, port->mem_target, port->mem_attr, &desired, ++ &port->memwin); + } + + static pci_bridge_emul_read_status_t +@@ -576,15 +583,36 @@ mvebu_pci_bridge_emul_base_conf_write(struct pci_bridge_emul *bridge, + break; + + case PCI_IO_BASE: +- mvebu_pcie_handle_iobase_change(port); ++ if ((mask & 0xffff) && mvebu_pcie_handle_iobase_change(port)) { ++ /* On error disable IO range */ ++ conf->iobase &= ~0xf0; ++ conf->iolimit &= ~0xf0; ++ conf->iobaseupper = cpu_to_le16(0x0000); ++ conf->iolimitupper = cpu_to_le16(0x0000); ++ if (mvebu_has_ioport(port)) ++ conf->iobase |= 0xf0; ++ } + break; + + case PCI_MEMORY_BASE: +- mvebu_pcie_handle_membase_change(port); ++ if (mvebu_pcie_handle_membase_change(port)) { ++ /* On error disable mem range */ ++ conf->membase = cpu_to_le16(le16_to_cpu(conf->membase) & ~0xfff0); ++ conf->memlimit = cpu_to_le16(le16_to_cpu(conf->memlimit) & ~0xfff0); ++ conf->membase = cpu_to_le16(le16_to_cpu(conf->membase) | 0xfff0); ++ } + break; + + case PCI_IO_BASE_UPPER16: +- mvebu_pcie_handle_iobase_change(port); ++ if (mvebu_pcie_handle_iobase_change(port)) { ++ /* On error disable IO range */ ++ conf->iobase &= ~0xf0; ++ conf->iolimit &= ~0xf0; ++ conf->iobaseupper = cpu_to_le16(0x0000); ++ conf->iolimitupper = cpu_to_le16(0x0000); ++ if (mvebu_has_ioport(port)) ++ conf->iobase |= 0xf0; ++ } + break; + + case PCI_PRIMARY_BUS: +-- +2.34.1 + -- cgit v1.2.3