Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] irqchip/mbigen: Fix the clear register offset
From: Majun @ 2017-04-25  2:16 UTC (permalink / raw)
  To: linux-arm-kernel

From: MaJun <majun258@huawei.com>

Don't minus reserved interrupts (64) when get the clear register offset,because
the clear register space includes the space of these 64 interrupts.

Signed-off-by: MaJun <majun258@huawei.com>
---
 drivers/irqchip/irq-mbigen.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/irqchip/irq-mbigen.c b/drivers/irqchip/irq-mbigen.c
index 061cdb8..75818a5 100644
--- a/drivers/irqchip/irq-mbigen.c
+++ b/drivers/irqchip/irq-mbigen.c
@@ -108,7 +108,6 @@ static inline void get_mbigen_clear_reg(irq_hw_number_t hwirq,
 {
 	unsigned int ofst;
 
-	hwirq -= RESERVED_IRQ_PER_MBIGEN_CHIP;
 	ofst = hwirq / 32 * 4;
 
 	*mask = 1 << (hwirq % 32);
-- 
1.7.12.4

^ permalink raw reply related

* [PATCH 1/2] PCI: mediatek: Add Mediatek PCIe host controller support
From: Ryder Lee @ 2017-04-25  2:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170424220218.GA18659@bhelgaas-glaptop.roam.corp.google.com>

Hi,

On Mon, 2017-04-24 at 17:02 -0500, Bjorn Helgaas wrote:
> Hi Ryder,
> 
> Looks good, but I have a few questions below.
> 
> On Sun, Apr 23, 2017 at 04:19:02PM +0800, Ryder Lee wrote:
> > Add support for the Mediatek PCIe controller which can be found
> > on MT7623A/N, MT2701 and MT8521p platforms.
> > 
> > Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> > ---
> >  drivers/pci/host/Kconfig         |  11 +
> >  drivers/pci/host/Makefile        |   1 +
> >  drivers/pci/host/pcie-mediatek.c | 611 +++++++++++++++++++++++++++++++++++++++
> >  3 files changed, 623 insertions(+)
> >  create mode 100644 drivers/pci/host/pcie-mediatek.c
> > 
> > diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> > index f7c1d4d..cf13b5d 100644
> > --- a/drivers/pci/host/Kconfig
> > +++ b/drivers/pci/host/Kconfig
> > @@ -174,6 +174,17 @@ config PCIE_ROCKCHIP
> >  	  There is 1 internal PCIe port available to support GEN2 with
> >  	  4 slots.
> >  
> > +config PCIE_MEDIATEK
> > +	bool "Mediatek PCIe Controller for MT7623 SoCs families"
> > +	depends on (ARM && ARCH_MEDIATEK) || COMPILE_TEST
> > +	depends on OF
> > +	depends on PCI
> > +	select PCIEPORTBUS
> > +	help
> > +	  Say Y here if you want to enable PCIe controller support on MT7623 A/N
> > +	  series SoCs. There is a one root complex with 3 root ports available.
> > +	  Each port supports Gen2 lane x1.
> > +
> >  config VMD
> >  	depends on PCI_MSI && X86_64 && SRCU
> >  	tristate "Intel Volume Management Device Driver"
> > diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
> > index 4d36866..265adff 100644
> > --- a/drivers/pci/host/Makefile
> > +++ b/drivers/pci/host/Makefile
> > @@ -17,6 +17,7 @@ obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
> >  obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
> >  obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
> >  obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
> > +obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
> >  obj-$(CONFIG_VMD) += vmd.o
> >  
> >  # The following drivers are for devices that use the generic ACPI
> > diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> > new file mode 100644
> > index 0000000..98e84d9
> > --- /dev/null
> > +++ b/drivers/pci/host/pcie-mediatek.c
> > @@ -0,0 +1,611 @@
> > +/*
> > + * PCIe host controller driver for Mediatek MT7623 SoCs families
> > + *
> > + * Copyright (c) 2017 MediaTek Inc.
> > + * Author: Ryder Lee <ryder.lee@mediatek.com>
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License version 2 as
> > + * published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/delay.h>
> > +#include <linux/kernel.h>
> > +#include <linux/module.h>
> > +#include <linux/of_address.h>
> > +#include <linux/of_pci.h>
> > +#include <linux/of_platform.h>
> > +#include <linux/pci.h>
> > +#include <linux/phy/phy.h>
> > +#include <linux/platform_device.h>
> > +#include <linux/pm_runtime.h>
> > +#include <linux/reset.h>
> > +
> > +/* PCIe shared registers */
> > +#define PCIE_SYS_CFG		0x00
> > +#define PCIE_INT_ENABLE		0x0c
> > +#define PCIE_CFG_ADDR		0x20
> > +#define PCIE_CFG_DATA		0x24
> > +
> > +/* PCIe per port registers */
> > +#define PCIE_BAR0_SETUP		0x10
> > +#define PCIE_BAR1_SETUP		0x14
> > +#define PCIE_BAR0_MEM_BASE	0x18
> > +#define PCIE_CLASS		0x34
> > +#define PCIE_LINK_STATUS	0x50
> > +
> > +#define PCIE_PORT_INT_EN(x)	BIT(20 + (x))
> > +#define PCIE_PORT_PERST(x)	BIT(1 + (x))
> > +#define PCIE_PORT_LINKUP	BIT(0)
> > +#define PCIE_BAR_MAP_MAX	GENMASK(31, 16)
> > +
> > +#define PCIE_BAR_ENABLE		BIT(0)
> > +#define PCIE_REVISION_ID	BIT(0)
> > +#define PCIE_CLASS_CODE		(0x60400 << 8)
> > +#define PCIE_CONF_REG(regn)	(((regn) & GENMASK(7, 2)) | \
> > +				((((regn) >> 8) & GENMASK(3, 0)) << 24))
> > +#define PCIE_CONF_FUN(fun)	(((fun) << 8) & GENMASK(10, 8))
> > +#define PCIE_CONF_DEV(dev)	(((dev) << 11) & GENMASK(15, 11))
> > +#define PCIE_CONF_BUS(bus)	(((bus) << 16) & GENMASK(23, 16))
> > +#define PCIE_CONF_ADDR(regn, fun, dev, bus) \
> > +	(PCIE_CONF_REG(regn) | PCIE_CONF_FUN(fun) | \
> > +	 PCIE_CONF_DEV(dev) | PCIE_CONF_BUS(bus))
> > +
> > +/* Mediatek specific configuration registers */
> > +#define PCIE_FTS_NUM		0x70c
> > +#define PCIE_FTS_NUM_MASK	GENMASK(15, 8)
> > +#define PCIE_FTS_NUM_L0(x)	((x) & 0xff << 8)
> > +
> > +#define PCIE_FC_CREDIT		0x73c
> > +#define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
> > +#define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
> > +
> > +/**
> > + * struct mtk_pcie_port - PCIe port information
> > + * @dev: pointer to root port device
> > + * @base: IO mapped register base
> > + * @list: port list
> > + * @pcie: pointer to PCIe host info
> > + * @reset: pointer to RC reset control
> > + * @regs: port memory region
> > + * @sys_ck: root port clock
> > + * @phy: pointer to phy control block
> > + * @irq: IRQ number
> > + * @lane: lane count
> > + * @index: port index
> > + */
> > +struct mtk_pcie_port {
> > +	struct device *dev;
> > +	void __iomem *base;
> > +	struct list_head list;
> > +	struct mtk_pcie *pcie;
> > +	struct reset_control *reset;
> > +	struct resource regs;
> > +	struct clk *sys_ck;
> > +	struct phy *phy;
> > +	int irq;
> > +	u32 lane;
> > +	u32 index;
> > +};
> > +
> > +/**
> > + * struct mtk_pcie - PCIe host information
> > + * @dev: pointer to PCIe device
> > + * @base: IO mapped register Base
> > + * @free_ck: free-run reference clock
> > + * @resources: bus resources
> > + * @ports: pointer to PCIe port information
> > + */
> > +struct mtk_pcie {
> > +	struct device *dev;
> > +	void __iomem *base;
> > +	struct clk *free_ck;
> > +	struct list_head resources;
> > +	struct list_head ports;
> > +};
> > +
> > +static inline bool mtk_pcie_link_is_up(struct mtk_pcie_port *port)
> > +{
> > +	return !!(readl_relaxed(port->base + PCIE_LINK_STATUS) &
> > +		  PCIE_PORT_LINKUP);
> > +}
> > +
> > +static bool mtk_pcie_valid_device(struct mtk_pcie *pcie,
> > +				  struct pci_bus *bus, int devfn)
> > +{
> > +	struct mtk_pcie_port *port;
> > +	struct pci_dev *dev;
> > +	struct pci_bus *pbus;
> > +
> > +	/* if there is no link, then there is no device */
> > +	list_for_each_entry(port, &pcie->ports, list) {
> > +		if (bus->number == 0 && port->index == PCI_SLOT(devfn) &&
> > +		    mtk_pcie_link_is_up(port)) {
> > +			return true;
> > +		} else if (bus->number != 0) {
> > +			pbus = bus;
> > +			do {
> > +				dev = pbus->self;
> > +				if (port->index == PCI_SLOT(dev->devfn) &&
> > +				    mtk_pcie_link_is_up(port)) {
> > +					return true;
> > +				}
> > +				pbus = dev->bus;
> > +			} while (dev->bus->number != 0);
> > +		}
> > +	}
> > +
> > +	return false;
> > +}
> > +
> > +static void mtk_pcie_port_free(struct mtk_pcie_port *port)
> > +{
> > +	struct mtk_pcie *pcie = port->pcie;
> > +	struct device *dev = pcie->dev;
> > +
> > +	devm_iounmap(dev, port->base);
> > +	devm_release_mem_region(dev, port->regs.start,
> > +				resource_size(&port->regs));
> > +	list_del(&port->list);
> > +	devm_kfree(dev, port);
> > +}
> > +
> > +static int mtk_pcie_hw_rd_cfg(struct mtk_pcie *pcie, u32 bus, u32 devfn,
> > +			      int where, int size, u32 *val)
> > +{
> > +	writel(PCIE_CONF_ADDR(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> > +	       pcie->base + PCIE_CFG_ADDR);
> > +
> > +	*val = 0;
> > +
> > +	switch (size) {
> > +	case 1:
> > +		*val = readb(pcie->base + PCIE_CFG_DATA + (where & 3));
> > +		break;
> > +	case 2:
> > +		*val = readw(pcie->base + PCIE_CFG_DATA + (where & 2));
> > +		break;
> > +	case 4:
> > +		*val = readl(pcie->base + PCIE_CFG_DATA);
> > +		break;
> > +	}
> > +
> > +	return PCIBIOS_SUCCESSFUL;
> > +}
> > +
> > +static int mtk_pcie_hw_wr_cfg(struct mtk_pcie *pcie, u32 bus, u32 devfn,
> > +			      int where, int size, u32 val)
> > +
> > +{
> > +	writel(PCIE_CONF_ADDR(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> > +	       pcie->base + PCIE_CFG_ADDR);
> > +
> > +	switch (size) {
> > +	case 1:
> > +		writeb(val, pcie->base + PCIE_CFG_DATA + (where & 3));
> > +		break;
> > +	case 2:
> > +		writew(val, pcie->base + PCIE_CFG_DATA + (where & 2));
> > +		break;
> > +	case 4:
> > +		writel(val, pcie->base + PCIE_CFG_DATA);
> > +		break;
> > +	}
> > +
> > +	return PCIBIOS_SUCCESSFUL;
> > +}
> > +
> > +static int mtk_pcie_read_config(struct pci_bus *bus, u32 devfn,
> > +				int where, int size, u32 *val)
> > +{
> > +	struct mtk_pcie *pcie = bus->sysdata;
> > +	u32 bn = bus->number;
> > +
> > +	if (!mtk_pcie_valid_device(pcie, bus, devfn)) {
> > +		*val = 0xffffffff;
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +	}
> 
> I know there are some other drivers with the *_valid_device() pattern
> in their config accessors, but I don't like it because it's racy.
> It's possible for the link to be up for the test above, then go down
> before the actual config access below.
> 
> Your hardware *should* do something sensible if we try to read config
> space when the link is down, and ideally that would be enough that we
> don't need this "valid_device()" check.
> 
Yup,it's unnecessary, will remove it.

> > +	return mtk_pcie_hw_rd_cfg(pcie, bn, devfn, where, size, val);
> > +}
> > +
> > +static int mtk_pcie_write_config(struct pci_bus *bus, u32 devfn,
> > +				 int where, int size, u32 val)
> > +{
> > +	struct mtk_pcie *pcie = bus->sysdata;
> > +	u32 bn = bus->number;
> > +
> > +	if (!mtk_pcie_valid_device(pcie, bus, devfn))
> > +		return PCIBIOS_DEVICE_NOT_FOUND;
> > +
> > +	return mtk_pcie_hw_wr_cfg(pcie, bn, devfn, where, size, val);
> > +}
> > +
> > +static struct pci_ops mtk_pcie_ops = {
> > +	.read  = mtk_pcie_read_config,
> > +	.write = mtk_pcie_write_config,
> > +};
> > +
> > +static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> > +{
> > +	struct mtk_pcie *pcie = port->pcie;
> > +	u32 val;
> > +
> > +	/* enable interrupt */
> > +	val = readl(pcie->base + PCIE_INT_ENABLE);
> > +	val |= PCIE_PORT_INT_EN(port->index);
> > +	writel(val, pcie->base + PCIE_INT_ENABLE);
> > +
> > +	/* map to all DDR region. We need to set it before cfg operation. */
> > +	writel(PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE,
> > +	       port->base + PCIE_BAR0_SETUP);
> > +
> > +	/* configure class Code and revision ID */
> > +	writel(PCIE_CLASS_CODE | PCIE_REVISION_ID,
> > +	       port->base + PCIE_CLASS);
> > +
> > +	/* configure FC credit */
> > +	mtk_pcie_hw_rd_cfg(pcie, 0, (port->index << 3),
> > +			   PCIE_FC_CREDIT, 4, &val);
> > +	val &= ~PCIE_FC_CREDIT_MASK;
> > +	val |= PCIE_FC_CREDIT_VAL(0x806c);
> > +	mtk_pcie_hw_wr_cfg(pcie, 0, (port->index << 3),
> > +			   PCIE_FC_CREDIT, 4, val);
> > +
> > +	/* configure RC FTS number to 250 when it leaves L0s */
> > +	mtk_pcie_hw_rd_cfg(pcie, 0, (port->index << 3),
> > +			   PCIE_FTS_NUM, 4, &val);
> > +	val &= ~PCIE_FTS_NUM_MASK;
> > +	val |= PCIE_FTS_NUM_L0(0x50);
> > +	mtk_pcie_hw_wr_cfg(pcie, 0, (port->index << 3),
> > +			   PCIE_FTS_NUM, 4, val);
> > +}
> > +
> > +static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
> > +{
> > +	struct mtk_pcie *pcie = port->pcie;
> > +	u32 val;
> > +
> > +	/* assert port PERST_N */
> > +	val = readl(pcie->base + PCIE_SYS_CFG);
> > +	val |= PCIE_PORT_PERST(port->index);
> > +	writel(val, pcie->base + PCIE_SYS_CFG);
> > +
> > +	/* de-assert port PERST_N */
> > +	val = readl(pcie->base + PCIE_SYS_CFG);
> > +	val &= ~PCIE_PORT_PERST(port->index);
> > +	writel(val, pcie->base + PCIE_SYS_CFG);
> > +
> > +	/*
> > +	 * at least 100ms delay because PCIe v2.0 need more time to
> > +	 * train from Gen1 to Gen2
> > +	 */
> > +	msleep(100);
> > +}
> > +
> > +static int mtk_pcie_enable_ports(struct mtk_pcie *pcie)
> > +{
> > +	struct device *dev = pcie->dev;
> > +	struct mtk_pcie_port *port, *tmp;
> > +	int err, linkup = 0;
> > +
> > +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> > +		err = clk_prepare_enable(port->sys_ck);
> > +		if (err) {
> > +			dev_err(dev, "failed to enable port%d clock\n",
> > +				port->index);
> > +			continue;
> > +		}
> > +
> > +		/* assert RC */
> > +		reset_control_assert(port->reset);
> > +		/* de-assert RC */
> > +		reset_control_deassert(port->reset);
> > +
> > +		/* power on PHY */
> > +		err = phy_power_on(port->phy);
> > +		if (err) {
> > +			dev_err(dev, "failed to power on port%d phy\n",
> > +				port->index);
> > +			goto err_phy_on;
> > +		}
> > +
> > +		mtk_pcie_assert_ports(port);
> > +
> > +		/* if link up, then setup root port configuration space */
> > +		if (mtk_pcie_link_is_up(port)) {
> > +			mtk_pcie_configure_rc(port);
> > +			linkup++;
> > +			continue;
> > +		}
> > +
> > +		dev_info(dev, "Port%d link down\n", port->index);
> > +
> > +		phy_power_off(port->phy);
> > +err_phy_on:
> > +		clk_disable_unprepare(port->sys_ck);
> > +		mtk_pcie_port_free(port);
> > +	}
> > +
> > +	return linkup;
> > +}
> > +
> > +static int mtk_pcie_get_port_resource(struct mtk_pcie_port *port,
> > +				      struct device_node *node)
> > +{
> > +	struct device *dev = port->pcie->dev;
> > +	struct platform_device *pdev = to_platform_device(dev);
> > +	struct platform_device *plat_dev;
> > +	char name[10];
> > +	int err;
> > +
> > +	err = of_address_to_resource(node, 0, &port->regs);
> > +	if (err) {
> > +		dev_err(dev, "failed to parse address: %d\n", err);
> > +		return err;
> > +	}
> > +
> > +	port->base = devm_ioremap_resource(dev, &port->regs);
> > +	if (IS_ERR(port->base)) {
> > +		dev_err(dev, "failed to map port%d base\n", port->index);
> > +		return PTR_ERR(port->base);
> > +	}
> > +
> > +	plat_dev = of_find_device_by_node(node);
> > +	if (!plat_dev) {
> > +		plat_dev = of_platform_device_create(
> > +					node, NULL,
> > +					platform_bus_type.dev_root);
> > +		if (!plat_dev)
> > +			return -EPROBE_DEFER;
> > +	}
> > +
> > +	port->dev = &plat_dev->dev;
> > +
> > +	port->irq = platform_get_irq(pdev, port->index);
> > +	if (!port->irq) {
> > +		dev_err(dev, "failed to get irq\n");
> > +		return -ENODEV;
> > +	}
> > +
> > +	port->sys_ck = devm_clk_get(port->dev, "sys_ck");
> > +	if (IS_ERR(port->sys_ck)) {
> > +		dev_err(port->dev, "failed to get port%d clock\n", port->index);
> > +		return PTR_ERR(port->sys_ck);
> > +	}
> > +
> > +	port->reset = devm_reset_control_get(port->dev, "pcie-reset");
> > +	if (IS_ERR(port->reset)) {
> > +		dev_err(port->dev, "failed to get port%d reset control\n",
> > +			port->index);
> > +		return PTR_ERR(port->reset);
> > +	}
> > +
> > +	snprintf(name, sizeof(name), "pcie-phy%d", port->index);
> > +	port->phy = devm_of_phy_get(port->dev, node, name);
> > +	if (IS_ERR(port->phy)) {
> > +		dev_err(port->dev, "failed to get port%d phy\n", port->index);
> > +		return PTR_ERR(port->phy);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_pcie_parse_and_add_res(struct mtk_pcie *pcie)
> > +{
> > +	struct device *dev = pcie->dev;
> > +	struct platform_device *pdev = to_platform_device(dev);
> > +	struct device_node *node = dev->of_node, *child;
> > +	struct resource_entry *win, *tmp;
> > +	struct resource *regs;
> > +	resource_size_t iobase;
> > +	int err;
> > +
> > +	/* parse shared resources */
> > +	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> > +	pcie->base = devm_ioremap_resource(dev, regs);
> > +	if (IS_ERR(pcie->base)) {
> > +		dev_err(dev, "failed to get PCIe base\n");
> > +		return PTR_ERR(pcie->base);
> > +	}
> > +
> > +	pcie->free_ck = devm_clk_get(dev, "free_ck");
> > +	if (IS_ERR(pcie->free_ck)) {
> > +		dev_err(dev, "failed to get free_ck\n");
> > +		return PTR_ERR(pcie->free_ck);
> > +	}
> > +
> > +	err = of_pci_get_host_bridge_resources(node, 0, 0xff, &pcie->resources,
> > +					       &iobase);
> > +	if (err)
> > +		return err;
> > +
> > +	err = devm_request_pci_bus_resources(dev, &pcie->resources);
> > +	if (err)
> > +		return err;
> > +
> > +	resource_list_for_each_entry_safe(win, tmp, &pcie->resources) {
> > +		struct resource *res = win->res;
> > +
> > +		switch (resource_type(res)) {
> > +		case IORESOURCE_IO:
> > +			err = pci_remap_iospace(res, iobase);
> > +			if (err) {
> > +				dev_warn(dev, "failed to map resource %pR\n",
> > +					 res);
> > +				resource_list_destroy_entry(win);
> > +			}
> > +			break;
> > +		}
> > +	}
> > +
> > +	/* parse port resources */
> > +	for_each_child_of_node(node, child) {
> > +		struct mtk_pcie_port *port;
> > +		int index;
> > +
> > +		err = of_pci_get_devfn(child);
> > +		if (err < 0) {
> > +			dev_err(pcie->dev, "failed to parse devfn: %d\n", err);
> 
> dev_err(dev, ...)

OK.
> > +			return err;
> > +		}
> > +
> > +		index = PCI_SLOT(err);
> > +		if (index < 1) {
> > +			dev_err(dev, "invalid port number: %d\n", index);
> > +			return -EINVAL;
> > +		}
> > +
> > +		index--;
> > +
> > +		if (!of_device_is_available(child))
> > +			continue;
> > +
> > +		port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> > +		if (!port)
> > +			return -ENOMEM;
> > +
> > +		err = of_property_read_u32(child, "num-lanes", &port->lane);
> > +		if (err) {
> > +			dev_err(dev, "missing num-lanes property\n");
> > +			return err;
> > +		}
> > +
> > +		port->index = index;
> > +		port->pcie = pcie;
> > +
> > +		err = mtk_pcie_get_port_resource(port, child);
> > +		if (err)
> > +			return err;
> > +
> > +		INIT_LIST_HEAD(&port->list);
> > +		list_add_tail(&port->list, &pcie->ports);
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +/*
> > + * This IP lacks interrupt status register to check or map INTx from
> > + * different devices at the same time.
> > + */
> > +static int __init mtk_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> > +{
> > +	struct mtk_pcie *pcie = dev->bus->sysdata;
> > +	struct mtk_pcie_port *port;
> > +
> > +	list_for_each_entry(port, &pcie->ports, list)
> > +		if (port->index == slot)
> > +			return port->irq;
> > +
> > +	return -1;
> > +}
> > +
> > +static int mtk_pcie_register_ports(struct mtk_pcie *pcie)
> > +{
> > +	struct pci_bus *bus, *child;
> > +
> > +	bus = pci_scan_root_bus(pcie->dev, 0, &mtk_pcie_ops, pcie,
> > +				&pcie->resources);
> > +	if (!bus) {
> > +		dev_err(pcie->dev, "failed to create root bus\n");
> > +		return -ENOMEM;
> > +	}
> > +
> > +	if (!pci_has_flag(PCI_PROBE_ONLY)) {
> > +		pci_fixup_irqs(pci_common_swizzle, mtk_pcie_map_irq);
> > +		pci_bus_size_bridges(bus);
> > +		pci_bus_assign_resources(bus);
> > +
> > +		list_for_each_entry(child, &bus->children, node)
> > +			pcie_bus_configure_settings(child);
> 
> Do you actually need the functionality of PCI_PROBE_ONLY?  We're
> trying to get rid of this, so if you don't need it, please omit it.
> 
> If you *do* need it, can you include a note about why?
> 
> If you do need it, I don't think PCI_PROBE_ONLY should control
> pci_fixup_irqs() or pcie_bus_configure_settings().  I know there is
> some other similar code that does this, but I think PCI_PROBE_ONLY
> should only influence resource assignment, i.e., BARs and bridge
> windows.  I don't want it to influence IRQs or the MPS/MRRS settings
> done by pcie_bus_configure_settings() if we can avoid it.

I will remove it, thanks.
> > +	}
> > +
> > +	pci_bus_add_devices(bus);
> > +
> > +	return 0;
> > +}
> > +
> > +static int mtk_pcie_probe(struct platform_device *pdev)
> > +{
> > +	struct mtk_pcie *pcie;
> > +	int err;
> > +
> > +	pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
> > +	if (!pcie)
> > +		return -ENOMEM;
> > +
> > +	pcie->dev = &pdev->dev;
> > +	platform_set_drvdata(pdev, pcie);
> > +
> > +	/*
> > +	 * parse PCI ranges, configuration bus range and
> > +	 * request their resources
> > +	 */
> > +	INIT_LIST_HEAD(&pcie->ports);
> > +	INIT_LIST_HEAD(&pcie->resources);
> > +
> > +	err = mtk_pcie_parse_and_add_res(pcie);
> > +	if (err)
> > +		goto err_parse;
> > +
> > +	pm_runtime_enable(pcie->dev);
> > +	err = pm_runtime_get_sync(pcie->dev);
> > +	if (err)
> > +		goto err_pm;
> > +
> > +	err = clk_prepare_enable(pcie->free_ck);
> > +	if (err) {
> > +		dev_err(pcie->dev, "failed to enable free_ck\n");
> > +		goto err_free_ck;
> > +	}
> > +
> > +	/* power on PCIe ports */
> > +	err = mtk_pcie_enable_ports(pcie);
> > +	if (!err)
> > +		goto err_enable;
> > +
> > +	/* register PCIe ports */
> > +	err = mtk_pcie_register_ports(pcie);
> > +	if (err)
> > +		goto err_enable;
> > +
> > +	return 0;
> > +
> > +err_enable:
> > +	clk_disable_unprepare(pcie->free_ck);
> > +err_free_ck:
> > +	pm_runtime_put_sync(pcie->dev);
> > +err_pm:
> > +	pm_runtime_disable(pcie->dev);
> > +err_parse:
> > +	pci_free_resource_list(&pcie->resources);
> > +
> > +	return err;
> > +}
> > +
> > +static const struct of_device_id mtk_pcie_ids[] = {
> > +	{ .compatible = "mediatek,mt7623-pcie"},
> > +	{ .compatible = "mediatek,mt2701-pcie"},
> > +	{},
> > +};
> > +MODULE_DEVICE_TABLE(of, mtk_pcie_ids);
> > +
> > +static struct platform_driver mtk_pcie_driver = {
> > +	.probe = mtk_pcie_probe,
> > +	.driver = {
> > +		.name = "mtk-pcie",
> > +		.of_match_table = mtk_pcie_ids,
> 
> Per [1], I think you should have ".suppress_bind_attrs = true," here.
> Without it, apparently you can easily crash the system by unbinding
> the driver, as in [2].
> 
> [1] https://git.kernel.org/cgit/linux/kernel/git/helgaas/pci.git/commit/?id=65e0527b933a
> [2] https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git/commit/?id=073d3dbe9a7c
OK!
> > +	},
> > +};
> > +
> > +builtin_platform_driver(mtk_pcie_driver);
> > +
> > +MODULE_DESCRIPTION("Mediatek PCIe host driver for MT7623 SoCs families");
> > +MODULE_LICENSE("GPL v2");
> > -- 
> > 1.9.1
> > 

Thanks for your review!
> > _______________________________________________
> > linux-arm-kernel mailing list
> > linux-arm-kernel at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 
> _______________________________________________
> Linux-mediatek mailing list
> Linux-mediatek at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-mediatek

^ permalink raw reply

* support autofocus / autogain in libv4l2
From: Mauro Carvalho Chehab @ 2017-04-25  1:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170424220701.GA27846@amd>

Em Tue, 25 Apr 2017 00:07:01 +0200
Pavel Machek <pavel@ucw.cz> escreveu:

> Hi!
> 
> > Please don't add a new application under lib/. It is fine if you want
> > some testing application, if the ones there aren't enough, but please
> > place it under contrib/test/.
> > 
> > You should likely take a look at v4l2grab first, as it could have
> > almost everything you would need.  
> 
> I really need some kind of video output. v4l2grab is not useful
> there. v4l2gl might be, but I don't think I have enough dependencies.

Well, you could use some app to show the snaps that v4l2grab takes.

Yeah, compiling v4l2gl on N9 can indeed be complex. I suspect that it 
shouldn't hard to compile xawtv there (probably disabling some optional
features).

> Umm, and it looks like libv4l can not automatically convert from
> GRBG10.. and if it could, going through RGB24 would probably be too
> slow on this device :-(.

I suspect it shouldn't be hard to add support for GRBG10. It already
supports 8 and 16 bits Bayer formats, at lib/libv4lconvert/bayer.c
(to both RGB and YUV formats).

How it would preform is another question ;)

> > IMO, the above belongs to a separate processing module under
> > 	lib/libv4lconvert/processing/  
> 
> Is there an example using autogain/autowhitebalance from
> libv4lconvert?

Well, if you plug a USB camera without those controls, it should
automatically expose controls for it, as if the device had such
controls.

Thanks,
Mauro

^ permalink raw reply

* [PATCH] arm64: dts: exynos: Remove the te-gpios property in the TM2 boards
From: Hoegeun Kwon @ 2017-04-25  1:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CGME20170425015437epcas5p43549d47e69519f43d89ba2de496ba451@epcas5p4.samsung.com>

The decon uses HW-TRIGGER, so TE interrupt is not necessary.
Therefore, remove the te-gpios property in the TM2 dts.

Signed-off-by: Hoegeun Kwon <hoegeun.kwon@samsung.com>
---
 arch/arm64/boot/dts/exynos/exynos5433-tm2.dts | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts b/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts
index 3ff9527..23191eb 100644
--- a/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts
+++ b/arch/arm64/boot/dts/exynos/exynos5433-tm2.dts
@@ -60,7 +60,6 @@
 		vci-supply = <&ldo28_reg>;
 		reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>;
 		enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>;
-		te-gpios = <&gpf1 3 GPIO_ACTIVE_HIGH>;
 	};
 };
 
-- 
1.9.1

^ permalink raw reply related

* [PATCH] [media] pxa_camera: fix module remove codepath for v4l2 clock
From: Petr Cvek @ 2017-04-25  1:51 UTC (permalink / raw)
  To: linux-arm-kernel

The conversion from soc_camera omitted a correct handling of the clock
gating for a sensor. When the pxa_camera driver module was removed it
tried to unregister clk, but this caused a similar warning:

  WARNING: CPU: 0 PID: 6740 at drivers/media/v4l2-core/v4l2-clk.c:278
  v4l2_clk_unregister(): Refusing to unregister ref-counted 0-0030 clock!

The clock was at time still refcounted by the sensor driver. Before
the removing of the pxa_camera the clock must be dropped by the sensor
driver. This should be triggered by v4l2_async_notifier_unregister() call
which removes sensor driver module too, calls unbind() function and then
tries to probe sensor driver again. Inside unbind() we can safely
unregister the v4l2 clock as the sensor driver got removed. The original
v4l2_clk_unregister() should be put inside test as the clock can be
already unregistered from unbind(). If there was not any bound sensor
the clock is still present.

The codepath is practically a copy from the old soc_camera. The bug was
tested with a pxa_camera+ov9640 combination during the conversion
of the ov9640 from the soc_camera.

Signed-off-by: Petr Cvek <petr.cvek@tul.cz>
---
 drivers/media/platform/pxa_camera.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/pxa_camera.c b/drivers/media/platform/pxa_camera.c
index 929006f65cc7..6615f80fe059 100644
--- a/drivers/media/platform/pxa_camera.c
+++ b/drivers/media/platform/pxa_camera.c
@@ -2177,6 +2177,12 @@ static void pxa_camera_sensor_unbind(struct v4l2_async_notifier *notifier,
 	pxa_dma_stop_channels(pcdev);
 
 	pxa_camera_destroy_formats(pcdev);
+
+	if (pcdev->mclk_clk) {
+		v4l2_clk_unregister(pcdev->mclk_clk);
+		pcdev->mclk_clk = NULL;
+	}
+
 	video_unregister_device(&pcdev->vdev);
 	pcdev->sensor = NULL;
 
@@ -2501,7 +2507,13 @@ static int pxa_camera_remove(struct platform_device *pdev)
 	dma_release_channel(pcdev->dma_chans[1]);
 	dma_release_channel(pcdev->dma_chans[2]);
 
-	v4l2_clk_unregister(pcdev->mclk_clk);
+	v4l2_async_notifier_unregister(&pcdev->notifier);
+
+	if (pcdev->mclk_clk) {
+		v4l2_clk_unregister(pcdev->mclk_clk);
+		pcdev->mclk_clk = NULL;
+	}
+
 	v4l2_device_unregister(&pcdev->v4l2_dev);
 
 	dev_info(&pdev->dev, "PXA Camera driver unloaded\n");
-- 
2.11.0

^ permalink raw reply related

* support autofocus / autogain in libv4l2
From: Mauro Carvalho Chehab @ 2017-04-25  1:47 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170424212914.GA20780@amd>

Em Mon, 24 Apr 2017 23:29:14 +0200
Pavel Machek <pavel@ucw.cz> escreveu:

> Hi!
> 
> > > For focus to be useful, we need autofocus implmented
> > > somewhere. Unfortunately, v4l framework does not seem to provide good
> > > place where to put autofocus. I believe, long-term, we'll need some
> > > kind of "video server" providing this kind of services.
> > > 
> > > Anyway, we probably don't want autofocus in kernel (even through some
> > > cameras do it in hardware), and we probably don't want autofocus in
> > > each and every user application.
> > > 
> > > So what remains is libv4l2.   
> > 
> > IMO, the best place for autofocus is at libv4l2. Putting it on a
> > separate "video server" application looks really weird for me.  
> 
> Well... let me see. libraries are quite limited -- it is hard to open
> files, or use threads/have custom main loop. It may be useful to
> switch resolutions -- do autofocus/autogain at lower resolution, then
> switch to high one for taking picture. It would be good to have that
> in "system" code, but I'm not at all sure libv4l2 design will allow
> that.

I don't see why it would be hard to open files or have threads inside
a library. There are several libraries that do that already, specially
the ones designed to be used on multimidia apps.

Resolution switch can indeed be a problem on devices that use MC
and subdev API, as a plugin would be required to teach the library
about N9 specifics (or the Kernel API should be improved to let
a generic application to better detect the hardware capabilities).

> It would be good if application could say "render live camera into
> this window" and only care about user interface, then say "give me a
> high resolution jpeg". But that would require main loop in the
> library...

Nothing prevents writing an upper layer on the top of libv4l in
order to provide such kind of functions.

> It would be nice if more than one application could be accessing the
> camera at the same time... (I.e. something graphical running preview
> then using command line tool to grab a picture.) This one is
> definitely not solveable inside a library...

Someone once suggested to have something like pulseaudio for V4L.
For such usage, a server would be interesting. Yet, I would code it
in a way that applications using libv4l will talk with such daemon
in a transparent way.

> > The above looks really odd. Why do you want to make libv4l2 dependent
> > on sdl?  
> 
> I don't, but I had some nasty problems with linker; this should really
> go into application but it refused to link. Scary libtool.

That's weird. 


> > If you're adding a SDL-specific application, you'll need to add the 
> > needed autoconf bits to detect if SDL devel package is installed,
> > auto-disabling it if not.
> > 
> > Yet, I don't think that SDL should be part of the library, but,
> > instead, part of some application.  
> 
> Agreed. libtool prevented me from doing the right thing.

if you add libSDL detection at configure.ac, you likely won't need to
deal with libtool.

On a quick look at web, it seems that there's a m4 module that does
the right thing, according with:
	https://wiki.libsdl.org/FAQLinux


Thanks,
Mauro

^ permalink raw reply

* [PATCH v3 1/3] mtd: nand: Cleanup/rework the atmel_nand driver
From: Brian Norris @ 2017-04-25  1:09 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1489651362-17077-2-git-send-email-boris.brezillon@free-electrons.com>

On Thu, Mar 16, 2017 at 09:02:40AM +0100, Boris Brezillon wrote:

> diff --git a/drivers/mtd/nand/atmel/nand-controller.c b/drivers/mtd/nand/atmel/nand-controller.c
> new file mode 100644
> index 000000000000..f71b9e5d7d9d
> --- /dev/null
> +++ b/drivers/mtd/nand/atmel/nand-controller.c
> @@ -0,0 +1,2198 @@
[...]

> +static int
> +atmel_hsmc_nand_controller_legacy_init(struct atmel_hsmc_nand_controller *nc)
> +{
> +	struct regmap_config regmap_conf = {
> +		.reg_bits = 32,
> +		.val_bits = 32,
> +		.reg_stride = 4,
> +		.val_bits = 32,

You assigned val_bits twice. Is that just a harmless mistake, or did you
mean to set something else?

(sparse and other tools complain about this)

> +	};


Brian

^ permalink raw reply

* [PATCH 2/2] ARM: dts: Add the ethernet and ethernet PHY to the cygnus core DT.
From: Eric Anholt @ 2017-04-25  0:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1759fb29-0678-0ec5-5398-16c4a3ba9660@gmail.com>

Florian Fainelli <f.fainelli@gmail.com> writes:

> On 04/24/2017 02:50 PM, Eric Anholt wrote:
>> Cygnus has a single amac controller connected to the B53 switch with 2
>> PHYs.  On the BCM911360_EP platform, those two PHYs are connected to
>> the external ethernet jacks.
>> 
>> Signed-off-by: Eric Anholt <eric@anholt.net>
>
> This looks fine, just a few nits on the label names:

Thanks.  I've applied all of these (and Andrew's and Scott's
suggestions), and I'll send out a new version once the DT maintainers
have had a chance to look.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170424/897c79ae/attachment.sig>

^ permalink raw reply

* [PATCH 2/2] ARM: dts: Add the ethernet and ethernet PHY to the cygnus core DT.
From: Eric Anholt @ 2017-04-25  0:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170424220842.GA26241@lunn.ch>

Andrew Lunn <andrew@lunn.ch> writes:

>> +		mdio: mdio at 18002000 {
>> +			compatible = "brcm,iproc-mdio";
>> +			reg = <0x18002000 0x8>;
>> +			#size-cells = <1>;
>> +			#address-cells = <0>;
>> +
>> +			gphy0: eth-gphy at 0 {
>> +				reg = <0>;
>> +				max-speed = <1000>;
>> +			};
>> +
>> +			gphy1: eth-gphy at 1 {
>> +				reg = <1>;
>> +				max-speed = <1000>;
>> +			};
>> +		};
>
> Hi Eric
>
> Do these max-speed properties do anything useful? Is the PHY capable
> of > 1Gbps?

Not sure where I had those copy-and-pasted from, but they don't seem
necessary.  Dropped.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170424/ee121fb9/attachment.sig>

^ permalink raw reply

* [PATCH 4/5] Hot-remove implementation for arm64
From: Laura Abbott @ 2017-04-24 23:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170421100500.GB20029@samekh>

On 04/21/2017 03:05 AM, Andrea Reale wrote:
> Hi all,
> 
> thanks for taking the time to comment. Replies in-line.
> 
> On Wed, Apr 19, 2017 at 08:53:13AM -0700, Laura Abbott wrote:
>> On 04/18/2017 11:48 AM, Ard Biesheuvel wrote:
>>> On 18 April 2017 at 19:21, Mark Rutland <mark.rutland@arm.com> wrote:
>>>> On Fri, Apr 14, 2017 at 03:01:58PM +0100, Andrea Reale wrote:
> 
> [...]
> 
>>>>
>>>> From a quick scan, I see that it's necessary to use pgtable_page_ctor()
>>>> for pages that will be used for userspace page tables, but it's not
>>>> clear to me if it's ever necessary for pages used for kernel page
>>>> tables.
>>>>
>>>> If it is, we appear to have a bug on arm64.
>>>>
>>>> Laura, Ard, thoughts?
>>>>
>>>
>>> The generic apply_to_page_range() will expect the PTE lock to be
>>> initialized for page table pages that are not part of init_mm. For
>>> arm64, that is precisely efi_mm as far as I am aware. For EFI, the
>>> locking is unnecessary but does no harm (the permissions are set once
>>> via apply_to_page_range() at boot), so I added this call when adding
>>> support for strict permissions in EFI rt services mappings.
>>>
>>> So I think it is appropriate for create_pgd_mapping() to be in charge
>>> of calling the ctor(). We simply have no destroy_pgd_mapping()
>>> counterpart that would be the place for the dtor() call, given that we
>>> never take down EFI rt services mappi >
>>> Whether it makes sense or not to lock/unlock in apply_to_page_range()
>>> is something I did not spend any brain cycles on at the time.
>>>
>>
>> Agreed there shouldn't be a problem right now. I do think the locking is
>> appropriate in apply_to_page_range given what other functions also get
>> locked.
>>
>> I really wish this were less asymmetrical though since it get hard
>> to reason about. It looks like hotplug_paging will call the ctor,
>> so is there an issue with calling hot-remove on memory that was once
>> hot-added or is that not a concern?
>>
>> Thanks,
>> Laura
> 
> I think the confusion comes from the fact that, in hotplug_paging, we are
> passing pgd_pgtable_alloc as the page allocator for __create_pgd_mapping,
> which always calls the ctor.
> 
> If I got things right (but, please, correct me if I am wrong), we don't
> need to get the pte_lock that the ctor gets since - in hotplug - we are
> adding to init_mm.
> 
> Moreover, I am just realizing that calling the dtor while hot-removing
> might create problems when removing memory that *was not* previously
> hotplugged, as we are calling a dtor on something that was never
> ctor'ed. Is that what you were hinting at, Laura?
> 
> Thanks and best regards,
> Andrea
> 

Yes, that was what I was thinking.

Thanks,
Laura

^ permalink raw reply

* [PATCH 1/2] net: dsa: b53: Add compatible strings for the Cygnus-family BCM11360.
From: Scott Branden @ 2017-04-24 23:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <8760hte4zw.fsf@eliezer.anholt.net>



On 17-04-24 04:54 PM, Eric Anholt wrote:
> Scott Branden <scott.branden@broadcom.com> writes:
>
>> Minor comment in line
>>
>> On 17-04-24 02:50 PM, Eric Anholt wrote:
>>> Cygnus is a small family of SoCs, of which we currently have
>>> devicetree for BCM11360 and BCM58300.  The 11360's B53 is mostly the
>>> same as 58xx, just requiring a tiny bit of setup that was previously
>>> missing.
>>>
>>> Signed-off-by: Eric Anholt <eric@anholt.net>
>>> ---
>>>  Documentation/devicetree/bindings/net/dsa/b53.txt | 3 +++
>>>  drivers/net/dsa/b53/b53_srab.c                    | 2 ++
>>>  2 files changed, 5 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/net/dsa/b53.txt b/Documentation/devicetree/bindings/net/dsa/b53.txt
>>> index d6c6e41648d4..49c93d3c0839 100644
>>> --- a/Documentation/devicetree/bindings/net/dsa/b53.txt
>>> +++ b/Documentation/devicetree/bindings/net/dsa/b53.txt
>>> @@ -29,6 +29,9 @@ Required properties:
>>>        "brcm,bcm58625-srab"
>>>        "brcm,bcm88312-srab" and the mandatory "brcm,nsp-srab string
>>>
>>> +  For the BCM11360 SoC, must be:
>>> +      "brcm,bcm11360-srab" and the mandatory "brcm,cygnus-srab string
>>> +
>> place in alphabetical order in the doc?
>
> Moved it above BCM5310x now.  I hope that's what you meant.
>
Yes, sorry for not being more clear.

^ permalink raw reply

* [PATCH v7 1/4] syscalls: Restore address limit after a syscall
From: Kees Cook @ 2017-04-24 23:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170410164420.64003-1-thgarnie@google.com>

On Mon, Apr 10, 2017 at 9:44 AM, Thomas Garnier <thgarnie@google.com> wrote:
> This patch ensures a syscall does not return to user-mode with a kernel
> address limit. If that happened, a process can corrupt kernel-mode
> memory and elevate privileges.
>
> For example, it would mitigation this bug:
>
> - https://bugs.chromium.org/p/project-zero/issues/detail?id=990
>
> The CONFIG_ARCH_NO_SYSCALL_VERIFY_PRE_USERMODE_STATE option is also
> added so each architecture can optimize this change.
>
> Signed-off-by: Thomas Garnier <thgarnie@google.com>
> Tested-by: Kees Cook <keescook@chromium.org>

Ingo, I think this series is ready. Can you pull it? (And if not, what
should next steps be?)

-Kees

> ---
> Based on next-20170410
> ---
>  arch/s390/Kconfig        |  1 +
>  include/linux/syscalls.h | 26 +++++++++++++++++++++++++-
>  init/Kconfig             |  6 ++++++
>  kernel/sys.c             | 13 +++++++++++++
>  4 files changed, 45 insertions(+), 1 deletion(-)
>
> diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
> index d25435d94b6e..489a0cc6e46b 100644
> --- a/arch/s390/Kconfig
> +++ b/arch/s390/Kconfig
> @@ -103,6 +103,7 @@ config S390
>         select ARCH_INLINE_WRITE_UNLOCK_BH
>         select ARCH_INLINE_WRITE_UNLOCK_IRQ
>         select ARCH_INLINE_WRITE_UNLOCK_IRQRESTORE
> +       select ARCH_NO_SYSCALL_VERIFY_PRE_USERMODE_STATE
>         select ARCH_SAVE_PAGE_KEYS if HIBERNATION
>         select ARCH_SUPPORTS_ATOMIC_RMW
>         select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT
> diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
> index 980c3c9b06f8..801a7a74fe28 100644
> --- a/include/linux/syscalls.h
> +++ b/include/linux/syscalls.h
> @@ -191,6 +191,27 @@ extern struct trace_event_functions exit_syscall_print_funcs;
>         SYSCALL_METADATA(sname, x, __VA_ARGS__)                 \
>         __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
>
> +
> +/*
> + * Called before coming back to user-mode. Returning to user-mode with an
> + * address limit different than USER_DS can allow to overwrite kernel memory.
> + */
> +static inline void verify_pre_usermode_state(void) {
> +       BUG_ON(!segment_eq(get_fs(), USER_DS));
> +}
> +
> +#ifndef CONFIG_ARCH_NO_SYSCALL_VERIFY_PRE_USERMODE_STATE
> +#define __CHECK_USER_CALLER() \
> +       bool user_caller = segment_eq(get_fs(), USER_DS)
> +#define __VERIFY_PRE_USERMODE_STATE() \
> +       if (user_caller) verify_pre_usermode_state()
> +#else
> +#define __CHECK_USER_CALLER()
> +#define __VERIFY_PRE_USERMODE_STATE()
> +asmlinkage void address_limit_check_failed(void);
> +#endif
> +
> +
>  #define __PROTECT(...) asmlinkage_protect(__VA_ARGS__)
>  #define __SYSCALL_DEFINEx(x, name, ...)                                        \
>         asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__))       \
> @@ -199,7 +220,10 @@ extern struct trace_event_functions exit_syscall_print_funcs;
>         asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__));      \
>         asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__))       \
>         {                                                               \
> -               long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));  \
> +               long ret;                                               \
> +               __CHECK_USER_CALLER();                                  \
> +               ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__));       \
> +               __VERIFY_PRE_USERMODE_STATE();                          \
>                 __MAP(x,__SC_TEST,__VA_ARGS__);                         \
>                 __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__));       \
>                 return ret;                                             \
> diff --git a/init/Kconfig b/init/Kconfig
> index 7f7027817bce..e5fbd0becfa7 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -1958,6 +1958,12 @@ config PROFILING
>  config TRACEPOINTS
>         bool
>
> +config ARCH_NO_SYSCALL_VERIFY_PRE_USERMODE_STATE
> +       bool
> +       help
> +         Disable the generic pre-usermode state verification. Allow each
> +         architecture to optimize how and when the verification is done.
> +
>  source "arch/Kconfig"
>
>  endmenu                # General setup
> diff --git a/kernel/sys.c b/kernel/sys.c
> index 196c7134bee6..d30530ff8166 100644
> --- a/kernel/sys.c
> +++ b/kernel/sys.c
> @@ -2459,3 +2459,16 @@ COMPAT_SYSCALL_DEFINE1(sysinfo, struct compat_sysinfo __user *, info)
>         return 0;
>  }
>  #endif /* CONFIG_COMPAT */
> +
> +#ifdef CONFIG_ARCH_NO_SYSCALL_VERIFY_PRE_USERMODE_STATE
> +/*
> + * This function is called when an architecture specific implementation detected
> + * an invalid address limit. The generic user-mode state checker will finish on
> + * the appropriate BUG_ON.
> + */
> +asmlinkage void address_limit_check_failed(void)
> +{
> +       verify_pre_usermode_state();
> +       panic("address_limit_check_failed called with a valid user-mode state");
> +}
> +#endif
> --
> 2.12.2.715.g7642488e1d-goog
>



-- 
Kees Cook
Pixel Security

^ permalink raw reply

* [PATCH 1/2] net: dsa: b53: Add compatible strings for the Cygnus-family BCM11360.
From: Eric Anholt @ 2017-04-24 23:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <a2f4f0c9-feea-291b-dae5-f4ed10f9c547@broadcom.com>

Scott Branden <scott.branden@broadcom.com> writes:

> Minor comment in line
>
> On 17-04-24 02:50 PM, Eric Anholt wrote:
>> Cygnus is a small family of SoCs, of which we currently have
>> devicetree for BCM11360 and BCM58300.  The 11360's B53 is mostly the
>> same as 58xx, just requiring a tiny bit of setup that was previously
>> missing.
>>
>> Signed-off-by: Eric Anholt <eric@anholt.net>
>> ---
>>  Documentation/devicetree/bindings/net/dsa/b53.txt | 3 +++
>>  drivers/net/dsa/b53/b53_srab.c                    | 2 ++
>>  2 files changed, 5 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/net/dsa/b53.txt b/Documentation/devicetree/bindings/net/dsa/b53.txt
>> index d6c6e41648d4..49c93d3c0839 100644
>> --- a/Documentation/devicetree/bindings/net/dsa/b53.txt
>> +++ b/Documentation/devicetree/bindings/net/dsa/b53.txt
>> @@ -29,6 +29,9 @@ Required properties:
>>        "brcm,bcm58625-srab"
>>        "brcm,bcm88312-srab" and the mandatory "brcm,nsp-srab string
>>
>> +  For the BCM11360 SoC, must be:
>> +      "brcm,bcm11360-srab" and the mandatory "brcm,cygnus-srab string
>> +
> place in alphabetical order in the doc?

Moved it above BCM5310x now.  I hope that's what you meant.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 832 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170424/ec506094/attachment.sig>

^ permalink raw reply

* [PATCH 1/2] net: dsa: b53: Add compatible strings for the Cygnus-family BCM11360.
From: Florian Fainelli @ 2017-04-24 23:17 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1361654c-e4eb-e0a0-3397-b43235b5ff60@broadcom.com>

On 04/24/2017 04:15 PM, Arun Parameswaran wrote:
> 
> 
> On 17-04-24 04:07 PM, Florian Fainelli wrote:
>> On 04/24/2017 04:03 PM, Arun Parameswaran wrote:
>>> Hi Eric
>>>
>>> A comment on the Device ID.
>>>
>>>
>>> On 17-04-24 02:50 PM, Eric Anholt wrote:
>>>> Cygnus is a small family of SoCs, of which we currently have
>>>> devicetree for BCM11360 and BCM58300.  The 11360's B53 is mostly the
>>>> same as 58xx, just requiring a tiny bit of setup that was previously
>>>> missing.
>>>>
>>>> Signed-off-by: Eric Anholt <eric@anholt.net>
>>>> ---
>>>>  Documentation/devicetree/bindings/net/dsa/b53.txt | 3 +++
>>>>  drivers/net/dsa/b53/b53_srab.c                    | 2 ++
>>>>  2 files changed, 5 insertions(+)
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/net/dsa/b53.txt b/Documentation/devicetree/bindings/net/dsa/b53.txt
>>>> index d6c6e41648d4..49c93d3c0839 100644
>>>> --- a/Documentation/devicetree/bindings/net/dsa/b53.txt
>>>> +++ b/Documentation/devicetree/bindings/net/dsa/b53.txt
>>>> @@ -29,6 +29,9 @@ Required properties:
>>>>        "brcm,bcm58625-srab"
>>>>        "brcm,bcm88312-srab" and the mandatory "brcm,nsp-srab string
>>>>  
>>>> +  For the BCM11360 SoC, must be:
>>>> +      "brcm,bcm11360-srab" and the mandatory "brcm,cygnus-srab string
>>>> +
>>>>    For the BCM63xx/33xx SoCs with an integrated switch, must be one of:
>>>>        "brcm,bcm3384-switch"
>>>>        "brcm,bcm6328-switch"
>>>> diff --git a/drivers/net/dsa/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c
>>>> index 8a62b6a69703..c37ffd1b6833 100644
>>>> --- a/drivers/net/dsa/b53/b53_srab.c
>>>> +++ b/drivers/net/dsa/b53/b53_srab.c
>>>> @@ -364,6 +364,7 @@ static const struct of_device_id b53_srab_of_match[] = {
>>>>  	{ .compatible = "brcm,bcm53018-srab" },
>>>>  	{ .compatible = "brcm,bcm53019-srab" },
>>>>  	{ .compatible = "brcm,bcm5301x-srab" },
>>>> +	{ .compatible = "brcm,bcm11360-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>>>  	{ .compatible = "brcm,bcm58522-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>>>  	{ .compatible = "brcm,bcm58525-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>>>  	{ .compatible = "brcm,bcm58535-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>>> @@ -371,6 +372,7 @@ static const struct of_device_id b53_srab_of_match[] = {
>>>>  	{ .compatible = "brcm,bcm58623-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>>>  	{ .compatible = "brcm,bcm58625-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>>>  	{ .compatible = "brcm,bcm88312-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>>> +	{ .compatible = "brcm,cygnus-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>> The device ID should be 0xd300. This is the actual value read from the switch regs.
>>> This also requires an entry in the 'b53_switch_chips' structure in b53_common.c.
>> These are not real ID numbers, these are values that indicate the
>> generation of the switch being embedded into the SoC. Within
>> b53_common.c we don't have to differentiate a Starfighter 2 embedded in
>> BCM11360, NSP, or 7445 or 7278, which is why using 58XX_DEVICE_ID should
>> be good enough.
> Ok. Thanks.
> 
> I was under the impression, that these id's could be used in the b53_switch_detect()
> API to auto detect the switch. In that API, the switch ID is read from the
> Management page register.

For external switches that is the case, but for internal/integrated
switches, the ID is not always representative of the switch. This is why
the choice of a chip-type ID was used here while adding support for NSP
to the b53 driver.

-- 
Florian

^ permalink raw reply

* [PATCH 1/2] net: dsa: b53: Add compatible strings for the Cygnus-family BCM11360.
From: Arun Parameswaran @ 2017-04-24 23:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <173c8ff2-6a31-5460-9a3f-8d8ac445a336@gmail.com>



On 17-04-24 04:07 PM, Florian Fainelli wrote:
> On 04/24/2017 04:03 PM, Arun Parameswaran wrote:
>> Hi Eric
>>
>> A comment on the Device ID.
>>
>>
>> On 17-04-24 02:50 PM, Eric Anholt wrote:
>>> Cygnus is a small family of SoCs, of which we currently have
>>> devicetree for BCM11360 and BCM58300.  The 11360's B53 is mostly the
>>> same as 58xx, just requiring a tiny bit of setup that was previously
>>> missing.
>>>
>>> Signed-off-by: Eric Anholt <eric@anholt.net>
>>> ---
>>>  Documentation/devicetree/bindings/net/dsa/b53.txt | 3 +++
>>>  drivers/net/dsa/b53/b53_srab.c                    | 2 ++
>>>  2 files changed, 5 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/net/dsa/b53.txt b/Documentation/devicetree/bindings/net/dsa/b53.txt
>>> index d6c6e41648d4..49c93d3c0839 100644
>>> --- a/Documentation/devicetree/bindings/net/dsa/b53.txt
>>> +++ b/Documentation/devicetree/bindings/net/dsa/b53.txt
>>> @@ -29,6 +29,9 @@ Required properties:
>>>        "brcm,bcm58625-srab"
>>>        "brcm,bcm88312-srab" and the mandatory "brcm,nsp-srab string
>>>  
>>> +  For the BCM11360 SoC, must be:
>>> +      "brcm,bcm11360-srab" and the mandatory "brcm,cygnus-srab string
>>> +
>>>    For the BCM63xx/33xx SoCs with an integrated switch, must be one of:
>>>        "brcm,bcm3384-switch"
>>>        "brcm,bcm6328-switch"
>>> diff --git a/drivers/net/dsa/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c
>>> index 8a62b6a69703..c37ffd1b6833 100644
>>> --- a/drivers/net/dsa/b53/b53_srab.c
>>> +++ b/drivers/net/dsa/b53/b53_srab.c
>>> @@ -364,6 +364,7 @@ static const struct of_device_id b53_srab_of_match[] = {
>>>  	{ .compatible = "brcm,bcm53018-srab" },
>>>  	{ .compatible = "brcm,bcm53019-srab" },
>>>  	{ .compatible = "brcm,bcm5301x-srab" },
>>> +	{ .compatible = "brcm,bcm11360-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>>  	{ .compatible = "brcm,bcm58522-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>>  	{ .compatible = "brcm,bcm58525-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>>  	{ .compatible = "brcm,bcm58535-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>> @@ -371,6 +372,7 @@ static const struct of_device_id b53_srab_of_match[] = {
>>>  	{ .compatible = "brcm,bcm58623-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>>  	{ .compatible = "brcm,bcm58625-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>>  	{ .compatible = "brcm,bcm88312-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>> +	{ .compatible = "brcm,cygnus-srab", .data = (void *)BCM58XX_DEVICE_ID },
>> The device ID should be 0xd300. This is the actual value read from the switch regs.
>> This also requires an entry in the 'b53_switch_chips' structure in b53_common.c.
> These are not real ID numbers, these are values that indicate the
> generation of the switch being embedded into the SoC. Within
> b53_common.c we don't have to differentiate a Starfighter 2 embedded in
> BCM11360, NSP, or 7445 or 7278, which is why using 58XX_DEVICE_ID should
> be good enough.
Ok. Thanks.

I was under the impression, that these id's could be used in the b53_switch_detect()
API to auto detect the switch. In that API, the switch ID is read from the
Management page register.

>>>  	{ .compatible = "brcm,nsp-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>>  	{ /* sentinel */ },
>>>  };
>> Other wise this patch set looks good.
>>
>> I was testing a similar change (except for the above, which doesn't
>> affect the functionality) to get the switch working and it works.
>>
>> Thanks
>> Arun
>>
>

^ permalink raw reply

* [PATCH 1/2] net: dsa: b53: Add compatible strings for the Cygnus-family BCM11360.
From: Florian Fainelli @ 2017-04-24 23:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <ee265657-8175-b6c7-a0dc-cec216cd9ede@broadcom.com>

On 04/24/2017 04:03 PM, Arun Parameswaran wrote:
> Hi Eric
> 
> A comment on the Device ID.
> 
> 
> On 17-04-24 02:50 PM, Eric Anholt wrote:
>> Cygnus is a small family of SoCs, of which we currently have
>> devicetree for BCM11360 and BCM58300.  The 11360's B53 is mostly the
>> same as 58xx, just requiring a tiny bit of setup that was previously
>> missing.
>>
>> Signed-off-by: Eric Anholt <eric@anholt.net>
>> ---
>>  Documentation/devicetree/bindings/net/dsa/b53.txt | 3 +++
>>  drivers/net/dsa/b53/b53_srab.c                    | 2 ++
>>  2 files changed, 5 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/net/dsa/b53.txt b/Documentation/devicetree/bindings/net/dsa/b53.txt
>> index d6c6e41648d4..49c93d3c0839 100644
>> --- a/Documentation/devicetree/bindings/net/dsa/b53.txt
>> +++ b/Documentation/devicetree/bindings/net/dsa/b53.txt
>> @@ -29,6 +29,9 @@ Required properties:
>>        "brcm,bcm58625-srab"
>>        "brcm,bcm88312-srab" and the mandatory "brcm,nsp-srab string
>>  
>> +  For the BCM11360 SoC, must be:
>> +      "brcm,bcm11360-srab" and the mandatory "brcm,cygnus-srab string
>> +
>>    For the BCM63xx/33xx SoCs with an integrated switch, must be one of:
>>        "brcm,bcm3384-switch"
>>        "brcm,bcm6328-switch"
>> diff --git a/drivers/net/dsa/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c
>> index 8a62b6a69703..c37ffd1b6833 100644
>> --- a/drivers/net/dsa/b53/b53_srab.c
>> +++ b/drivers/net/dsa/b53/b53_srab.c
>> @@ -364,6 +364,7 @@ static const struct of_device_id b53_srab_of_match[] = {
>>  	{ .compatible = "brcm,bcm53018-srab" },
>>  	{ .compatible = "brcm,bcm53019-srab" },
>>  	{ .compatible = "brcm,bcm5301x-srab" },
>> +	{ .compatible = "brcm,bcm11360-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>  	{ .compatible = "brcm,bcm58522-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>  	{ .compatible = "brcm,bcm58525-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>  	{ .compatible = "brcm,bcm58535-srab", .data = (void *)BCM58XX_DEVICE_ID },
>> @@ -371,6 +372,7 @@ static const struct of_device_id b53_srab_of_match[] = {
>>  	{ .compatible = "brcm,bcm58623-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>  	{ .compatible = "brcm,bcm58625-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>  	{ .compatible = "brcm,bcm88312-srab", .data = (void *)BCM58XX_DEVICE_ID },
>> +	{ .compatible = "brcm,cygnus-srab", .data = (void *)BCM58XX_DEVICE_ID },
> The device ID should be 0xd300. This is the actual value read from the switch regs.
> This also requires an entry in the 'b53_switch_chips' structure in b53_common.c.

These are not real ID numbers, these are values that indicate the
generation of the switch being embedded into the SoC. Within
b53_common.c we don't have to differentiate a Starfighter 2 embedded in
BCM11360, NSP, or 7445 or 7278, which is why using 58XX_DEVICE_ID should
be good enough.

>>  	{ .compatible = "brcm,nsp-srab", .data = (void *)BCM58XX_DEVICE_ID },
>>  	{ /* sentinel */ },
>>  };
> Other wise this patch set looks good.
> 
> I was testing a similar change (except for the above, which doesn't
> affect the functionality) to get the switch working and it works.
> 
> Thanks
> Arun
> 


-- 
Florian

^ permalink raw reply

* [PATCH 1/2] net: dsa: b53: Add compatible strings for the Cygnus-family BCM11360.
From: Arun Parameswaran @ 2017-04-24 23:03 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170424215022.30382-2-eric@anholt.net>

Hi Eric

A comment on the Device ID.


On 17-04-24 02:50 PM, Eric Anholt wrote:
> Cygnus is a small family of SoCs, of which we currently have
> devicetree for BCM11360 and BCM58300.  The 11360's B53 is mostly the
> same as 58xx, just requiring a tiny bit of setup that was previously
> missing.
>
> Signed-off-by: Eric Anholt <eric@anholt.net>
> ---
>  Documentation/devicetree/bindings/net/dsa/b53.txt | 3 +++
>  drivers/net/dsa/b53/b53_srab.c                    | 2 ++
>  2 files changed, 5 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/net/dsa/b53.txt b/Documentation/devicetree/bindings/net/dsa/b53.txt
> index d6c6e41648d4..49c93d3c0839 100644
> --- a/Documentation/devicetree/bindings/net/dsa/b53.txt
> +++ b/Documentation/devicetree/bindings/net/dsa/b53.txt
> @@ -29,6 +29,9 @@ Required properties:
>        "brcm,bcm58625-srab"
>        "brcm,bcm88312-srab" and the mandatory "brcm,nsp-srab string
>  
> +  For the BCM11360 SoC, must be:
> +      "brcm,bcm11360-srab" and the mandatory "brcm,cygnus-srab string
> +
>    For the BCM63xx/33xx SoCs with an integrated switch, must be one of:
>        "brcm,bcm3384-switch"
>        "brcm,bcm6328-switch"
> diff --git a/drivers/net/dsa/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c
> index 8a62b6a69703..c37ffd1b6833 100644
> --- a/drivers/net/dsa/b53/b53_srab.c
> +++ b/drivers/net/dsa/b53/b53_srab.c
> @@ -364,6 +364,7 @@ static const struct of_device_id b53_srab_of_match[] = {
>  	{ .compatible = "brcm,bcm53018-srab" },
>  	{ .compatible = "brcm,bcm53019-srab" },
>  	{ .compatible = "brcm,bcm5301x-srab" },
> +	{ .compatible = "brcm,bcm11360-srab", .data = (void *)BCM58XX_DEVICE_ID },
>  	{ .compatible = "brcm,bcm58522-srab", .data = (void *)BCM58XX_DEVICE_ID },
>  	{ .compatible = "brcm,bcm58525-srab", .data = (void *)BCM58XX_DEVICE_ID },
>  	{ .compatible = "brcm,bcm58535-srab", .data = (void *)BCM58XX_DEVICE_ID },
> @@ -371,6 +372,7 @@ static const struct of_device_id b53_srab_of_match[] = {
>  	{ .compatible = "brcm,bcm58623-srab", .data = (void *)BCM58XX_DEVICE_ID },
>  	{ .compatible = "brcm,bcm58625-srab", .data = (void *)BCM58XX_DEVICE_ID },
>  	{ .compatible = "brcm,bcm88312-srab", .data = (void *)BCM58XX_DEVICE_ID },
> +	{ .compatible = "brcm,cygnus-srab", .data = (void *)BCM58XX_DEVICE_ID },
The device ID should be 0xd300. This is the actual value read from the switch regs.
This also requires an entry in the 'b53_switch_chips' structure in b53_common.c.
>  	{ .compatible = "brcm,nsp-srab", .data = (void *)BCM58XX_DEVICE_ID },
>  	{ /* sentinel */ },
>  };
Other wise this patch set looks good.

I was testing a similar change (except for the above, which doesn't
affect the functionality) to get the switch working and it works.

Thanks
Arun

^ permalink raw reply

* [PATCH] ARM: tegra: Select appropriate DMA options for LPAE
From: Paul Kocialkowski @ 2017-04-24 22:59 UTC (permalink / raw)
  To: linux-arm-kernel

This automatically selects options for zone DMA and 64 bit DMA addresses
when LPAE is enabled on ARM Tegra platforms. These options are required
for proper operation with LPAE enabled.

Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
---
 arch/arm/mach-tegra/Kconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index 329f01c5b6f8..c8368d647741 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -13,5 +13,7 @@ menuconfig ARCH_TEGRA
 	select ARCH_HAS_RESET_CONTROLLER
 	select RESET_CONTROLLER
 	select SOC_BUS
+	select ZONE_DMA if ARM_LPAE
+	select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
 	help
 	  This enables support for NVIDIA Tegra based systems.
-- 
2.12.2

^ permalink raw reply related

* [PATCH 1/2] net: dsa: b53: Add compatible strings for the Cygnus-family BCM11360.
From: Scott Branden @ 2017-04-24 22:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170424215022.30382-2-eric@anholt.net>

Minor comment in line

On 17-04-24 02:50 PM, Eric Anholt wrote:
> Cygnus is a small family of SoCs, of which we currently have
> devicetree for BCM11360 and BCM58300.  The 11360's B53 is mostly the
> same as 58xx, just requiring a tiny bit of setup that was previously
> missing.
>
> Signed-off-by: Eric Anholt <eric@anholt.net>
> ---
>  Documentation/devicetree/bindings/net/dsa/b53.txt | 3 +++
>  drivers/net/dsa/b53/b53_srab.c                    | 2 ++
>  2 files changed, 5 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/net/dsa/b53.txt b/Documentation/devicetree/bindings/net/dsa/b53.txt
> index d6c6e41648d4..49c93d3c0839 100644
> --- a/Documentation/devicetree/bindings/net/dsa/b53.txt
> +++ b/Documentation/devicetree/bindings/net/dsa/b53.txt
> @@ -29,6 +29,9 @@ Required properties:
>        "brcm,bcm58625-srab"
>        "brcm,bcm88312-srab" and the mandatory "brcm,nsp-srab string
>
> +  For the BCM11360 SoC, must be:
> +      "brcm,bcm11360-srab" and the mandatory "brcm,cygnus-srab string
> +
place in alphabetical order in the doc?

>    For the BCM63xx/33xx SoCs with an integrated switch, must be one of:
>        "brcm,bcm3384-switch"
>        "brcm,bcm6328-switch"
> diff --git a/drivers/net/dsa/b53/b53_srab.c b/drivers/net/dsa/b53/b53_srab.c
> index 8a62b6a69703..c37ffd1b6833 100644
> --- a/drivers/net/dsa/b53/b53_srab.c
> +++ b/drivers/net/dsa/b53/b53_srab.c
> @@ -364,6 +364,7 @@ static const struct of_device_id b53_srab_of_match[] = {
>  	{ .compatible = "brcm,bcm53018-srab" },
>  	{ .compatible = "brcm,bcm53019-srab" },
>  	{ .compatible = "brcm,bcm5301x-srab" },
> +	{ .compatible = "brcm,bcm11360-srab", .data = (void *)BCM58XX_DEVICE_ID },
>  	{ .compatible = "brcm,bcm58522-srab", .data = (void *)BCM58XX_DEVICE_ID },
>  	{ .compatible = "brcm,bcm58525-srab", .data = (void *)BCM58XX_DEVICE_ID },
>  	{ .compatible = "brcm,bcm58535-srab", .data = (void *)BCM58XX_DEVICE_ID },
> @@ -371,6 +372,7 @@ static const struct of_device_id b53_srab_of_match[] = {
>  	{ .compatible = "brcm,bcm58623-srab", .data = (void *)BCM58XX_DEVICE_ID },
>  	{ .compatible = "brcm,bcm58625-srab", .data = (void *)BCM58XX_DEVICE_ID },
>  	{ .compatible = "brcm,bcm88312-srab", .data = (void *)BCM58XX_DEVICE_ID },
> +	{ .compatible = "brcm,cygnus-srab", .data = (void *)BCM58XX_DEVICE_ID },
>  	{ .compatible = "brcm,nsp-srab", .data = (void *)BCM58XX_DEVICE_ID },
>  	{ /* sentinel */ },
>  };
>

^ permalink raw reply

* [PATCH V2] scsi: mpt3sas: remove redundant wmb
From: Martin K. Petersen @ 2017-04-24 22:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1491591978-17880-1-git-send-email-okaya@codeaurora.org>


Sinan,

> Due to relaxed ordering requirements on multiple architectures,
> drivers are required to use wmb/rmb/mb combinations when they need to
> guarantee observability between the memory and the HW.

Applied to 4.12/scsi-queue, thanks!

-- 
Martin K. Petersen	Oracle Linux Engineering

^ permalink raw reply

* [PATCH 1/3] coresight: Replace sprintf with scnprintf
From: Olav Haugan @ 2017-04-24 22:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170408154223.GA22401@kroah.com>

On 17-04-08 17:42:23, Greg KH wrote:
> On Mon, Mar 27, 2017 at 11:09:31AM -0600, Mathieu Poirier wrote:
> > From: Olav Haugan <ohaugan@codeaurora.org>
> > 
> > Replace all occurrences of sprintf with scnprintf in coresight driver for
> > consistency. scnprintf is also a safer alternative to sprintf.
> 
> But it's totally pointless here :(
> 

The driver is using a mix of sprintf and scnprintf. This patch is
making the usage consistent across the driver. (There is actually more scnprintf
usage than sprintf usage.) Consistency is good. What is the harm?

> > 
> > Signed-off-by: Olav Haugan <ohaugan@codeaurora.org>
> > Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
> > ---
> >  drivers/hwtracing/coresight/coresight-etb10.c      |  2 +-
> >  drivers/hwtracing/coresight/coresight-etm-perf.c   |  2 +-
> >  .../hwtracing/coresight/coresight-etm3x-sysfs.c    | 66 +++++++++++-----------
> >  drivers/hwtracing/coresight/coresight-funnel.c     |  4 +-
> >  drivers/hwtracing/coresight/coresight-stm.c        |  2 +-
> >  drivers/hwtracing/coresight/coresight-tmc.c        |  2 +-
> >  6 files changed, 39 insertions(+), 39 deletions(-)
> > 
> > diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c
> > index d7325c6534ad..491f4da61c11 100644
> > --- a/drivers/hwtracing/coresight/coresight-etb10.c
> > +++ b/drivers/hwtracing/coresight/coresight-etb10.c
> > @@ -588,7 +588,7 @@ static ssize_t trigger_cntr_show(struct device *dev,
> >  	struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
> >  	unsigned long val = drvdata->trigger_cntr;
> >  
> > -	return sprintf(buf, "%#lx\n", val);
> > +	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
> 
> There is no need for this in sysfs show callbacks.  You _know_ this is a
> PAGE_SIZE buffer, and that you can not overflow it with a simple number.
> 
> So don't change these types of functions for no reason please.
> 
> Same for most of this patch.
> 
> thanks,
> 
> greg k-h
> 

-- 
.Olav

The Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project

^ permalink raw reply

* [PATCH 2/2] ARM: dts: Add the ethernet and ethernet PHY to the cygnus core DT.
From: Andrew Lunn @ 2017-04-24 22:08 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170424215022.30382-3-eric@anholt.net>

> +		mdio: mdio at 18002000 {
> +			compatible = "brcm,iproc-mdio";
> +			reg = <0x18002000 0x8>;
> +			#size-cells = <1>;
> +			#address-cells = <0>;
> +
> +			gphy0: eth-gphy at 0 {
> +				reg = <0>;
> +				max-speed = <1000>;
> +			};
> +
> +			gphy1: eth-gphy at 1 {
> +				reg = <1>;
> +				max-speed = <1000>;
> +			};
> +		};

Hi Eric

Do these max-speed properties do anything useful? Is the PHY capable
of > 1Gbps?

   Thanks
	Andrew

^ permalink raw reply

* support autofocus / autogain in libv4l2
From: Pavel Machek @ 2017-04-24 22:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170424103802.00d3b554@vento.lan>

Hi!

> Please don't add a new application under lib/. It is fine if you want
> some testing application, if the ones there aren't enough, but please
> place it under contrib/test/.
> 
> You should likely take a look at v4l2grab first, as it could have
> almost everything you would need.

I really need some kind of video output. v4l2grab is not useful
there. v4l2gl might be, but I don't think I have enough dependencies.

Umm, and it looks like libv4l can not automatically convert from
GRBG10.. and if it could, going through RGB24 would probably be too
slow on this device :-(.

> IMO, the above belongs to a separate processing module under
> 	lib/libv4lconvert/processing/

Is there an example using autogain/autowhitebalance from
libv4lconvert?

Best regards,
									Pavel
-- 
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20170425/c41537cc/attachment.sig>

^ permalink raw reply

* [PATCH 1/2] PCI: mediatek: Add Mediatek PCIe host controller support
From: Bjorn Helgaas @ 2017-04-24 22:02 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1492935543-18190-2-git-send-email-ryder.lee@mediatek.com>

Hi Ryder,

Looks good, but I have a few questions below.

On Sun, Apr 23, 2017 at 04:19:02PM +0800, Ryder Lee wrote:
> Add support for the Mediatek PCIe controller which can be found
> on MT7623A/N, MT2701 and MT8521p platforms.
> 
> Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
> ---
>  drivers/pci/host/Kconfig         |  11 +
>  drivers/pci/host/Makefile        |   1 +
>  drivers/pci/host/pcie-mediatek.c | 611 +++++++++++++++++++++++++++++++++++++++
>  3 files changed, 623 insertions(+)
>  create mode 100644 drivers/pci/host/pcie-mediatek.c
> 
> diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
> index f7c1d4d..cf13b5d 100644
> --- a/drivers/pci/host/Kconfig
> +++ b/drivers/pci/host/Kconfig
> @@ -174,6 +174,17 @@ config PCIE_ROCKCHIP
>  	  There is 1 internal PCIe port available to support GEN2 with
>  	  4 slots.
>  
> +config PCIE_MEDIATEK
> +	bool "Mediatek PCIe Controller for MT7623 SoCs families"
> +	depends on (ARM && ARCH_MEDIATEK) || COMPILE_TEST
> +	depends on OF
> +	depends on PCI
> +	select PCIEPORTBUS
> +	help
> +	  Say Y here if you want to enable PCIe controller support on MT7623 A/N
> +	  series SoCs. There is a one root complex with 3 root ports available.
> +	  Each port supports Gen2 lane x1.
> +
>  config VMD
>  	depends on PCI_MSI && X86_64 && SRCU
>  	tristate "Intel Volume Management Device Driver"
> diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
> index 4d36866..265adff 100644
> --- a/drivers/pci/host/Makefile
> +++ b/drivers/pci/host/Makefile
> @@ -17,6 +17,7 @@ obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
>  obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
>  obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
>  obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o
> +obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o
>  obj-$(CONFIG_VMD) += vmd.o
>  
>  # The following drivers are for devices that use the generic ACPI
> diff --git a/drivers/pci/host/pcie-mediatek.c b/drivers/pci/host/pcie-mediatek.c
> new file mode 100644
> index 0000000..98e84d9
> --- /dev/null
> +++ b/drivers/pci/host/pcie-mediatek.c
> @@ -0,0 +1,611 @@
> +/*
> + * PCIe host controller driver for Mediatek MT7623 SoCs families
> + *
> + * Copyright (c) 2017 MediaTek Inc.
> + * Author: Ryder Lee <ryder.lee@mediatek.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/delay.h>
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of_address.h>
> +#include <linux/of_pci.h>
> +#include <linux/of_platform.h>
> +#include <linux/pci.h>
> +#include <linux/phy/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/pm_runtime.h>
> +#include <linux/reset.h>
> +
> +/* PCIe shared registers */
> +#define PCIE_SYS_CFG		0x00
> +#define PCIE_INT_ENABLE		0x0c
> +#define PCIE_CFG_ADDR		0x20
> +#define PCIE_CFG_DATA		0x24
> +
> +/* PCIe per port registers */
> +#define PCIE_BAR0_SETUP		0x10
> +#define PCIE_BAR1_SETUP		0x14
> +#define PCIE_BAR0_MEM_BASE	0x18
> +#define PCIE_CLASS		0x34
> +#define PCIE_LINK_STATUS	0x50
> +
> +#define PCIE_PORT_INT_EN(x)	BIT(20 + (x))
> +#define PCIE_PORT_PERST(x)	BIT(1 + (x))
> +#define PCIE_PORT_LINKUP	BIT(0)
> +#define PCIE_BAR_MAP_MAX	GENMASK(31, 16)
> +
> +#define PCIE_BAR_ENABLE		BIT(0)
> +#define PCIE_REVISION_ID	BIT(0)
> +#define PCIE_CLASS_CODE		(0x60400 << 8)
> +#define PCIE_CONF_REG(regn)	(((regn) & GENMASK(7, 2)) | \
> +				((((regn) >> 8) & GENMASK(3, 0)) << 24))
> +#define PCIE_CONF_FUN(fun)	(((fun) << 8) & GENMASK(10, 8))
> +#define PCIE_CONF_DEV(dev)	(((dev) << 11) & GENMASK(15, 11))
> +#define PCIE_CONF_BUS(bus)	(((bus) << 16) & GENMASK(23, 16))
> +#define PCIE_CONF_ADDR(regn, fun, dev, bus) \
> +	(PCIE_CONF_REG(regn) | PCIE_CONF_FUN(fun) | \
> +	 PCIE_CONF_DEV(dev) | PCIE_CONF_BUS(bus))
> +
> +/* Mediatek specific configuration registers */
> +#define PCIE_FTS_NUM		0x70c
> +#define PCIE_FTS_NUM_MASK	GENMASK(15, 8)
> +#define PCIE_FTS_NUM_L0(x)	((x) & 0xff << 8)
> +
> +#define PCIE_FC_CREDIT		0x73c
> +#define PCIE_FC_CREDIT_MASK	(GENMASK(31, 31) | GENMASK(28, 16))
> +#define PCIE_FC_CREDIT_VAL(x)	((x) << 16)
> +
> +/**
> + * struct mtk_pcie_port - PCIe port information
> + * @dev: pointer to root port device
> + * @base: IO mapped register base
> + * @list: port list
> + * @pcie: pointer to PCIe host info
> + * @reset: pointer to RC reset control
> + * @regs: port memory region
> + * @sys_ck: root port clock
> + * @phy: pointer to phy control block
> + * @irq: IRQ number
> + * @lane: lane count
> + * @index: port index
> + */
> +struct mtk_pcie_port {
> +	struct device *dev;
> +	void __iomem *base;
> +	struct list_head list;
> +	struct mtk_pcie *pcie;
> +	struct reset_control *reset;
> +	struct resource regs;
> +	struct clk *sys_ck;
> +	struct phy *phy;
> +	int irq;
> +	u32 lane;
> +	u32 index;
> +};
> +
> +/**
> + * struct mtk_pcie - PCIe host information
> + * @dev: pointer to PCIe device
> + * @base: IO mapped register Base
> + * @free_ck: free-run reference clock
> + * @resources: bus resources
> + * @ports: pointer to PCIe port information
> + */
> +struct mtk_pcie {
> +	struct device *dev;
> +	void __iomem *base;
> +	struct clk *free_ck;
> +	struct list_head resources;
> +	struct list_head ports;
> +};
> +
> +static inline bool mtk_pcie_link_is_up(struct mtk_pcie_port *port)
> +{
> +	return !!(readl_relaxed(port->base + PCIE_LINK_STATUS) &
> +		  PCIE_PORT_LINKUP);
> +}
> +
> +static bool mtk_pcie_valid_device(struct mtk_pcie *pcie,
> +				  struct pci_bus *bus, int devfn)
> +{
> +	struct mtk_pcie_port *port;
> +	struct pci_dev *dev;
> +	struct pci_bus *pbus;
> +
> +	/* if there is no link, then there is no device */
> +	list_for_each_entry(port, &pcie->ports, list) {
> +		if (bus->number == 0 && port->index == PCI_SLOT(devfn) &&
> +		    mtk_pcie_link_is_up(port)) {
> +			return true;
> +		} else if (bus->number != 0) {
> +			pbus = bus;
> +			do {
> +				dev = pbus->self;
> +				if (port->index == PCI_SLOT(dev->devfn) &&
> +				    mtk_pcie_link_is_up(port)) {
> +					return true;
> +				}
> +				pbus = dev->bus;
> +			} while (dev->bus->number != 0);
> +		}
> +	}
> +
> +	return false;
> +}
> +
> +static void mtk_pcie_port_free(struct mtk_pcie_port *port)
> +{
> +	struct mtk_pcie *pcie = port->pcie;
> +	struct device *dev = pcie->dev;
> +
> +	devm_iounmap(dev, port->base);
> +	devm_release_mem_region(dev, port->regs.start,
> +				resource_size(&port->regs));
> +	list_del(&port->list);
> +	devm_kfree(dev, port);
> +}
> +
> +static int mtk_pcie_hw_rd_cfg(struct mtk_pcie *pcie, u32 bus, u32 devfn,
> +			      int where, int size, u32 *val)
> +{
> +	writel(PCIE_CONF_ADDR(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> +	       pcie->base + PCIE_CFG_ADDR);
> +
> +	*val = 0;
> +
> +	switch (size) {
> +	case 1:
> +		*val = readb(pcie->base + PCIE_CFG_DATA + (where & 3));
> +		break;
> +	case 2:
> +		*val = readw(pcie->base + PCIE_CFG_DATA + (where & 2));
> +		break;
> +	case 4:
> +		*val = readl(pcie->base + PCIE_CFG_DATA);
> +		break;
> +	}
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int mtk_pcie_hw_wr_cfg(struct mtk_pcie *pcie, u32 bus, u32 devfn,
> +			      int where, int size, u32 val)
> +
> +{
> +	writel(PCIE_CONF_ADDR(where, PCI_FUNC(devfn), PCI_SLOT(devfn), bus),
> +	       pcie->base + PCIE_CFG_ADDR);
> +
> +	switch (size) {
> +	case 1:
> +		writeb(val, pcie->base + PCIE_CFG_DATA + (where & 3));
> +		break;
> +	case 2:
> +		writew(val, pcie->base + PCIE_CFG_DATA + (where & 2));
> +		break;
> +	case 4:
> +		writel(val, pcie->base + PCIE_CFG_DATA);
> +		break;
> +	}
> +
> +	return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int mtk_pcie_read_config(struct pci_bus *bus, u32 devfn,
> +				int where, int size, u32 *val)
> +{
> +	struct mtk_pcie *pcie = bus->sysdata;
> +	u32 bn = bus->number;
> +
> +	if (!mtk_pcie_valid_device(pcie, bus, devfn)) {
> +		*val = 0xffffffff;
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +	}

I know there are some other drivers with the *_valid_device() pattern
in their config accessors, but I don't like it because it's racy.
It's possible for the link to be up for the test above, then go down
before the actual config access below.

Your hardware *should* do something sensible if we try to read config
space when the link is down, and ideally that would be enough that we
don't need this "valid_device()" check.

> +	return mtk_pcie_hw_rd_cfg(pcie, bn, devfn, where, size, val);
> +}
> +
> +static int mtk_pcie_write_config(struct pci_bus *bus, u32 devfn,
> +				 int where, int size, u32 val)
> +{
> +	struct mtk_pcie *pcie = bus->sysdata;
> +	u32 bn = bus->number;
> +
> +	if (!mtk_pcie_valid_device(pcie, bus, devfn))
> +		return PCIBIOS_DEVICE_NOT_FOUND;
> +
> +	return mtk_pcie_hw_wr_cfg(pcie, bn, devfn, where, size, val);
> +}
> +
> +static struct pci_ops mtk_pcie_ops = {
> +	.read  = mtk_pcie_read_config,
> +	.write = mtk_pcie_write_config,
> +};
> +
> +static void mtk_pcie_configure_rc(struct mtk_pcie_port *port)
> +{
> +	struct mtk_pcie *pcie = port->pcie;
> +	u32 val;
> +
> +	/* enable interrupt */
> +	val = readl(pcie->base + PCIE_INT_ENABLE);
> +	val |= PCIE_PORT_INT_EN(port->index);
> +	writel(val, pcie->base + PCIE_INT_ENABLE);
> +
> +	/* map to all DDR region. We need to set it before cfg operation. */
> +	writel(PCIE_BAR_MAP_MAX | PCIE_BAR_ENABLE,
> +	       port->base + PCIE_BAR0_SETUP);
> +
> +	/* configure class Code and revision ID */
> +	writel(PCIE_CLASS_CODE | PCIE_REVISION_ID,
> +	       port->base + PCIE_CLASS);
> +
> +	/* configure FC credit */
> +	mtk_pcie_hw_rd_cfg(pcie, 0, (port->index << 3),
> +			   PCIE_FC_CREDIT, 4, &val);
> +	val &= ~PCIE_FC_CREDIT_MASK;
> +	val |= PCIE_FC_CREDIT_VAL(0x806c);
> +	mtk_pcie_hw_wr_cfg(pcie, 0, (port->index << 3),
> +			   PCIE_FC_CREDIT, 4, val);
> +
> +	/* configure RC FTS number to 250 when it leaves L0s */
> +	mtk_pcie_hw_rd_cfg(pcie, 0, (port->index << 3),
> +			   PCIE_FTS_NUM, 4, &val);
> +	val &= ~PCIE_FTS_NUM_MASK;
> +	val |= PCIE_FTS_NUM_L0(0x50);
> +	mtk_pcie_hw_wr_cfg(pcie, 0, (port->index << 3),
> +			   PCIE_FTS_NUM, 4, val);
> +}
> +
> +static void mtk_pcie_assert_ports(struct mtk_pcie_port *port)
> +{
> +	struct mtk_pcie *pcie = port->pcie;
> +	u32 val;
> +
> +	/* assert port PERST_N */
> +	val = readl(pcie->base + PCIE_SYS_CFG);
> +	val |= PCIE_PORT_PERST(port->index);
> +	writel(val, pcie->base + PCIE_SYS_CFG);
> +
> +	/* de-assert port PERST_N */
> +	val = readl(pcie->base + PCIE_SYS_CFG);
> +	val &= ~PCIE_PORT_PERST(port->index);
> +	writel(val, pcie->base + PCIE_SYS_CFG);
> +
> +	/*
> +	 * at least 100ms delay because PCIe v2.0 need more time to
> +	 * train from Gen1 to Gen2
> +	 */
> +	msleep(100);
> +}
> +
> +static int mtk_pcie_enable_ports(struct mtk_pcie *pcie)
> +{
> +	struct device *dev = pcie->dev;
> +	struct mtk_pcie_port *port, *tmp;
> +	int err, linkup = 0;
> +
> +	list_for_each_entry_safe(port, tmp, &pcie->ports, list) {
> +		err = clk_prepare_enable(port->sys_ck);
> +		if (err) {
> +			dev_err(dev, "failed to enable port%d clock\n",
> +				port->index);
> +			continue;
> +		}
> +
> +		/* assert RC */
> +		reset_control_assert(port->reset);
> +		/* de-assert RC */
> +		reset_control_deassert(port->reset);
> +
> +		/* power on PHY */
> +		err = phy_power_on(port->phy);
> +		if (err) {
> +			dev_err(dev, "failed to power on port%d phy\n",
> +				port->index);
> +			goto err_phy_on;
> +		}
> +
> +		mtk_pcie_assert_ports(port);
> +
> +		/* if link up, then setup root port configuration space */
> +		if (mtk_pcie_link_is_up(port)) {
> +			mtk_pcie_configure_rc(port);
> +			linkup++;
> +			continue;
> +		}
> +
> +		dev_info(dev, "Port%d link down\n", port->index);
> +
> +		phy_power_off(port->phy);
> +err_phy_on:
> +		clk_disable_unprepare(port->sys_ck);
> +		mtk_pcie_port_free(port);
> +	}
> +
> +	return linkup;
> +}
> +
> +static int mtk_pcie_get_port_resource(struct mtk_pcie_port *port,
> +				      struct device_node *node)
> +{
> +	struct device *dev = port->pcie->dev;
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct platform_device *plat_dev;
> +	char name[10];
> +	int err;
> +
> +	err = of_address_to_resource(node, 0, &port->regs);
> +	if (err) {
> +		dev_err(dev, "failed to parse address: %d\n", err);
> +		return err;
> +	}
> +
> +	port->base = devm_ioremap_resource(dev, &port->regs);
> +	if (IS_ERR(port->base)) {
> +		dev_err(dev, "failed to map port%d base\n", port->index);
> +		return PTR_ERR(port->base);
> +	}
> +
> +	plat_dev = of_find_device_by_node(node);
> +	if (!plat_dev) {
> +		plat_dev = of_platform_device_create(
> +					node, NULL,
> +					platform_bus_type.dev_root);
> +		if (!plat_dev)
> +			return -EPROBE_DEFER;
> +	}
> +
> +	port->dev = &plat_dev->dev;
> +
> +	port->irq = platform_get_irq(pdev, port->index);
> +	if (!port->irq) {
> +		dev_err(dev, "failed to get irq\n");
> +		return -ENODEV;
> +	}
> +
> +	port->sys_ck = devm_clk_get(port->dev, "sys_ck");
> +	if (IS_ERR(port->sys_ck)) {
> +		dev_err(port->dev, "failed to get port%d clock\n", port->index);
> +		return PTR_ERR(port->sys_ck);
> +	}
> +
> +	port->reset = devm_reset_control_get(port->dev, "pcie-reset");
> +	if (IS_ERR(port->reset)) {
> +		dev_err(port->dev, "failed to get port%d reset control\n",
> +			port->index);
> +		return PTR_ERR(port->reset);
> +	}
> +
> +	snprintf(name, sizeof(name), "pcie-phy%d", port->index);
> +	port->phy = devm_of_phy_get(port->dev, node, name);
> +	if (IS_ERR(port->phy)) {
> +		dev_err(port->dev, "failed to get port%d phy\n", port->index);
> +		return PTR_ERR(port->phy);
> +	}
> +
> +	return 0;
> +}
> +
> +static int mtk_pcie_parse_and_add_res(struct mtk_pcie *pcie)
> +{
> +	struct device *dev = pcie->dev;
> +	struct platform_device *pdev = to_platform_device(dev);
> +	struct device_node *node = dev->of_node, *child;
> +	struct resource_entry *win, *tmp;
> +	struct resource *regs;
> +	resource_size_t iobase;
> +	int err;
> +
> +	/* parse shared resources */
> +	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	pcie->base = devm_ioremap_resource(dev, regs);
> +	if (IS_ERR(pcie->base)) {
> +		dev_err(dev, "failed to get PCIe base\n");
> +		return PTR_ERR(pcie->base);
> +	}
> +
> +	pcie->free_ck = devm_clk_get(dev, "free_ck");
> +	if (IS_ERR(pcie->free_ck)) {
> +		dev_err(dev, "failed to get free_ck\n");
> +		return PTR_ERR(pcie->free_ck);
> +	}
> +
> +	err = of_pci_get_host_bridge_resources(node, 0, 0xff, &pcie->resources,
> +					       &iobase);
> +	if (err)
> +		return err;
> +
> +	err = devm_request_pci_bus_resources(dev, &pcie->resources);
> +	if (err)
> +		return err;
> +
> +	resource_list_for_each_entry_safe(win, tmp, &pcie->resources) {
> +		struct resource *res = win->res;
> +
> +		switch (resource_type(res)) {
> +		case IORESOURCE_IO:
> +			err = pci_remap_iospace(res, iobase);
> +			if (err) {
> +				dev_warn(dev, "failed to map resource %pR\n",
> +					 res);
> +				resource_list_destroy_entry(win);
> +			}
> +			break;
> +		}
> +	}
> +
> +	/* parse port resources */
> +	for_each_child_of_node(node, child) {
> +		struct mtk_pcie_port *port;
> +		int index;
> +
> +		err = of_pci_get_devfn(child);
> +		if (err < 0) {
> +			dev_err(pcie->dev, "failed to parse devfn: %d\n", err);

dev_err(dev, ...)

> +			return err;
> +		}
> +
> +		index = PCI_SLOT(err);
> +		if (index < 1) {
> +			dev_err(dev, "invalid port number: %d\n", index);
> +			return -EINVAL;
> +		}
> +
> +		index--;
> +
> +		if (!of_device_is_available(child))
> +			continue;
> +
> +		port = devm_kzalloc(dev, sizeof(*port), GFP_KERNEL);
> +		if (!port)
> +			return -ENOMEM;
> +
> +		err = of_property_read_u32(child, "num-lanes", &port->lane);
> +		if (err) {
> +			dev_err(dev, "missing num-lanes property\n");
> +			return err;
> +		}
> +
> +		port->index = index;
> +		port->pcie = pcie;
> +
> +		err = mtk_pcie_get_port_resource(port, child);
> +		if (err)
> +			return err;
> +
> +		INIT_LIST_HEAD(&port->list);
> +		list_add_tail(&port->list, &pcie->ports);
> +	}
> +
> +	return 0;
> +}
> +
> +/*
> + * This IP lacks interrupt status register to check or map INTx from
> + * different devices at the same time.
> + */
> +static int __init mtk_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> +{
> +	struct mtk_pcie *pcie = dev->bus->sysdata;
> +	struct mtk_pcie_port *port;
> +
> +	list_for_each_entry(port, &pcie->ports, list)
> +		if (port->index == slot)
> +			return port->irq;
> +
> +	return -1;
> +}
> +
> +static int mtk_pcie_register_ports(struct mtk_pcie *pcie)
> +{
> +	struct pci_bus *bus, *child;
> +
> +	bus = pci_scan_root_bus(pcie->dev, 0, &mtk_pcie_ops, pcie,
> +				&pcie->resources);
> +	if (!bus) {
> +		dev_err(pcie->dev, "failed to create root bus\n");
> +		return -ENOMEM;
> +	}
> +
> +	if (!pci_has_flag(PCI_PROBE_ONLY)) {
> +		pci_fixup_irqs(pci_common_swizzle, mtk_pcie_map_irq);
> +		pci_bus_size_bridges(bus);
> +		pci_bus_assign_resources(bus);
> +
> +		list_for_each_entry(child, &bus->children, node)
> +			pcie_bus_configure_settings(child);

Do you actually need the functionality of PCI_PROBE_ONLY?  We're
trying to get rid of this, so if you don't need it, please omit it.

If you *do* need it, can you include a note about why?

If you do need it, I don't think PCI_PROBE_ONLY should control
pci_fixup_irqs() or pcie_bus_configure_settings().  I know there is
some other similar code that does this, but I think PCI_PROBE_ONLY
should only influence resource assignment, i.e., BARs and bridge
windows.  I don't want it to influence IRQs or the MPS/MRRS settings
done by pcie_bus_configure_settings() if we can avoid it.

> +	}
> +
> +	pci_bus_add_devices(bus);
> +
> +	return 0;
> +}
> +
> +static int mtk_pcie_probe(struct platform_device *pdev)
> +{
> +	struct mtk_pcie *pcie;
> +	int err;
> +
> +	pcie = devm_kzalloc(&pdev->dev, sizeof(*pcie), GFP_KERNEL);
> +	if (!pcie)
> +		return -ENOMEM;
> +
> +	pcie->dev = &pdev->dev;
> +	platform_set_drvdata(pdev, pcie);
> +
> +	/*
> +	 * parse PCI ranges, configuration bus range and
> +	 * request their resources
> +	 */
> +	INIT_LIST_HEAD(&pcie->ports);
> +	INIT_LIST_HEAD(&pcie->resources);
> +
> +	err = mtk_pcie_parse_and_add_res(pcie);
> +	if (err)
> +		goto err_parse;
> +
> +	pm_runtime_enable(pcie->dev);
> +	err = pm_runtime_get_sync(pcie->dev);
> +	if (err)
> +		goto err_pm;
> +
> +	err = clk_prepare_enable(pcie->free_ck);
> +	if (err) {
> +		dev_err(pcie->dev, "failed to enable free_ck\n");
> +		goto err_free_ck;
> +	}
> +
> +	/* power on PCIe ports */
> +	err = mtk_pcie_enable_ports(pcie);
> +	if (!err)
> +		goto err_enable;
> +
> +	/* register PCIe ports */
> +	err = mtk_pcie_register_ports(pcie);
> +	if (err)
> +		goto err_enable;
> +
> +	return 0;
> +
> +err_enable:
> +	clk_disable_unprepare(pcie->free_ck);
> +err_free_ck:
> +	pm_runtime_put_sync(pcie->dev);
> +err_pm:
> +	pm_runtime_disable(pcie->dev);
> +err_parse:
> +	pci_free_resource_list(&pcie->resources);
> +
> +	return err;
> +}
> +
> +static const struct of_device_id mtk_pcie_ids[] = {
> +	{ .compatible = "mediatek,mt7623-pcie"},
> +	{ .compatible = "mediatek,mt2701-pcie"},
> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, mtk_pcie_ids);
> +
> +static struct platform_driver mtk_pcie_driver = {
> +	.probe = mtk_pcie_probe,
> +	.driver = {
> +		.name = "mtk-pcie",
> +		.of_match_table = mtk_pcie_ids,

Per [1], I think you should have ".suppress_bind_attrs = true," here.
Without it, apparently you can easily crash the system by unbinding
the driver, as in [2].

[1] https://git.kernel.org/cgit/linux/kernel/git/helgaas/pci.git/commit/?id=65e0527b933a
[2] https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git/commit/?id=073d3dbe9a7c

> +	},
> +};
> +
> +builtin_platform_driver(mtk_pcie_driver);
> +
> +MODULE_DESCRIPTION("Mediatek PCIe host driver for MT7623 SoCs families");
> +MODULE_LICENSE("GPL v2");
> -- 
> 1.9.1
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 2/2] ARM: dts: Add the ethernet and ethernet PHY to the cygnus core DT.
From: Florian Fainelli @ 2017-04-24 21:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20170424215022.30382-3-eric@anholt.net>

On 04/24/2017 02:50 PM, Eric Anholt wrote:
> Cygnus has a single amac controller connected to the B53 switch with 2
> PHYs.  On the BCM911360_EP platform, those two PHYs are connected to
> the external ethernet jacks.
> 
> Signed-off-by: Eric Anholt <eric@anholt.net>

This looks fine, just a few nits on the label names:

> ---
>  arch/arm/boot/dts/bcm-cygnus.dtsi      | 60 ++++++++++++++++++++++++++++++++++
>  arch/arm/boot/dts/bcm911360_entphn.dts |  8 +++++
>  2 files changed, 68 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/bcm-cygnus.dtsi b/arch/arm/boot/dts/bcm-cygnus.dtsi
> index 009f1346b817..318899df9972 100644
> --- a/arch/arm/boot/dts/bcm-cygnus.dtsi
> +++ b/arch/arm/boot/dts/bcm-cygnus.dtsi
> @@ -142,6 +142,56 @@
>  			interrupts = <0>;
>  		};
>  
> +		mdio: mdio at 18002000 {
> +			compatible = "brcm,iproc-mdio";
> +			reg = <0x18002000 0x8>;
> +			#size-cells = <1>;
> +			#address-cells = <0>;
> +
> +			gphy0: eth-gphy at 0 {
> +				reg = <0>;
> +				max-speed = <1000>;
> +			};
> +
> +			gphy1: eth-gphy at 1 {
> +				reg = <1>;
> +				max-speed = <1000>;
> +			};
> +		};
> +
> +		dsa: dsa at 18007000 {

This would be better named switch: switch at 18007000

> +			compatible = "brcm,bcm11360-srab", "brcm,cygnus-srab";
> +			reg = <0x18007000 0x1000>;
> +			status = "disabled";
> +
> +			ports {
> +				#address-cells = <1>;
> +				#size-cells = <0>;
> +
> +				port0 at 0 {

You can probably just put port at 0

> +					reg = <0>;
> +					phy-handle = <&gphy0>;
> +					phy-mode = "rgmii";
> +				};
> +
> +				port1 at 1 {

And so on

> +					reg = <1>;
> +					phy-handle = <&gphy1>;
> +					phy-mode = "rgmii";
> +				};
> +
> +				port8 at 8 {

And so forth

> +					reg = <8>;
> +					label = "cpu";
> +					ethernet = <&eth0>;
> +					fixed-link {
> +						speed = <1000>;
> +						full-duplex;
> +					};
> +				};
> +			};
> +		};
> +
>  		i2c0: i2c at 18008000 {
>  			compatible = "brcm,cygnus-iproc-i2c", "brcm,iproc-i2c";
>  			reg = <0x18008000 0x100>;
> @@ -295,6 +345,16 @@
>  			status = "disabled";
>  		};
>  
> +		eth0: enet at 18042000 {
> +			compatible = "brcm,amac";
> +			reg = <0x18042000 0x1000>,
> +			      <0x18110000 0x1000>;
> +			reg-names = "amac_base", "idm_base";
> +			interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
> +			max-speed = <1000>;
> +			status = "disabled";
> +		};
> +
>  		nand: nand at 18046000 {
>  			compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1";
>  			reg = <0x18046000 0x600>, <0xf8105408 0x600>,
> diff --git a/arch/arm/boot/dts/bcm911360_entphn.dts b/arch/arm/boot/dts/bcm911360_entphn.dts
> index 8b3800f46288..2a1f54ab3574 100644
> --- a/arch/arm/boot/dts/bcm911360_entphn.dts
> +++ b/arch/arm/boot/dts/bcm911360_entphn.dts
> @@ -57,6 +57,14 @@
>  	};
>  };
>  
> +&dsa {
> +	status = "okay";
> +};

And that would be &switch here then.

With that fixed:

Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>

> +
> +&eth0 {
> +	status = "okay";
> +};
> +
>  &uart3 {
>  	status = "okay";
>  };
> 


-- 
Florian

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox