* [PATCH v13 06/15] irqchip/gic-v2m: Register the MSI doorbell
From: Eric Auger @ 2016-10-06 8:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475743531-4780-1-git-send-email-eric.auger@redhat.com>
Register the GIC V2M global doorbell. The registered information
are used to set up the KVM passthrough use case.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v12 -> v13:
- use new msi doorbell registration prototype
- remove iommu protection attributes
- add unregistration in teardown
v11 -> v12:
- use irq_get_msi_doorbell_info new name
- simplify error handling
v10 -> v11:
- use the new registration API and re-implement the msi_doorbell_info
ops
v9 -> v10:
- introduce the registration concept in place of msi_doorbell_info
callback
v8 -> v9:
- use global_doorbell instead of percpu_doorbells
v7 -> v8:
- gicv2m_msi_doorbell_info does not return a pointer to const
- remove spurious !v2m check
- add IOMMU_MMIO flag
v7: creation
---
drivers/irqchip/irq-gic-v2m.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/irqchip/irq-gic-v2m.c b/drivers/irqchip/irq-gic-v2m.c
index 863e073..343f19f 100644
--- a/drivers/irqchip/irq-gic-v2m.c
+++ b/drivers/irqchip/irq-gic-v2m.c
@@ -26,6 +26,7 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/irqchip/arm-gic.h>
+#include <linux/msi-doorbell.h>
/*
* MSI_TYPER:
@@ -70,6 +71,7 @@ struct v2m_data {
u32 spi_offset; /* offset to be subtracted from SPI number */
unsigned long *bm; /* MSI vector bitmap */
u32 flags; /* v2m flags for specific implementation */
+ struct msi_doorbell_info *doorbell_info; /* MSI doorbell */
};
static void gicv2m_mask_msi_irq(struct irq_data *d)
@@ -254,6 +256,7 @@ static void gicv2m_teardown(void)
struct v2m_data *v2m, *tmp;
list_for_each_entry_safe(v2m, tmp, &v2m_nodes, entry) {
+ msi_doorbell_unregister_global(v2m->doorbell_info);
list_del(&v2m->entry);
kfree(v2m->bm);
iounmap(v2m->base);
@@ -370,12 +373,18 @@ static int __init gicv2m_init_one(struct fwnode_handle *fwnode,
goto err_iounmap;
}
+ ret = msi_doorbell_register_global(v2m->res.start, sizeof(u32),
+ false, &v2m->doorbell_info);
+ if (ret)
+ goto err_free_bm;
+
list_add_tail(&v2m->entry, &v2m_nodes);
pr_info("range%pR, SPI[%d:%d]\n", res,
v2m->spi_start, (v2m->spi_start + v2m->nr_spis - 1));
return 0;
-
+err_free_bm:
+ kfree(v2m->bm);
err_iounmap:
iounmap(v2m->base);
err_free_v2m:
--
1.9.1
^ permalink raw reply related
* [PATCH v13 05/15] genirq/msi: msi_doorbell_calc_pages
From: Eric Auger @ 2016-10-06 8:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475743531-4780-1-git-send-email-eric.auger@redhat.com>
msi_doorbell_calc_pages() sum up the number of iommu pages of a given order
requested to map all the registered doorbells. This function will allow
to dimension the intermediate physical address (IPA) aperture requested
to map the MSI doorbells.
Note this requirement cannot be computed at MSI doorbell registration time
since the IOMMU page order is not known.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v11 -> v12:
- fix style issues: remove useless line break, remove pointless braces,
fix kernel-doc comments
- reword commit message
- rename msi_doorbell_pages into msi_doorbell_calc_pages
- rename static compute* functions
v10: creation
---
include/linux/msi-doorbell.h | 15 +++++++++++
kernel/irq/msi-doorbell.c | 64 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
diff --git a/include/linux/msi-doorbell.h b/include/linux/msi-doorbell.h
index c18a382..f1106cb 100644
--- a/include/linux/msi-doorbell.h
+++ b/include/linux/msi-doorbell.h
@@ -54,6 +54,15 @@ void msi_doorbell_unregister_global(struct msi_doorbell_info *db);
*/
bool msi_doorbell_safe(void);
+/**
+ * msi_doorbell_calc_pages - compute the number of pages
+ * requested to map all the registered doorbells
+ * @order: iommu page order
+ *
+ * Return: the number of requested pages
+ */
+int msi_doorbell_calc_pages(unsigned int order);
+
#else
static inline int
@@ -72,6 +81,12 @@ static inline bool msi_doorbell_safe(void)
{
return true;
}
+
+static inline int msi_doorbell_calc_pages(unsigned int order)
+{
+ return 0;
+}
+
#endif /* CONFIG_MSI_DOORBELL */
#endif
diff --git a/kernel/irq/msi-doorbell.c b/kernel/irq/msi-doorbell.c
index 60a262a..d1cc525 100644
--- a/kernel/irq/msi-doorbell.c
+++ b/kernel/irq/msi-doorbell.c
@@ -96,3 +96,67 @@ bool msi_doorbell_safe(void)
return !nb_unsafe_doorbells;
}
EXPORT_SYMBOL_GPL(msi_doorbell_safe);
+
+/**
+ * calc_region_reqs - compute the number of pages requested to map a region
+ *
+ * @addr: physical base address of the region
+ * @size: size of the region
+ * @order: the page order
+ *
+ * Return: the number of requested pages to map this region
+ */
+static int calc_region_reqs(phys_addr_t addr, size_t size, unsigned int order)
+{
+ phys_addr_t offset, granule;
+ unsigned int nb_pages;
+
+ granule = (uint64_t)(1 << order);
+ offset = addr & (granule - 1);
+ size = ALIGN(size + offset, granule);
+ nb_pages = size >> order;
+
+ return nb_pages;
+}
+
+/**
+ * calc_dbinfo_reqs - compute the number of pages requested to map a given
+ * MSI doorbell
+ *
+ * @dbi: doorbell info descriptor
+ * @order: page order
+ *
+ * Return: the number of requested pages to map this doorbell
+ */
+static int calc_dbinfo_reqs(struct msi_doorbell_info *dbi, unsigned int order)
+{
+ int ret = 0;
+
+ if (!dbi->doorbell_is_percpu) {
+ ret = calc_region_reqs(dbi->global_doorbell, dbi->size, order);
+ } else {
+ phys_addr_t __percpu *pbase;
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+ pbase = per_cpu_ptr(dbi->percpu_doorbells, cpu);
+ ret += calc_region_reqs(*pbase, dbi->size, order);
+ }
+ }
+ return ret;
+}
+
+int msi_doorbell_calc_pages(unsigned int order)
+{
+ struct msi_doorbell *db;
+ int ret = 0;
+
+ mutex_lock(&msi_doorbell_mutex);
+ list_for_each_entry(db, &msi_doorbell_list, next)
+ ret += calc_dbinfo_reqs(&db->info, order);
+
+ mutex_unlock(&msi_doorbell_mutex);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(msi_doorbell_calc_pages);
--
1.9.1
^ permalink raw reply related
* [PATCH v13 04/15] genirq/msi: Introduce the MSI doorbell API
From: Eric Auger @ 2016-10-06 8:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475743531-4780-1-git-send-email-eric.auger@redhat.com>
We introduce a new msi-doorbell API that allows msi controllers
to allocate and register their doorbells. This is useful when
those doorbells are likely to be iommu mapped (typically on ARM).
The VFIO layer will need to gather information about those doorbells:
whether they are safe (ie. they implement irq remapping) and how
many IOMMU pages are requested to map all of them.
This patch first introduces the dedicated msi_doorbell_info struct
and the registration/unregistration functions.
A doorbell region is characterized by its physical address base, size,
and whether it its safe (ie. it implements IRQ remapping). A doorbell
can be per-cpu of global. We currently only care about global doorbells.
A function returns whether all doorbells are safe.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v12 -> v13:
- directly select MSI_DOORBELL in ARM_SMMU and ARM_SMMU_V3 configs
- remove prot attribute
- move msi_doorbell_info struct definition in msi-doorbell.c
- change the commit title
- change proto of the registration function
- msi_doorbell_safe now in this patch
v11 -> v12:
- rename irqchip_doorbell into msi_doorbell, irqchip_doorbell_list
into msi_doorbell_list and irqchip_doorbell_mutex into
msi_doorbell_mutex
- fix style issues: align msi_doorbell struct members, kernel-doc comments
- use kzalloc
- use container_of in msi_doorbell_unregister_global
- compute nb_unsafe_doorbells on registration/unregistration
- registration simply returns NULL if allocation failed
v10 -> v11:
- remove void *chip_data argument from register/unregister function
- remove lookup funtions since we restored the struct irq_chip
msi_doorbell_info ops to realize this function
- reword commit message and title
Conflicts:
kernel/irq/Makefile
Conflicts:
drivers/iommu/Kconfig
---
drivers/iommu/Kconfig | 2 +
include/linux/msi-doorbell.h | 77 ++++++++++++++++++++++++++++++++++
kernel/irq/Kconfig | 4 ++
kernel/irq/Makefile | 1 +
kernel/irq/msi-doorbell.c | 98 ++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 182 insertions(+)
create mode 100644 include/linux/msi-doorbell.h
create mode 100644 kernel/irq/msi-doorbell.c
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 8ee54d7..0cc7fac 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -297,6 +297,7 @@ config SPAPR_TCE_IOMMU
config ARM_SMMU
bool "ARM Ltd. System MMU (SMMU) Support"
depends on (ARM64 || ARM) && MMU
+ select MSI_DOORBELL
select IOMMU_API
select IOMMU_IO_PGTABLE_LPAE
select ARM_DMA_USE_IOMMU if ARM
@@ -310,6 +311,7 @@ config ARM_SMMU
config ARM_SMMU_V3
bool "ARM Ltd. System MMU Version 3 (SMMUv3) Support"
depends on ARM64
+ select MSI_DOORBELL
select IOMMU_API
select IOMMU_IO_PGTABLE_LPAE
select GENERIC_MSI_IRQ_DOMAIN
diff --git a/include/linux/msi-doorbell.h b/include/linux/msi-doorbell.h
new file mode 100644
index 0000000..c18a382
--- /dev/null
+++ b/include/linux/msi-doorbell.h
@@ -0,0 +1,77 @@
+/*
+ * API to register/query MSI doorbells likely to be IOMMU mapped
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _LINUX_MSI_DOORBELL_H
+#define _LINUX_MSI_DOORBELL_H
+
+struct msi_doorbell_info;
+
+#ifdef CONFIG_MSI_DOORBELL
+
+/**
+ * msi_doorbell_register - allocate and register a global doorbell
+ * @base: physical base address of the global doorbell
+ * @size: size of the global doorbell
+ * @prot: protection/memory attributes
+ * @safe: true is irq_remapping implemented for this doorbell
+ * @dbinfo: returned doorbell info
+ *
+ * Return: 0 on success, -ENOMEM on allocation failure
+ */
+int msi_doorbell_register_global(phys_addr_t base, size_t size,
+ bool safe,
+ struct msi_doorbell_info **dbinfo);
+
+/**
+ * msi_doorbell_unregister_global - unregister a global doorbell
+ * @db: doorbell info to unregister
+ *
+ * remove the doorbell descriptor from the list of registered doorbells
+ * and deallocates it
+ */
+void msi_doorbell_unregister_global(struct msi_doorbell_info *db);
+
+/**
+ * msi_doorbell_safe - return whether all registered doorbells are safe
+ *
+ * Safe doorbells are those which implement irq remapping
+ * Return: true if all doorbells are safe, false otherwise
+ */
+bool msi_doorbell_safe(void);
+
+#else
+
+static inline int
+msi_doorbell_register_global(phys_addr_t base, size_t size,
+ int prot, bool safe,
+ struct msi_doorbell_info **dbinfo)
+{
+ *dbinfo = NULL;
+ return 0;
+}
+
+static inline void
+msi_doorbell_unregister_global(struct msi_doorbell_info *db) {}
+
+static inline bool msi_doorbell_safe(void)
+{
+ return true;
+}
+#endif /* CONFIG_MSI_DOORBELL */
+
+#endif
diff --git a/kernel/irq/Kconfig b/kernel/irq/Kconfig
index 3bbfd6a..d4faaaa 100644
--- a/kernel/irq/Kconfig
+++ b/kernel/irq/Kconfig
@@ -72,6 +72,10 @@ config GENERIC_IRQ_IPI
config GENERIC_MSI_IRQ
bool
+# MSI doorbell support (for doorbell IOMMU mapping)
+config MSI_DOORBELL
+ bool
+
# Generic MSI hierarchical interrupt domain support
config GENERIC_MSI_IRQ_DOMAIN
bool
diff --git a/kernel/irq/Makefile b/kernel/irq/Makefile
index 1d3ee31..5b04dd1 100644
--- a/kernel/irq/Makefile
+++ b/kernel/irq/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_PM_SLEEP) += pm.o
obj-$(CONFIG_GENERIC_MSI_IRQ) += msi.o
obj-$(CONFIG_GENERIC_IRQ_IPI) += ipi.o
obj-$(CONFIG_SMP) += affinity.o
+obj-$(CONFIG_MSI_DOORBELL) += msi-doorbell.o
diff --git a/kernel/irq/msi-doorbell.c b/kernel/irq/msi-doorbell.c
new file mode 100644
index 0000000..60a262a
--- /dev/null
+++ b/kernel/irq/msi-doorbell.c
@@ -0,0 +1,98 @@
+/*
+ * API to register/query MSI doorbells likely to be IOMMU mapped
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ * Author: Eric Auger <eric.auger@redhat.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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/msi-doorbell.h>
+
+/**
+ * struct msi_doorbell_info - MSI doorbell region descriptor
+ * @percpu_doorbells: per cpu doorbell base address
+ * @global_doorbell: base address of the doorbell
+ * @doorbell_is_percpu: is the doorbell per cpu or global?
+ * @safe: true if irq remapping is implemented
+ * @size: size of the doorbell
+ */
+struct msi_doorbell_info {
+ union {
+ phys_addr_t __percpu *percpu_doorbells;
+ phys_addr_t global_doorbell;
+ };
+ bool doorbell_is_percpu;
+ bool safe;
+ size_t size;
+};
+
+struct msi_doorbell {
+ struct msi_doorbell_info info;
+ struct list_head next;
+};
+
+/* list of registered MSI doorbells */
+static LIST_HEAD(msi_doorbell_list);
+
+/* counts the number of unsafe registered doorbells */
+static uint nb_unsafe_doorbells;
+
+/* protects the list and nb__unsafe_doorbells */
+static DEFINE_MUTEX(msi_doorbell_mutex);
+
+int msi_doorbell_register_global(phys_addr_t base, size_t size, bool safe,
+ struct msi_doorbell_info **dbinfo)
+{
+ struct msi_doorbell *db;
+
+ db = kzalloc(sizeof(*db), GFP_KERNEL);
+ if (!db)
+ return -ENOMEM;
+
+ db->info.global_doorbell = base;
+ db->info.size = size;
+ db->info.safe = safe;
+
+ mutex_lock(&msi_doorbell_mutex);
+ list_add(&db->next, &msi_doorbell_list);
+ if (!db->info.safe)
+ nb_unsafe_doorbells++;
+ mutex_unlock(&msi_doorbell_mutex);
+ *dbinfo = &db->info;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(msi_doorbell_register_global);
+
+void msi_doorbell_unregister_global(struct msi_doorbell_info *dbinfo)
+{
+ struct msi_doorbell *db;
+
+ db = container_of(dbinfo, struct msi_doorbell, info);
+
+ mutex_lock(&msi_doorbell_mutex);
+ list_del(&db->next);
+ if (!db->info.safe)
+ nb_unsafe_doorbells--;
+ mutex_unlock(&msi_doorbell_mutex);
+ kfree(db);
+}
+EXPORT_SYMBOL_GPL(msi_doorbell_unregister_global);
+
+bool msi_doorbell_safe(void)
+{
+ return !nb_unsafe_doorbells;
+}
+EXPORT_SYMBOL_GPL(msi_doorbell_safe);
--
1.9.1
^ permalink raw reply related
* [PATCH v13 03/15] iommu/dma: Allow MSI-only cookies
From: Eric Auger @ 2016-10-06 8:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475743531-4780-1-git-send-email-eric.auger@redhat.com>
From: Robin Murphy <robin.murphy@arm.com>
IOMMU domain users such as VFIO face a similar problem to DMA API ops
with regard to mapping MSI messages in systems where the MSI write is
subject to IOMMU translation. With the relevant infrastructure now in
place for managed DMA domains, it's actually really simple for other
users to piggyback off that and reap the benefits without giving up
their own IOVA management, and without having to reinvent their own
wheel in the MSI layer.
Allow such users to opt into automatic MSI remapping by dedicating a
region of their IOVA space to a managed cookie.
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v1 -> v2:
- compared to Robin's version
- add NULL last param to iommu_dma_init_domain
- set the msi_geometry aperture
- I removed
if (base < U64_MAX - size)
reserve_iova(iovad, iova_pfn(iovad, base + size), ULONG_MAX);
don't get why we would reserve something out of the scope of the iova domain?
what do I miss?
---
drivers/iommu/dma-iommu.c | 40 ++++++++++++++++++++++++++++++++++++++++
include/linux/dma-iommu.h | 9 +++++++++
2 files changed, 49 insertions(+)
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index c5ab866..11da1a0 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -716,3 +716,43 @@ void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
msg->address_lo += lower_32_bits(msi_page->iova);
}
}
+
+/**
+ * iommu_get_dma_msi_region_cookie - Configure a domain for MSI remapping only
+ * @domain: IOMMU domain to prepare
+ * @base: Base address of IOVA region to use as the MSI remapping aperture
+ * @size: Size of the desired MSI aperture
+ *
+ * Users who manage their own IOVA allocation and do not want DMA API support,
+ * but would still like to take advantage of automatic MSI remapping, can use
+ * this to initialise their own domain appropriately.
+ */
+int iommu_get_dma_msi_region_cookie(struct iommu_domain *domain,
+ dma_addr_t base, u64 size)
+{
+ struct iommu_dma_cookie *cookie;
+ struct iova_domain *iovad;
+ int ret;
+
+ if (domain->type == IOMMU_DOMAIN_DMA)
+ return -EINVAL;
+
+ ret = iommu_get_dma_cookie(domain);
+ if (ret)
+ return ret;
+
+ ret = iommu_dma_init_domain(domain, base, size, NULL);
+ if (ret) {
+ iommu_put_dma_cookie(domain);
+ return ret;
+ }
+
+ domain->msi_geometry.aperture_start = base;
+ domain->msi_geometry.aperture_end = base + size - 1;
+
+ cookie = domain->iova_cookie;
+ iovad = &cookie->iovad;
+
+ return 0;
+}
+EXPORT_SYMBOL(iommu_get_dma_msi_region_cookie);
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 32c5890..1c55413 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -67,6 +67,9 @@ int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
/* The DMA API isn't _quite_ the whole story, though... */
void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
+int iommu_get_dma_msi_region_cookie(struct iommu_domain *domain,
+ dma_addr_t base, u64 size);
+
#else
struct iommu_domain;
@@ -90,6 +93,12 @@ static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
{
}
+static inline int iommu_get_dma_msi_region_cookie(struct iommu_domain *domain,
+ dma_addr_t base, u64 size)
+{
+ return -ENODEV;
+}
+
#endif /* CONFIG_IOMMU_DMA */
#endif /* __KERNEL__ */
#endif /* __DMA_IOMMU_H */
--
1.9.1
^ permalink raw reply related
* [PATCH v13 02/15] iommu/arm-smmu: Initialize the msi geometry
From: Eric Auger @ 2016-10-06 8:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475743531-4780-1-git-send-email-eric.auger@redhat.com>
On ARM, MSI write transactions also are translated by the smmu.
Let's report that specificity by setting the iommu_msi_supported
field to true. A valid aperture window will need to be provided.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
v12 -> v13:
- reword the commit message
v8 -> v9:
- reword the title and patch description
v7 -> v8:
- use DOMAIN_ATTR_MSI_GEOMETRY
v4 -> v5:
- don't handle fsl_pamu_domain anymore
- handle arm-smmu-v3
---
drivers/iommu/arm-smmu-v3.c | 2 ++
drivers/iommu/arm-smmu.c | 3 +++
2 files changed, 5 insertions(+)
diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 15c01c3..f82eec3 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1382,6 +1382,7 @@ static bool arm_smmu_capable(enum iommu_cap cap)
static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
{
struct arm_smmu_domain *smmu_domain;
+ struct iommu_domain_msi_geometry msi_geometry = {0, 0, true};
if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
return NULL;
@@ -1400,6 +1401,7 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
kfree(smmu_domain);
return NULL;
}
+ smmu_domain->domain.msi_geometry = msi_geometry;
mutex_init(&smmu_domain->init_mutex);
spin_lock_init(&smmu_domain->pgtbl_lock);
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index ac4aab9..97ff1b4 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1002,6 +1002,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
{
struct arm_smmu_domain *smmu_domain;
+ struct iommu_domain_msi_geometry msi_geometry = {0, 0, true};
if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
return NULL;
@@ -1020,6 +1021,8 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
return NULL;
}
+ smmu_domain->domain.msi_geometry = msi_geometry;
+
mutex_init(&smmu_domain->init_mutex);
spin_lock_init(&smmu_domain->pgtbl_lock);
--
1.9.1
^ permalink raw reply related
* [PATCH v13 01/15] iommu: Introduce DOMAIN_ATTR_MSI_GEOMETRY
From: Eric Auger @ 2016-10-06 8:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475743531-4780-1-git-send-email-eric.auger@redhat.com>
Introduce a new DOMAIN_ATTR_MSI_GEOMETRY domain attribute. It enables
to query the aperture of the IOVA window dedicated to MSIs and
test whether the MSIs must be IOMMU mapped.
x86 IOMMUs will typically expose an MSI aperture matching the 1MB
region [FEE0_0000h - FEF0_000h] corresponding to the the APIC
configuration space and no support for MSI IOMMU mapping.
On ARM, the requirement to map MSIs will be reported by setting
iommu_msi_supported to true.
A helper function is added to allow testing if the aperture is valid.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Suggested-by: Alex Williamson <alex.williamson@redhat.com>
---
v12 -> v13:
- reword the commit message
v8 -> v9:
- rename programmable into iommu_msi_supported
- add iommu_domain_msi_aperture_valid
v8: creation
- deprecates DOMAIN_ATTR_MSI_MAPPING flag
---
drivers/iommu/iommu.c | 5 +++++
include/linux/iommu.h | 14 ++++++++++++++
2 files changed, 19 insertions(+)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 9a2f196..617cb2b 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1485,6 +1485,7 @@ int iommu_domain_get_attr(struct iommu_domain *domain,
enum iommu_attr attr, void *data)
{
struct iommu_domain_geometry *geometry;
+ struct iommu_domain_msi_geometry *msi_geometry;
bool *paging;
int ret = 0;
u32 *count;
@@ -1495,6 +1496,10 @@ int iommu_domain_get_attr(struct iommu_domain *domain,
*geometry = domain->geometry;
break;
+ case DOMAIN_ATTR_MSI_GEOMETRY:
+ msi_geometry = data;
+ *msi_geometry = domain->msi_geometry;
+ break;
case DOMAIN_ATTR_PAGING:
paging = data;
*paging = (domain->pgsize_bitmap != 0UL);
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index 436dc21..9f90735 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -52,6 +52,12 @@ struct iommu_domain_geometry {
bool force_aperture; /* DMA only allowed in mappable range? */
};
+struct iommu_domain_msi_geometry {
+ dma_addr_t aperture_start; /* First address used for MSI IOVA */
+ dma_addr_t aperture_end; /* Last address used for MSI IOVA */
+ bool iommu_msi_supported; /* Is MSI mapping supported? */
+};
+
/* Domain feature flags */
#define __IOMMU_DOMAIN_PAGING (1U << 0) /* Support for iommu_map/unmap */
#define __IOMMU_DOMAIN_DMA_API (1U << 1) /* Domain for use in DMA-API
@@ -83,6 +89,7 @@ struct iommu_domain {
iommu_fault_handler_t handler;
void *handler_token;
struct iommu_domain_geometry geometry;
+ struct iommu_domain_msi_geometry msi_geometry;
void *iova_cookie;
};
@@ -108,6 +115,7 @@ enum iommu_cap {
enum iommu_attr {
DOMAIN_ATTR_GEOMETRY,
+ DOMAIN_ATTR_MSI_GEOMETRY,
DOMAIN_ATTR_PAGING,
DOMAIN_ATTR_WINDOWS,
DOMAIN_ATTR_FSL_PAMU_STASH,
@@ -352,6 +360,12 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
void iommu_fwspec_free(struct device *dev);
int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
+static inline bool iommu_domain_msi_aperture_valid(struct iommu_domain *domain)
+{
+ return (domain->msi_geometry.aperture_end >
+ domain->msi_geometry.aperture_start);
+}
+
#else /* CONFIG_IOMMU_API */
struct iommu_ops {};
--
1.9.1
^ permalink raw reply related
* [PATCH v13 00/15] KVM PCIe/MSI passthrough on ARM/ARM64
From: Eric Auger @ 2016-10-06 8:45 UTC (permalink / raw)
To: linux-arm-kernel
Following Robin's series [1], addressing MSI IOMMU mapping for devices
attached to a DMA ops domain, quite a lot of changes (and simplifications)
were induced with respect to the v12 iteration:
- msi-iommu API role now is handled at dma-iommu level
- MSI doorbell registration API still is used for security assessment
and doorbell overall iommu page size computation.
- MSI layer part II is not needed anymore since mapping directly is
done in the irqchip compose callback.
The VFIO user API and VFIO layer changes have not changed though. All the
patches now are in the same series.
Tested on AMD Overdrive (single GICv2m frame) with I350 VF assignment.
dependency:
the series depends on Robin's generic-v7 branch:
[1] [PATCH v7 00/22] Generic DT bindings for PCI IOMMUs and ARM SMMU
http://www.spinics.net/lists/arm-kernel/msg531110.html
Best Regards
Eric
Git: complete series available at
https://github.com/eauger/linux/tree/generic-v7-pcie-passthru-v13
the above branch includes a temporary patch to work around a ThunderX pci
bus reset crash (which I think unrelated to this series):
"vfio: pci: HACK! workaround thunderx pci_try_reset_bus crash"
Do not take this one for other platforms.
Eric Auger (14):
iommu: Introduce DOMAIN_ATTR_MSI_GEOMETRY
iommu/arm-smmu: Initialize the msi geometry
genirq/msi: Introduce the MSI doorbell API
genirq/msi: msi_doorbell_calc_pages
irqchip/gic-v2m: Register the MSI doorbell
irqchip/gicv3-its: Register the MSI doorbell
vfio: Introduce a vfio_dma type field
vfio/type1: vfio_find_dma accepting a type argument
vfio/type1: Implement recursive vfio_find_dma_from_node
vfio/type1: Handle unmap/unpin and replay for VFIO_IOVA_RESERVED slots
vfio: Allow reserved msi iova registration
vfio/type1: Check doorbell safety
iommu/arm-smmu: Do not advertise IOMMU_CAP_INTR_REMAP
vfio/type1: Return the MSI geometry through VFIO_IOMMU_GET_INFO
capability chains
Robin Murphy (1):
iommu/dma: Allow MSI-only cookies
drivers/iommu/Kconfig | 2 +
drivers/iommu/arm-smmu-v3.c | 5 +-
drivers/iommu/arm-smmu.c | 6 +-
drivers/iommu/dma-iommu.c | 40 +++++++
drivers/iommu/iommu.c | 5 +
drivers/irqchip/irq-gic-v2m.c | 11 +-
drivers/irqchip/irq-gic-v3-its.c | 14 +++
drivers/vfio/Kconfig | 1 +
drivers/vfio/vfio_iommu_type1.c | 244 ++++++++++++++++++++++++++++++++++++---
include/linux/dma-iommu.h | 9 ++
include/linux/iommu.h | 14 +++
include/linux/msi-doorbell.h | 92 +++++++++++++++
include/uapi/linux/vfio.h | 42 ++++++-
kernel/irq/Kconfig | 4 +
kernel/irq/Makefile | 1 +
kernel/irq/msi-doorbell.c | 162 ++++++++++++++++++++++++++
16 files changed, 633 insertions(+), 19 deletions(-)
create mode 100644 include/linux/msi-doorbell.h
create mode 100644 kernel/irq/msi-doorbell.c
--
1.9.1
^ permalink raw reply
* [PATCH 2/8] PM / Domain: Add residency property to genpd states
From: Ulf Hansson @ 2016-10-06 8:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475699519-109623-3-git-send-email-lina.iyer@linaro.org>
On 5 October 2016 at 22:31, Lina Iyer <lina.iyer@linaro.org> wrote:
> Residency of a domain's idle state indicates that the minimum idle time
> for the domain's idle state to be beneficial for power. Add the
> parameter to the state node. Future patches, will use the residency
> value in the genpd governor to determine if it is worth while to enter
> an idle state.
>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Kind regards
Uffe
> ---
> include/linux/pm_domain.h | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
> index bd1ffb9..c113713 100644
> --- a/include/linux/pm_domain.h
> +++ b/include/linux/pm_domain.h
> @@ -38,6 +38,7 @@ struct gpd_dev_ops {
> struct genpd_power_state {
> s64 power_off_latency_ns;
> s64 power_on_latency_ns;
> + s64 residency_ns;
> };
>
> struct generic_pm_domain {
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH 1/8] PM / Domains: Make genpd state allocation dynamic
From: Ulf Hansson @ 2016-10-06 8:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475699519-109623-2-git-send-email-lina.iyer@linaro.org>
On 5 October 2016 at 22:31, Lina Iyer <lina.iyer@linaro.org> wrote:
> Allow PM Domain states to be defined dynamically by the drivers. This
> removes the limitation on the maximum number of states possible for a
> domain.
>
> Cc: Axel Haslam <ahaslam+renesas@baylibre.com>
> Suggested-by: Ulf Hansson <ulf.hansson@linaro.org>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> ---
> arch/arm/mach-imx/gpc.c | 17 ++++++++++-------
> drivers/base/power/domain.c | 10 ----------
> include/linux/pm_domain.h | 4 +---
> 3 files changed, 11 insertions(+), 20 deletions(-)
>
> diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
> index 0df062d..b92dad5 100644
> --- a/arch/arm/mach-imx/gpc.c
> +++ b/arch/arm/mach-imx/gpc.c
> @@ -380,13 +380,6 @@ static struct pu_domain imx6q_pu_domain = {
> .name = "PU",
> .power_off = imx6q_pm_pu_power_off,
> .power_on = imx6q_pm_pu_power_on,
> - .states = {
> - [0] = {
> - .power_off_latency_ns = 25000,
> - .power_on_latency_ns = 2000000,
> - },
> - },
> - .state_count = 1,
> },
> };
>
> @@ -430,6 +423,16 @@ static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
> if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
> return 0;
>
> + imx6q_pu_domain.base.states = devm_kzalloc(dev,
> + sizeof(*imx6q_pu_domain.base.states),
> + GFP_KERNEL);
> + if (!imx6q_pu_domain.base.states)
> + return -ENOMEM;
> +
> + imx6q_pu_domain.base.states[0].power_off_latency_ns = 25000;
> + imx6q_pu_domain.base.states[0].power_on_latency_ns = 2000000;
> + mx6q_pu_domain.base.state_count = 1,
> +
> pm_genpd_init(&imx6q_pu_domain.base, NULL, false);
> return of_genpd_add_provider_onecell(dev->of_node,
> &imx_gpc_onecell_data);
> diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
> index e023066..740afa9 100644
> --- a/drivers/base/power/domain.c
> +++ b/drivers/base/power/domain.c
> @@ -1325,16 +1325,6 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
> genpd->dev_ops.start = pm_clk_resume;
> }
>
> - if (genpd->state_idx >= GENPD_MAX_NUM_STATES) {
> - pr_warn("Initial state index out of bounds.\n");
> - genpd->state_idx = GENPD_MAX_NUM_STATES - 1;
> - }
> -
> - if (genpd->state_count > GENPD_MAX_NUM_STATES) {
> - pr_warn("Limiting states to %d\n", GENPD_MAX_NUM_STATES);
> - genpd->state_count = GENPD_MAX_NUM_STATES;
> - }
> -
> /* Use only one "off" state if there were no states declared */
> if (genpd->state_count == 0)
> genpd->state_count = 1;
> diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h
> index a09fe5c..bd1ffb9 100644
> --- a/include/linux/pm_domain.h
> +++ b/include/linux/pm_domain.h
> @@ -19,8 +19,6 @@
> /* Defines used for the flags field in the struct generic_pm_domain */
> #define GENPD_FLAG_PM_CLK (1U << 0) /* PM domain uses PM clk */
>
> -#define GENPD_MAX_NUM_STATES 8 /* Number of possible low power states */
> -
> enum gpd_status {
> GPD_STATE_ACTIVE = 0, /* PM domain is active */
> GPD_STATE_POWER_OFF, /* PM domain is off */
> @@ -70,7 +68,7 @@ struct generic_pm_domain {
> void (*detach_dev)(struct generic_pm_domain *domain,
> struct device *dev);
> unsigned int flags; /* Bit field of configs for genpd */
> - struct genpd_power_state states[GENPD_MAX_NUM_STATES];
> + struct genpd_power_state *states;
> unsigned int state_count; /* number of states */
> unsigned int state_idx; /* state that genpd will go to when off */
>
> --
> 2.7.4
>
In general I like the improvement, but..
This change implies that ->states may very well be NULL. This isn't
validated by genpd's internal logic when power off/on the domain
(genpd_power_on|off(), __default_power_down_ok()). You need to fix
this, somehow.
Perhaps the easiest solutions is, when pm_genpd_init() finds that
->state is NULL, that we allocate a struct genpd_power_state with
array size of 1 and assign it to ->states. Although, doing this also
means you need to track that genpd was responsible for the the
allocation, so it must also free the data from within genpd_remove().
Unless you have other ideas!?
Kind regards
Uffe
^ permalink raw reply
* [PATCH 4.4 30/93] irqchip/gicv3: Silence noisy DEBUG_PER_CPU_MAPS warning
From: Greg Kroah-Hartman @ 2016-10-06 8:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161006074731.150212126@linuxfoundation.org>
4.4-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Morse <james.morse@arm.com>
commit 727653d6ce7103b245eb8041f55dd5885f4c3289 upstream.
gic_raise_softirq() walks the list of cpus using for_each_cpu(), it calls
gic_compute_target_list() which advances the iterator by the number of
CPUs in the cluster.
If gic_compute_target_list() reaches the last CPU it leaves the iterator
pointing at the last CPU. This means the next time round the for_each_cpu()
loop cpumask_next() will be called with an invalid CPU.
This triggers a warning when built with CONFIG_DEBUG_PER_CPU_MAPS:
[ 3.077738] GICv3: CPU1: found redistributor 1 region 0:0x000000002f120000
[ 3.077943] CPU1: Booted secondary processor [410fd0f0]
[ 3.078542] ------------[ cut here ]------------
[ 3.078746] WARNING: CPU: 1 PID: 0 at ../include/linux/cpumask.h:121 gic_raise_softirq+0x12c/0x170
[ 3.078812] Modules linked in:
[ 3.078869]
[ 3.078930] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 4.8.0-rc5+ #5188
[ 3.078994] Hardware name: Foundation-v8A (DT)
[ 3.079059] task: ffff80087a1a0080 task.stack: ffff80087a19c000
[ 3.079145] PC is at gic_raise_softirq+0x12c/0x170
[ 3.079226] LR is at gic_raise_softirq+0xa4/0x170
[ 3.079296] pc : [<ffff0000083ead24>] lr : [<ffff0000083eac9c>] pstate: 200001c9
[ 3.081139] Call trace:
[ 3.081202] Exception stack(0xffff80087a19fbe0 to 0xffff80087a19fd10)
[ 3.082269] [<ffff0000083ead24>] gic_raise_softirq+0x12c/0x170
[ 3.082354] [<ffff00000808e614>] smp_send_reschedule+0x34/0x40
[ 3.082433] [<ffff0000080e80a0>] resched_curr+0x50/0x88
[ 3.082512] [<ffff0000080e89d0>] check_preempt_curr+0x60/0xd0
[ 3.082593] [<ffff0000080e8a60>] ttwu_do_wakeup+0x20/0xe8
[ 3.082672] [<ffff0000080e8bb8>] ttwu_do_activate+0x90/0xc0
[ 3.082753] [<ffff0000080ea9a4>] try_to_wake_up+0x224/0x370
[ 3.082836] [<ffff0000080eabc8>] default_wake_function+0x10/0x18
[ 3.082920] [<ffff000008103134>] __wake_up_common+0x5c/0xa0
[ 3.083003] [<ffff0000081031f4>] __wake_up_locked+0x14/0x20
[ 3.083086] [<ffff000008103f80>] complete+0x40/0x60
[ 3.083168] [<ffff00000808df7c>] secondary_start_kernel+0x15c/0x1d0
[ 3.083240] [<00000000808911a4>] 0x808911a4
[ 3.113401] Detected PIPT I-cache on CPU2
Avoid updating the iterator if the next call to cpumask_next() would
cause the for_each_cpu() loop to exit.
There is no change to gic_raise_softirq()'s behaviour, (cpumask_next()s
eventual call to _find_next_bit() will return early as start >= nbits),
this patch just silences the warning.
Fixes: 021f653791ad ("irqchip: gic-v3: Initial support for GICv3")
Signed-off-by: James Morse <james.morse@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: Jason Cooper <jason@lakedaemon.net>
Link: http://lkml.kernel.org/r/1474306155-3303-1-git-send-email-james.morse at arm.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/irqchip/irq-gic-v3.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -544,7 +544,7 @@ static struct notifier_block gic_cpu_not
static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
unsigned long cluster_id)
{
- int cpu = *base_cpu;
+ int next_cpu, cpu = *base_cpu;
unsigned long mpidr = cpu_logical_map(cpu);
u16 tlist = 0;
@@ -558,9 +558,10 @@ static u16 gic_compute_target_list(int *
tlist |= 1 << (mpidr & 0xf);
- cpu = cpumask_next(cpu, mask);
- if (cpu >= nr_cpu_ids)
+ next_cpu = cpumask_next(cpu, mask);
+ if (next_cpu >= nr_cpu_ids)
goto out;
+ cpu = next_cpu;
mpidr = cpu_logical_map(cpu);
^ permalink raw reply
* [PATCH 4.7 050/141] irqchip/gicv3: Silence noisy DEBUG_PER_CPU_MAPS warning
From: Greg Kroah-Hartman @ 2016-10-06 8:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161006074448.608056610@linuxfoundation.org>
4.7-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Morse <james.morse@arm.com>
commit 727653d6ce7103b245eb8041f55dd5885f4c3289 upstream.
gic_raise_softirq() walks the list of cpus using for_each_cpu(), it calls
gic_compute_target_list() which advances the iterator by the number of
CPUs in the cluster.
If gic_compute_target_list() reaches the last CPU it leaves the iterator
pointing at the last CPU. This means the next time round the for_each_cpu()
loop cpumask_next() will be called with an invalid CPU.
This triggers a warning when built with CONFIG_DEBUG_PER_CPU_MAPS:
[ 3.077738] GICv3: CPU1: found redistributor 1 region 0:0x000000002f120000
[ 3.077943] CPU1: Booted secondary processor [410fd0f0]
[ 3.078542] ------------[ cut here ]------------
[ 3.078746] WARNING: CPU: 1 PID: 0 at ../include/linux/cpumask.h:121 gic_raise_softirq+0x12c/0x170
[ 3.078812] Modules linked in:
[ 3.078869]
[ 3.078930] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 4.8.0-rc5+ #5188
[ 3.078994] Hardware name: Foundation-v8A (DT)
[ 3.079059] task: ffff80087a1a0080 task.stack: ffff80087a19c000
[ 3.079145] PC is at gic_raise_softirq+0x12c/0x170
[ 3.079226] LR is at gic_raise_softirq+0xa4/0x170
[ 3.079296] pc : [<ffff0000083ead24>] lr : [<ffff0000083eac9c>] pstate: 200001c9
[ 3.081139] Call trace:
[ 3.081202] Exception stack(0xffff80087a19fbe0 to 0xffff80087a19fd10)
[ 3.082269] [<ffff0000083ead24>] gic_raise_softirq+0x12c/0x170
[ 3.082354] [<ffff00000808e614>] smp_send_reschedule+0x34/0x40
[ 3.082433] [<ffff0000080e80a0>] resched_curr+0x50/0x88
[ 3.082512] [<ffff0000080e89d0>] check_preempt_curr+0x60/0xd0
[ 3.082593] [<ffff0000080e8a60>] ttwu_do_wakeup+0x20/0xe8
[ 3.082672] [<ffff0000080e8bb8>] ttwu_do_activate+0x90/0xc0
[ 3.082753] [<ffff0000080ea9a4>] try_to_wake_up+0x224/0x370
[ 3.082836] [<ffff0000080eabc8>] default_wake_function+0x10/0x18
[ 3.082920] [<ffff000008103134>] __wake_up_common+0x5c/0xa0
[ 3.083003] [<ffff0000081031f4>] __wake_up_locked+0x14/0x20
[ 3.083086] [<ffff000008103f80>] complete+0x40/0x60
[ 3.083168] [<ffff00000808df7c>] secondary_start_kernel+0x15c/0x1d0
[ 3.083240] [<00000000808911a4>] 0x808911a4
[ 3.113401] Detected PIPT I-cache on CPU2
Avoid updating the iterator if the next call to cpumask_next() would
cause the for_each_cpu() loop to exit.
There is no change to gic_raise_softirq()'s behaviour, (cpumask_next()s
eventual call to _find_next_bit() will return early as start >= nbits),
this patch just silences the warning.
Fixes: 021f653791ad ("irqchip: gic-v3: Initial support for GICv3")
Signed-off-by: James Morse <james.morse@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Cc: linux-arm-kernel at lists.infradead.org
Cc: Jason Cooper <jason@lakedaemon.net>
Link: http://lkml.kernel.org/r/1474306155-3303-1-git-send-email-james.morse at arm.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
drivers/irqchip/irq-gic-v3.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -558,7 +558,7 @@ static struct notifier_block gic_cpu_not
static u16 gic_compute_target_list(int *base_cpu, const struct cpumask *mask,
unsigned long cluster_id)
{
- int cpu = *base_cpu;
+ int next_cpu, cpu = *base_cpu;
unsigned long mpidr = cpu_logical_map(cpu);
u16 tlist = 0;
@@ -572,9 +572,10 @@ static u16 gic_compute_target_list(int *
tlist |= 1 << (mpidr & 0xf);
- cpu = cpumask_next(cpu, mask);
- if (cpu >= nr_cpu_ids)
+ next_cpu = cpumask_next(cpu, mask);
+ if (next_cpu >= nr_cpu_ids)
goto out;
+ cpu = next_cpu;
mpidr = cpu_logical_map(cpu);
^ permalink raw reply
* [PATCH 2/3] gpio: Add a driver for the Raspberry Pi's firmware GPIO calls.
From: Linus Walleij @ 2016-10-06 8:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <87lgyh6at5.fsf@eliezer.anholt.net>
On Sat, Sep 24, 2016 at 9:01 AM, Eric Anholt <eric@anholt.net> wrote:
> Linus Walleij <linus.walleij@linaro.org> writes:
>> Sorry I am not familiar with your development model. I don't know
>> about any RPI downstream tree... What I mean is that the patch to
>> include/soc/bcm2835/raspberrypi-firmware.h should be merged by
>> whoever is maintaining that file, it is not a GPIO file.
>>
>> If I get an ACK from the maintainer I can take it into the GPIO
>> tree.
>
> Oh, people often say "the rpi tree" to mean downstream (currently 4.4).
> The maintainer of that file upstream is me, and I was hoping you could
> merge through your tree.
OK no problem, I can merge it once we agree on the mechanics :)
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 5/8] dt/bindings: Update binding for PM domain idle states
From: Geert Uytterhoeven @ 2016-10-06 8:09 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAMuHMdWxft8o493XN2zg1wj2By7P+qBkrvyQOt7WdBnhPAvSXQ@mail.gmail.com>
On Thu, Oct 6, 2016 at 10:06 AM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> On Wed, Oct 5, 2016 at 10:31 PM, Lina Iyer <lina.iyer@linaro.org> wrote:
>> Update DT bindings to describe idle states of PM domains.
>>
>> This patch is based on the original patch by Marc Titinger.
>>
>> Cc: <devicetree@vger.kernel.org>
>> Signed-off-by: Marc Titinger <mtitinger+renesas@baylibre.com>
>> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
>> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
>> Acked-by: Rob Herring <robh@kernel.org>
>> ---
>> .../devicetree/bindings/power/power_domain.txt | 36 ++++++++++++++++++++++
>> 1 file changed, 36 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/power/power_domain.txt b/Documentation/devicetree/bindings/power/power_domain.txt
>> index 025b5e7..a043315 100644
>> --- a/Documentation/devicetree/bindings/power/power_domain.txt
>> +++ b/Documentation/devicetree/bindings/power/power_domain.txt
>> @@ -29,6 +29,10 @@ Optional properties:
>> specified by this binding. More details about power domain specifier are
>> available in the next section.
>>
>> +- domain-idle-states : A phandle of an idle-state that shall be soaked into a
>> + generic domain power state. The idle state definitions are
>> + compatible with arm,idle-state specified in [1].
>> +
>> Example:
>>
>> power: power-controller at 12340000 {
>> @@ -59,6 +63,36 @@ The nodes above define two power controllers: 'parent' and 'child'.
>> Domains created by the 'child' power controller are subdomains of '0' power
>> domain provided by the 'parent' power controller.
>>
>> +Example 3:
>> + parent: power-controller at 12340000 {
>
> With W=1, this is gonna trigger:
>
> Warning (unit_address_vs_reg): Node foo has a unit name, but no reg property
>
> Yes, there are pre-existing users in this file.
Scrap this... switching desktops causes loss of position...
>> + compatible = "foo,power-controller";
>> + reg = <0x12340000 0x1000>;
>> + #power-domain-cells = <1>;
>> + domain-idle-states = <&DOMAIN_RET, &DOMAIN_PWR_DN>;
>> + };
+ DOMAIN_RET: state at 0 {
+ compatible = "arm,idle-state";
+ entry-latency-us = <1000>;
+ exit-latency-us = <2000>;
+ min-residency-us = <10000>;
This one is gonna trigger
Warning (unit_address_vs_reg): Node foo has a unit name, but no reg property
+ };
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH 5/8] dt/bindings: Update binding for PM domain idle states
From: Geert Uytterhoeven @ 2016-10-06 8:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475699519-109623-6-git-send-email-lina.iyer@linaro.org>
On Wed, Oct 5, 2016 at 10:31 PM, Lina Iyer <lina.iyer@linaro.org> wrote:
> Update DT bindings to describe idle states of PM domains.
>
> This patch is based on the original patch by Marc Titinger.
>
> Cc: <devicetree@vger.kernel.org>
> Signed-off-by: Marc Titinger <mtitinger+renesas@baylibre.com>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> Acked-by: Rob Herring <robh@kernel.org>
> ---
> .../devicetree/bindings/power/power_domain.txt | 36 ++++++++++++++++++++++
> 1 file changed, 36 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/power/power_domain.txt b/Documentation/devicetree/bindings/power/power_domain.txt
> index 025b5e7..a043315 100644
> --- a/Documentation/devicetree/bindings/power/power_domain.txt
> +++ b/Documentation/devicetree/bindings/power/power_domain.txt
> @@ -29,6 +29,10 @@ Optional properties:
> specified by this binding. More details about power domain specifier are
> available in the next section.
>
> +- domain-idle-states : A phandle of an idle-state that shall be soaked into a
> + generic domain power state. The idle state definitions are
> + compatible with arm,idle-state specified in [1].
> +
> Example:
>
> power: power-controller at 12340000 {
> @@ -59,6 +63,36 @@ The nodes above define two power controllers: 'parent' and 'child'.
> Domains created by the 'child' power controller are subdomains of '0' power
> domain provided by the 'parent' power controller.
>
> +Example 3:
> + parent: power-controller at 12340000 {
With W=1, this is gonna trigger:
Warning (unit_address_vs_reg): Node foo has a unit name, but no reg property
Yes, there are pre-existing users in this file.
> + compatible = "foo,power-controller";
> + reg = <0x12340000 0x1000>;
> + #power-domain-cells = <1>;
> + domain-idle-states = <&DOMAIN_RET, &DOMAIN_PWR_DN>;
> + };
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH 3/8] PM / Domains: Allow domain power states to be read from DT
From: Geert Uytterhoeven @ 2016-10-06 8:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1475699519-109623-4-git-send-email-lina.iyer@linaro.org>
Hi Lina,
On Wed, Oct 5, 2016 at 10:31 PM, Lina Iyer <lina.iyer@linaro.org> wrote:
> This patch allows domains to define idle states in the DT. SoC's can
> define domain idle states in DT using the "domain-idle-states" property
> of the domain provider. Calling of_pm_genpd_init() will read the idle
> states and initialize the genpd for the domain.
>
> In addition to the entry and exit latency for idle state, also add
> residency_ns, param and of_node property to each state. A domain idling
> in a state is only power effecient if it stays idle for a certain period
> in that state. The residency provides this minimum time for the idle
> state to provide power benefits. The param is a state specific u32 value
> that the platform may use for that idle state.
>
> This patch is based on the original patch by Marc Titinger.
>
> Signed-off-by: Marc Titinger <mtitinger+renesas@baylibre.com>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> ---
> drivers/base/power/domain.c | 103 ++++++++++++++++++++++++++++++++++++++++++++
> include/linux/pm_domain.h | 8 ++++
> 2 files changed, 111 insertions(+)
>
> diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c
> index 740afa9..368a5b8 100644
> --- a/drivers/base/power/domain.c
> +++ b/drivers/base/power/domain.c
> @@ -1895,6 +1895,109 @@ out:
> return ret ? -EPROBE_DEFER : 0;
> }
> EXPORT_SYMBOL_GPL(genpd_dev_pm_attach);
> +
> +static const struct of_device_id idle_state_match[] = {
> + { .compatible = "arm,idle-state", },
Do we want ARM-specific compatible values without an #ifdef in drivers/base/?
I know we already have "samsung,power-domain".
Perhaps that should be protected by #ifdef, too.
> + { }
> +};
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH 02/11] DOCUMENTATION: dt-bindings: Document the STM32 USART bindings
From: Alexandre Torgue @ 2016-10-06 8:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAL_JsqK=VCHcPbupnwLVEWehqJbXfGD1CSZT++A4+N6DD6VqxA@mail.gmail.com>
Hi Rob,
On 10/05/2016 05:13 PM, Rob Herring wrote:
> On Wed, Oct 5, 2016 at 9:09 AM, Gerald Baeza <gerald.baeza@st.com> wrote:
>> On 09/23/2016 05:29 PM, Rob Herring wrote:
>>>
>>> On Thu, Sep 15, 2016 at 06:42:34PM +0200, Alexandre TORGUE wrote:
>>>>
>>>> This adds documentation of device tree bindings for the
>>>> STM32 USART
>>>
>>>
>>> Please make your subject prefixes consistent and drop "DOCUMENTATION".
>>>
>>
>> Ok, thanks
>>
>>>>
>>>> Signed-off-by: Maxime Coquelin <mcoquelin.stm32@gmail.com>
>>>> Signed-off-by: Alexandre TORGUE <alexandre.torgue@st.com>
>>>>
>>>> diff --git a/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
>>>> b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
>>>> new file mode 100644
>>>> index 0000000..75b1400
>>>> --- /dev/null
>>>> +++ b/Documentation/devicetree/bindings/serial/st,stm32-usart.txt
>>>> @@ -0,0 +1,34 @@
>>>> +* STMicroelectronics STM32 USART
>>>> +
>>>> +Required properties:
>>>> +- compatible: Can be either "st,stm32-usart", "st,stm32-uart",
>>>> +"st,stm32f7-usart" or "st,stm32f7-uart" depending on whether
>>>> +the device supports synchronous mode and is compatible with
>>>> +stm32(f4) or stm32f7.
>>>
>>>
>>> Why not put f4 in the compatible string. stm32 is too generic.
>>
>>
>> The initial binding is not in current kernel so it has been put in this
>> serie as PATCH 07/11. It will be squashed with this one, as you requested.
>>
>> But the driver tty/serial/stm32-usart.c was already upstreamed and it
>> already mentions the "st,stm32-usart" and "st,stm32-uart" for stm32f4 so I
>> kept this as it for backward compatibility for those who already use the
>> driver.
>>
>> I do not have the history to explain this inconsistency but can you confirm
>> that keeping the existing compatible values from the driver is the good
>> approach please?
>
> Yes, keep it as it. Please reformat 1 valid combination per line.
Ok. Do you mean something like:
- compatible: "st,stm32-usart", "st,stm32-uart" For STM32F4 SOC and if
IP supports synchronous mode.
- compatible: "st,stm32-uart" For STM32F4 SOC.
- compatible: "st,stm32f7-usart", "st,stm32f7-uart": For STM32F7 SOC
and if IP supports synchronous mode.
- compatible: "st,stm32f7-uart" For STM32F7 SOC
If you agree, what do you prefer to send modification ? I mean, those
bindings documentation patches are already in linux-next tree. Do you
want a new patch on top of linux-next or do you prefer I resend only
those ones ?
Regards
Alex
>
>>> What determines sync mode or not? If it is IP configuration fixed in the
>>> design, then this is fine. If it is user choice or board dependent, then
>>> use a separate property.
>>
>>
>> This is IP configuration fixed in the design, indeed.
>>
>>>> +- reg: The address and length of the peripheral registers space
>>>> +- interrupts: The interrupt line of the USART instance
>>>> +- clocks: The input clock of the USART instance
>>>> +
>>>> +Optional properties:
>>>> +- pinctrl: The reference on the pins configuration
>>>> +- st,hw-flow-ctrl: bool flag to enable hardware flow control.
>>>> +
>>>> +Examples:
>>>> +usart4: serial at 40004c00 {
>>>> + compatible = "st,stm32-uart";
>>>> + reg = <0x40004c00 0x400>;
>>>> + interrupts = <52>;
>>>> + clocks = <&clk_pclk1>;
>>>> + pinctrl-names = "default";
>>>> + pinctrl-0 = <&pinctrl_usart4>;
>>>> +};
>>>> +
>>>> +usart2: serial at 40004400 {
>>>> + compatible = "st,stm32-usart", "st,stm32-uart";
>>>
>>>
>>> What are valid combinations? usart is sync only, not sync and async?
>>
>>
>> usart (sync and async) is a superset of uart (async).
>> But the current driver does not use the synchronous mode, so the distinction
>> is just here to be consistent with the reference manual instances naming (so
>> configuration).
>
> Okay, but this point is not clear in the compatible text. The
> description should allow me to validate the example or a dts file.
>
> Rob
>
^ permalink raw reply
* [PATCH v6 5/5] ARM: sunxi: Enable VGA bridge
From: Maxime Ripard @ 2016-10-06 7:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.2ec28e2292f37131839babc08427ef9f1aece26a.1475740611.git-series.maxime.ripard@free-electrons.com>
Enable the VGA bridge used on the A13-Olinuxino in the sunxi defconfig
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/configs/sunxi_defconfig | 1 +
1 file changed, 1 insertion(+), 0 deletions(-)
diff --git a/arch/arm/configs/sunxi_defconfig b/arch/arm/configs/sunxi_defconfig
index 714da336ec86..33b8c3308335 100644
--- a/arch/arm/configs/sunxi_defconfig
+++ b/arch/arm/configs/sunxi_defconfig
@@ -98,6 +98,7 @@ CONFIG_MEDIA_RC_SUPPORT=y
CONFIG_RC_DEVICES=y
CONFIG_IR_SUNXI=y
CONFIG_DRM=y
+CONFIG_DRM_SIMPLE_VGA_DAC=y
CONFIG_DRM_SUN4I=y
CONFIG_FB=y
CONFIG_FB_SIMPLE=y
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH v6 4/5] ARM: multi_v7: enable VGA bridge
From: Maxime Ripard @ 2016-10-06 7:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.2ec28e2292f37131839babc08427ef9f1aece26a.1475740611.git-series.maxime.ripard@free-electrons.com>
Enable the RGB to VGA bridge driver in the defconfig
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
arch/arm/configs/multi_v7_defconfig | 1 +
1 file changed, 1 insertion(+), 0 deletions(-)
diff --git a/arch/arm/configs/multi_v7_defconfig b/arch/arm/configs/multi_v7_defconfig
index 2c8665cd9dc5..ae1879a61bbe 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -567,6 +567,7 @@ CONFIG_DRM=y
CONFIG_DRM_I2C_ADV7511=m
# CONFIG_DRM_I2C_CH7006 is not set
# CONFIG_DRM_I2C_SIL164 is not set
+CONFIG_DRM_SIMPLE_VGA_DAC=m
CONFIG_DRM_NXP_PTN3460=m
CONFIG_DRM_PARADE_PS8622=m
CONFIG_DRM_NOUVEAU=m
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH v6 3/5] ARM: sun5i: a13-olinuxino: Enable VGA bridge
From: Maxime Ripard @ 2016-10-06 7:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.2ec28e2292f37131839babc08427ef9f1aece26a.1475740611.git-series.maxime.ripard@free-electrons.com>
Now that we have support for the VGA bridges using our DRM driver, enable
the display engine for the Olimex A13-Olinuxino.
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Acked-by: Chen-Yu Tsai <wens@csie.org>
---
arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 54 ++++++++++++++++++++++++-
1 file changed, 54 insertions(+), 0 deletions(-)
diff --git a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
index b3c234c65ea1..c69e0b0b7b55 100644
--- a/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
+++ b/arch/arm/boot/dts/sun5i-a13-olinuxino.dts
@@ -72,6 +72,47 @@
default-state = "on";
};
};
+
+ bridge {
+ compatible = "simple-vga-dac";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port at 0 {
+ reg = <0>;
+
+ vga_bridge_in: endpoint {
+ remote-endpoint = <&tcon0_out_vga>;
+ };
+ };
+
+ port at 1 {
+ reg = <1>;
+
+ vga_bridge_out: endpoint {
+ remote-endpoint = <&vga_con_in>;
+ };
+ };
+ };
+ };
+
+ vga {
+ compatible = "vga-connector";
+
+ port {
+ vga_con_in: endpoint {
+ remote-endpoint = <&vga_bridge_out>;
+ };
+ };
+ };
+};
+
+&be0 {
+ status = "okay";
};
&ehci0 {
@@ -211,6 +252,19 @@
status = "okay";
};
+&tcon0 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&lcd_rgb666_pins>;
+ status = "okay";
+};
+
+&tcon0_out {
+ tcon0_out_vga: endpoint at 0 {
+ reg = <0>;
+ remote-endpoint = <&vga_bridge_in>;
+ };
+};
+
&uart1 {
pinctrl-names = "default";
pinctrl-0 = <&uart1_pins_b>;
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH v6 2/5] drm/bridge: Add RGB to VGA bridge support
From: Maxime Ripard @ 2016-10-06 7:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.2ec28e2292f37131839babc08427ef9f1aece26a.1475740611.git-series.maxime.ripard@free-electrons.com>
Some boards have an entirely passive RGB to VGA bridge, based on either
DACs or resistor ladders.
Those might or might not have an i2c bus routed to the VGA connector in
order to access the screen EDIDs.
Add a bridge that doesn't do anything but expose the modes available on the
screen, either based on the EDIDs if available, or based on the XGA
standards.
Acked-by: Rob Herring <robh@kernel.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
Documentation/devicetree/bindings/display/bridge/simple-vga-dac.txt | 48 +++++++++++++++-
drivers/gpu/drm/bridge/Kconfig | 7 ++-
drivers/gpu/drm/bridge/Makefile | 1 +-
drivers/gpu/drm/bridge/simple-vga-dac.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 285 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/display/bridge/simple-vga-dac.txt
create mode 100644 drivers/gpu/drm/bridge/simple-vga-dac.c
diff --git a/Documentation/devicetree/bindings/display/bridge/simple-vga-dac.txt b/Documentation/devicetree/bindings/display/bridge/simple-vga-dac.txt
new file mode 100644
index 000000000000..7143c54ea88c
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/bridge/simple-vga-dac.txt
@@ -0,0 +1,48 @@
+Dumb RGB to VGA bridge
+----------------------
+
+This binding is aimed for dumb RGB to VGA bridges that do not require
+any configuration.
+
+Required properties:
+
+- compatible: Must be "simple-vga-dac"
+
+Required nodes:
+
+This device has two video ports. Their connections are modeled using the OF
+graph bindings specified in Documentation/devicetree/bindings/graph.txt.
+
+- Video port 0 for RGB input
+- Video port 1 for VGA output
+
+
+Example
+-------
+
+bridge {
+ compatible = "simple-vga-dac";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ports {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ port at 0 {
+ reg = <0>;
+
+ vga_bridge_in: endpoint {
+ remote-endpoint = <&tcon0_out_vga>;
+ };
+ };
+
+ port at 1 {
+ reg = <1>;
+
+ vga_bridge_out: endpoint {
+ remote-endpoint = <&vga_con_in>;
+ };
+ };
+ };
+};
diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
index b590e678052d..5fe8c7829052 100644
--- a/drivers/gpu/drm/bridge/Kconfig
+++ b/drivers/gpu/drm/bridge/Kconfig
@@ -58,6 +58,13 @@ config DRM_SII902X
---help---
Silicon Image sii902x bridge chip driver.
+config DRM_SIMPLE_VGA_DAC
+ tristate "Simple VGA DAC support"
+ depends on OF
+ select DRM_KMS_HELPER
+ ---help---
+ Support for RGB to VGA bridges
+
config DRM_TOSHIBA_TC358767
tristate "Toshiba TC358767 eDP bridge"
depends on OF
diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
index efdb07e878f5..2cdd99035f38 100644
--- a/drivers/gpu/drm/bridge/Makefile
+++ b/drivers/gpu/drm/bridge/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_DRM_DW_HDMI_AHB_AUDIO) += dw-hdmi-ahb-audio.o
obj-$(CONFIG_DRM_NXP_PTN3460) += nxp-ptn3460.o
obj-$(CONFIG_DRM_PARADE_PS8622) += parade-ps8622.o
obj-$(CONFIG_DRM_SII902X) += sii902x.o
+obj-$(CONFIG_DRM_SIMPLE_VGA_DAC) += simple-vga-dac.o
obj-$(CONFIG_DRM_TOSHIBA_TC358767) += tc358767.o
obj-$(CONFIG_DRM_ANALOGIX_DP) += analogix/
obj-$(CONFIG_DRM_I2C_ADV7511) += adv7511/
diff --git a/drivers/gpu/drm/bridge/simple-vga-dac.c b/drivers/gpu/drm/bridge/simple-vga-dac.c
new file mode 100644
index 000000000000..c81a25ab0b0d
--- /dev/null
+++ b/drivers/gpu/drm/bridge/simple-vga-dac.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2015-2016 Free Electrons
+ * Copyright (C) 2015-2016 NextThing Co
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/of_graph.h>
+
+#include <drm/drmP.h>
+#include <drm/drm_atomic_helper.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_crtc_helper.h>
+
+struct simple_vga {
+ struct drm_bridge bridge;
+ struct drm_connector connector;
+
+ struct i2c_adapter *ddc;
+};
+
+static inline struct simple_vga *
+drm_bridge_to_simple_vga(struct drm_bridge *bridge)
+{
+ return container_of(bridge, struct simple_vga, bridge);
+}
+
+static inline struct simple_vga *
+drm_connector_to_simple_vga(struct drm_connector *connector)
+{
+ return container_of(connector, struct simple_vga, connector);
+}
+
+static int simple_vga_get_modes(struct drm_connector *connector)
+{
+ struct simple_vga *vga = drm_connector_to_simple_vga(connector);
+ struct edid *edid;
+ int ret;
+
+ if (IS_ERR(vga->ddc))
+ goto fallback;
+
+ edid = drm_get_edid(connector, vga->ddc);
+ if (!edid) {
+ DRM_INFO("EDID readout failed, falling back to standard modes\n");
+ goto fallback;
+ }
+
+ drm_mode_connector_update_edid_property(connector, edid);
+ return drm_add_edid_modes(connector, edid);
+
+fallback:
+ /*
+ * In case we cannot retrieve the EDIDs (broken or missing i2c
+ * bus), fallback on the XGA standards
+ */
+ ret = drm_add_modes_noedid(connector, 1920, 1200);
+
+ /* And prefer a mode pretty much anyone can handle */
+ drm_set_preferred_mode(connector, 1024, 768);
+
+ return ret;
+}
+
+static const struct drm_connector_helper_funcs simple_vga_con_helper_funcs = {
+ .get_modes = simple_vga_get_modes,
+};
+
+static enum drm_connector_status
+simple_vga_connector_detect(struct drm_connector *connector, bool force)
+{
+ struct simple_vga *vga = drm_connector_to_simple_vga(connector);
+
+ /*
+ * Even if we have an I2C bus, we can't assume that the cable
+ * is disconnected if drm_probe_ddc fails. Some cables don't
+ * wire the DDC pins, or the I2C bus might not be working at
+ * all.
+ */
+ if (!IS_ERR(vga->ddc) && drm_probe_ddc(vga->ddc))
+ return connector_status_connected;
+
+ return connector_status_unknown;
+}
+
+static void
+simple_vga_connector_destroy(struct drm_connector *connector)
+{
+ drm_connector_cleanup(connector);
+}
+
+static const struct drm_connector_funcs simple_vga_con_funcs = {
+ .dpms = drm_atomic_helper_connector_dpms,
+ .detect = simple_vga_connector_detect,
+ .fill_modes = drm_helper_probe_single_connector_modes,
+ .destroy = simple_vga_connector_destroy,
+ .reset = drm_atomic_helper_connector_reset,
+ .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
+ .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
+};
+
+static int simple_vga_attach(struct drm_bridge *bridge)
+{
+ struct simple_vga *vga = drm_bridge_to_simple_vga(bridge);
+ int ret;
+
+ if (!bridge->encoder) {
+ DRM_ERROR("Missing encoder\n");
+ return -ENODEV;
+ }
+
+ drm_connector_helper_add(&vga->connector,
+ &simple_vga_con_helper_funcs);
+ ret = drm_connector_init(bridge->dev, &vga->connector,
+ &simple_vga_con_funcs, DRM_MODE_CONNECTOR_VGA);
+ if (ret) {
+ DRM_ERROR("Failed to initialize connector\n");
+ return ret;
+ }
+
+ drm_mode_connector_attach_encoder(&vga->connector,
+ bridge->encoder);
+
+ return 0;
+}
+
+static const struct drm_bridge_funcs simple_vga_bridge_funcs = {
+ .attach = simple_vga_attach,
+};
+
+static struct i2c_adapter *simple_vga_retrieve_ddc(struct device *dev)
+{
+ struct device_node *end_node, *phandle, *remote;
+ struct i2c_adapter *ddc;
+
+ end_node = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
+ if (!end_node) {
+ dev_err(dev, "Missing connector endpoint\n");
+ return ERR_PTR(-ENODEV);
+ }
+
+ remote = of_graph_get_remote_port_parent(end_node);
+ of_node_put(end_node);
+ if (!remote) {
+ dev_err(dev, "Enable to parse remote node\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ phandle = of_parse_phandle(remote, "ddc-i2c-bus", 0);
+ of_node_put(remote);
+ if (!phandle)
+ return ERR_PTR(-ENODEV);
+
+ ddc = of_get_i2c_adapter_by_node(phandle);
+ of_node_put(phandle);
+ if (!ddc)
+ return ERR_PTR(-EPROBE_DEFER);
+
+ return ddc;
+}
+
+static int simple_vga_probe(struct platform_device *pdev)
+{
+ struct simple_vga *vga;
+ int ret;
+
+ vga = devm_kzalloc(&pdev->dev, sizeof(*vga), GFP_KERNEL);
+ if (!vga)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, vga);
+
+ vga->ddc = simple_vga_retrieve_ddc(&pdev->dev);
+ if (IS_ERR(vga->ddc)) {
+ if (PTR_ERR(vga->ddc) == -ENODEV) {
+ dev_info(&pdev->dev,
+ "No i2c bus specified... Disabling EDID readout\n");
+ } else {
+ dev_err(&pdev->dev, "Couldn't retrieve i2c bus\n");
+ return PTR_ERR(vga->ddc);
+ }
+ }
+
+ vga->bridge.funcs = &simple_vga_bridge_funcs;
+ vga->bridge.of_node = pdev->dev.of_node;
+
+ ret = drm_bridge_add(&vga->bridge);
+ if (ret && !IS_ERR(vga->ddc))
+ i2c_put_adapter(vga->ddc);
+
+ return ret;
+}
+
+static int simple_vga_remove(struct platform_device *pdev)
+{
+ struct simple_vga *vga = platform_get_drvdata(pdev);
+
+ drm_bridge_remove(&vga->bridge);
+
+ if (!IS_ERR(vga->ddc))
+ i2c_put_adapter(vga->ddc);
+
+ return 0;
+}
+
+static const struct of_device_id simple_vga_match[] = {
+ { .compatible = "simple-vga-dac" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, simple_vga_match);
+
+struct platform_driver simple_vga_driver = {
+ .probe = simple_vga_probe,
+ .remove = simple_vga_remove,
+ .driver = {
+ .name = "simple-vga-dac",
+ .of_match_table = simple_vga_match,
+ },
+};
+module_platform_driver(simple_vga_driver);
+
+MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
+MODULE_DESCRIPTION("Simple VGA DAC driver");
+MODULE_LICENSE("GPL");
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH v6 1/5] drm/sun4i: rgb: Remove the bridge enable/disable functions
From: Maxime Ripard @ 2016-10-06 7:57 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cover.2ec28e2292f37131839babc08427ef9f1aece26a.1475740611.git-series.maxime.ripard@free-electrons.com>
The atomic helpers already call the drm_bridge_enable on our behalf,
there's no need to do it a second time.
Reported-by: Sean Paul <seanpaul@chromium.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
drivers/gpu/drm/sun4i/sun4i_rgb.c | 6 ------
1 file changed, 0 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c
index 4e4bea6f395c..d198ad7e5323 100644
--- a/drivers/gpu/drm/sun4i/sun4i_rgb.c
+++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c
@@ -155,9 +155,6 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)
if (!IS_ERR(tcon->panel))
drm_panel_prepare(tcon->panel);
- /* encoder->bridge can be NULL; drm_bridge_enable checks for it */
- drm_bridge_enable(encoder->bridge);
-
sun4i_tcon_channel_enable(tcon, 0);
if (!IS_ERR(tcon->panel))
@@ -177,9 +174,6 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)
sun4i_tcon_channel_disable(tcon, 0);
- /* encoder->bridge can be NULL; drm_bridge_disable checks for it */
- drm_bridge_disable(encoder->bridge);
-
if (!IS_ERR(tcon->panel))
drm_panel_unprepare(tcon->panel);
}
--
git-series 0.8.10
^ permalink raw reply related
* [PATCH v6 0/5] drm: Add Support for Passive RGB to VGA bridges
From: Maxime Ripard @ 2016-10-06 7:57 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
This serie is about adding support for the RGB to VGA bridge found in
the A13-Olinuxino and the CHIP VGA adapter.
Both these boards rely on an entirely passive bridge made out of
resitor ladders that do not require any initialisation. The only thing
needed is to get the timings from the screen if available (and if not,
fall back on XGA standards), set up the display pipeline to output on
the RGB bus with the proper timings, and you're done.
This serie also fixes a bunch of bugs uncovered when trying to
increase the resolution, and hence the pixel clock, of our
pipeline. It also fixes a few bugs in the DRM driver itself that went
unnoticed before.
Let me know what you think,
Maxime
Changes from v5:
- Renamed to simple-vga-dac
Changes from v4:
- Removed unused functions
Changes from v3:
- Depends on OF in Kconfig
- Fixed typos in the driver comments
- Removed the mention of a "passive" bridge in the bindings doc
- Made the strcuture const
- Removed the nops and best_encoders implementations
- Removed the call to drm_bridge_enable in the sun4i driver
Changes from v2:
- Changed the compatible as suggested
- Rebased on top 4.8
Changes from v1:
- Switch to using a vga-connector
- Use drm_encoder bridge pointer instead of doing our own
- Report the connector status as unknown instead of connected by
default, and as connected only if we can retrieve the EDID.
- Switch to of_i2c_get_adapter by node, and put the reference when done
- Rebased on linux-next
Maxime Ripard (5):
drm/sun4i: rgb: Remove the bridge enable/disable functions
drm/bridge: Add RGB to VGA bridge support
ARM: sun5i: a13-olinuxino: Enable VGA bridge
ARM: multi_v7: enable VGA bridge
ARM: sunxi: Enable VGA bridge
.../bindings/display/bridge/rgb-to-vga-bridge.txt | 48 +++++
arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 54 +++++
arch/arm/configs/multi_v7_defconfig | 1 +
arch/arm/configs/sunxi_defconfig | 1 +
drivers/gpu/drm/bridge/Kconfig | 7 +
drivers/gpu/drm/bridge/Makefile | 1 +
drivers/gpu/drm/bridge/rgb-to-vga.c | 229 +++++++++++++++++++++
drivers/gpu/drm/sun4i/sun4i_rgb.c | 6 -
8 files changed, 341 insertions(+), 6 deletions(-)
create mode 100644 Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
create mode 100644 drivers/gpu/drm/bridge/rgb-to-vga.c
--
2.9.3
Maxime Ripard (5):
drm/sun4i: rgb: Remove the bridge enable/disable functions
drm/bridge: Add RGB to VGA bridge support
ARM: sun5i: a13-olinuxino: Enable VGA bridge
ARM: multi_v7: enable VGA bridge
ARM: sunxi: Enable VGA bridge
Documentation/devicetree/bindings/display/bridge/simple-vga-dac.txt | 48 +++++++++++++++-
arch/arm/boot/dts/sun5i-a13-olinuxino.dts | 54 +++++++++++++++++-
arch/arm/configs/multi_v7_defconfig | 1 +-
arch/arm/configs/sunxi_defconfig | 1 +-
drivers/gpu/drm/bridge/Kconfig | 7 ++-
drivers/gpu/drm/bridge/Makefile | 1 +-
drivers/gpu/drm/bridge/simple-vga-dac.c | 229 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
drivers/gpu/drm/sun4i/sun4i_rgb.c | 6 +--
8 files changed, 341 insertions(+), 6 deletions(-)
create mode 100644 Documentation/devicetree/bindings/display/bridge/simple-vga-dac.txt
create mode 100644 drivers/gpu/drm/bridge/simple-vga-dac.c
--
git-series 0.8.10
^ permalink raw reply
* [PATCH v5 2/5] drm/bridge: Add RGB to VGA bridge support
From: Maxime Ripard @ 2016-10-06 7:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <8795dc49-26f9-0505-f442-2ca74b51872f@codeaurora.org>
Hi Archit,
On Mon, Oct 03, 2016 at 04:40:57PM +0530, Archit Taneja wrote:
> Hi Maxime,
>
> On 09/30/2016 08:07 PM, Maxime Ripard wrote:
> >Some boards have an entirely passive RGB to VGA bridge, based on either
> >DACs or resistor ladders.
> >
> >Those might or might not have an i2c bus routed to the VGA connector in
> >order to access the screen EDIDs.
> >
> >Add a bridge that doesn't do anything but expose the modes available on the
> >screen, either based on the EDIDs if available, or based on the XGA
> >standards.
> >
> >Acked-by: Rob Herring <robh@kernel.org>
> >Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> >---
> > .../bindings/display/bridge/rgb-to-vga-bridge.txt | 48 +++++
> > drivers/gpu/drm/bridge/Kconfig | 7 +
> > drivers/gpu/drm/bridge/Makefile | 1 +
> > drivers/gpu/drm/bridge/rgb-to-vga.c | 229 +++++++++++++++++++++
> > 4 files changed, 285 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
> > create mode 100644 drivers/gpu/drm/bridge/rgb-to-vga.c
> >
> >diff --git a/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt b/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
> >new file mode 100644
> >index 000000000000..a8375bc1f9cb
> >--- /dev/null
> >+++ b/Documentation/devicetree/bindings/display/bridge/rgb-to-vga-bridge.txt
> >@@ -0,0 +1,48 @@
> >+Dumb RGB to VGA bridge
> >+----------------------
> >+
> >+This binding is aimed for dumb RGB to VGA bridges that do not require
> >+any configuration.
> >+
> >+Required properties:
> >+
> >+- compatible: Must be "rgb-to-vga-bridge"
>
> I'd talked to Laurent on IRC if he's okay with this. And I guess you to
> had discussed it during XDC too. He's suggested that it'd be better to
> have the compatible string as "simple-vga-dac".
I just wished this bikeshedding had taken place publicly and be
actually part of that discussion, but yeah, ok.
> Some of the reasons behind having this:
>
> - We don't need to specify "rgb" in the compatible string since most
> simple VGA DACs can only work with an RGB input.
Ok.
> - Also, with "dac" specified in the string, we don't need to
> specifically mention "bridge" in the string. Also, bridge is a drm
> specific term.
>
> - "simple" is considered because it's an unconfigurable bridge, and it
> might be misleading for other VGA DACs to not use "vga-dac".
All those "simple" bindings are just the biggest lie we ever
told. It's simple when you introduce it, and then grows into something
much more complicated than a non-simple implementation.
> What do you think about this? If you think it's good, would it be
> possible for you to change this? I guess it's okay for the rest of
> the patch to stay the same.
I'll update and respin the serie.
Thanks,
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20161006/701c158a/attachment.sig>
^ permalink raw reply
* linux-next: manual merge of the gpio tree with the arm-soc tree
From: Linus Walleij @ 2016-10-06 6:52 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161006094114.764d2f34@canb.auug.org.au>
On Thu, Oct 6, 2016 at 12:41 AM, Stephen Rothwell <sfr@canb.auug.org.au> wrote:
> On Tue, 27 Sep 2016 15:05:42 +1000 Stephen Rothwell <sfr@canb.auug.org.au> wrote:
>>
>> Today's linux-next merge of the gpio tree got a conflict in:
>>
>> arch/arm/mach-omap2/board-rx51-peripherals.c
>>
>> between commit:
>>
>> 9b7141d01a76 ("ARM: OMAP2+: Drop legacy board file for n900")
>>
>> from the arm-soc tree and commit:
>>
>> 9132ce450bd1 ("ARM: omap2: fix missing include")
>>
>> from the gpio tree.
>>
>> I fixed it up (the former removed the file, so I did that) and can
>> carry the fix as necessary. This is now fixed as far as linux-next is
>> concerned, but any non trivial conflicts should be mentioned to your
>> upstream maintainer when your tree is submitted for merging. You may
>> also want to consider cooperating with the maintainer of the conflicting
>> tree to minimise any particularly complex conflicts.
>
> Since Linus (Torvalds) has merged the gpio tree, this conflict (and
> file removal) now affects the merge of the arm-soc tree).
Yup and I also informed him in my pull request about this conflict
so shouldn't be a problem.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH] pwm: core: Use pwm->args.polarity to setup PWM_POLARITY_INVERSED
From: Lukasz Majewski @ 2016-10-06 6:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161001101235.24598-3-bhuvanchandra.dv@toradex.com>
The pwm_set_polarity() function finally calls pwm_apply_state(), which
in turn requires state->duty_cycle and state->period properly set.
In the moment when polarity is set, the PWM is disabled and not configured.
For that reason both above variables are set to 0 and the polarity is not
set.
To be sure that polarity is setup, one needs to set pwm->args.polarity, which
controls MX3_PWMCR_POUTC bit setting at imx_pwm_config_v2().
Signed-off-by: Lukasz Majewski <l.majewski@majess.pl>
---
This patch should be applied on top of:
"[v2,2/6] pwm: core: make the PWM_POLARITY flag in DTB optional"
http://patchwork.ozlabs.org/patch/677330/
---
drivers/pwm/core.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 1f62668..6cd6004 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -153,13 +153,11 @@ of_pwm_xlate_with_flags(struct pwm_chip *pc, const struct of_phandle_args *args)
return pwm;
pwm->args.period = args->args[1];
+ pwm->args.polarity = PWM_POLARITY_NORMAL;
- if (args->args_count > 2) {
+ if (args->args_count > 2)
if (args->args[2] & PWM_POLARITY_INVERTED)
- pwm_set_polarity(pwm, PWM_POLARITY_INVERSED);
- else
- pwm_set_polarity(pwm, PWM_POLARITY_NORMAL);
- }
+ pwm->args.polarity = PWM_POLARITY_INVERSED;
return pwm;
}
--
2.1.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox