* [PATCH v2 11/12] coresight: tmc-etr buf: Add TMC scatter gather mode backend
From: Suzuki K Poulose @ 2018-05-29 13:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, mathieu.poirier, mike.leach, robert.walker,
coresight, devicetree, robh, frowand.list, Suzuki K Poulose
In-Reply-To: <1527599737-28408-1-git-send-email-suzuki.poulose@arm.com>
Add the support for Scatter-Gather mode to the etr-buf layer.
Since we now have two different modes, we choose the backend
based on a set of conditions, documented in the code.
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
Change since last version:
- New in this version, splitted from the original patch.
- No functional changes.
---
drivers/hwtracing/coresight/coresight-tmc-etr.c | 114 +++++++++++++++++++++++-
drivers/hwtracing/coresight/coresight-tmc.h | 1 +
2 files changed, 111 insertions(+), 4 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index a0e504a..19955cf 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -516,7 +516,7 @@ static void tmc_etr_sg_table_populate(struct etr_sg_table *etr_table)
* @size - Total size of the data buffer
* @pages - Optional list of page virtual address
*/
-static struct etr_sg_table __maybe_unused *
+static struct etr_sg_table *
tmc_init_etr_sg_table(struct device *dev, int node,
unsigned long size, void **pages)
{
@@ -623,8 +623,86 @@ static const struct etr_buf_operations etr_flat_buf_ops = {
.get_data = tmc_etr_get_data_flat_buf,
};
+/*
+ * tmc_etr_alloc_sg_buf: Allocate an SG buf @etr_buf. Setup the parameters
+ * appropriately.
+ */
+static int tmc_etr_alloc_sg_buf(struct tmc_drvdata *drvdata,
+ struct etr_buf *etr_buf, int node,
+ void **pages)
+{
+ struct etr_sg_table *etr_table;
+
+ etr_table = tmc_init_etr_sg_table(drvdata->dev, node,
+ etr_buf->size, pages);
+ if (IS_ERR(etr_table))
+ return -ENOMEM;
+ etr_buf->hwaddr = etr_table->hwaddr;
+ etr_buf->mode = ETR_MODE_ETR_SG;
+ etr_buf->private = etr_table;
+ return 0;
+}
+
+static void tmc_etr_free_sg_buf(struct etr_buf *etr_buf)
+{
+ struct etr_sg_table *etr_table = etr_buf->private;
+
+ if (etr_table) {
+ tmc_free_sg_table(etr_table->sg_table);
+ kfree(etr_table);
+ }
+}
+
+static ssize_t tmc_etr_get_data_sg_buf(struct etr_buf *etr_buf, u64 offset,
+ size_t len, char **bufpp)
+{
+ struct etr_sg_table *etr_table = etr_buf->private;
+
+ return tmc_sg_table_get_data(etr_table->sg_table, offset, len, bufpp);
+}
+
+static void tmc_etr_sync_sg_buf(struct etr_buf *etr_buf, u64 rrp, u64 rwp)
+{
+ long r_offset, w_offset;
+ struct etr_sg_table *etr_table = etr_buf->private;
+ struct tmc_sg_table *table = etr_table->sg_table;
+
+ /* Convert hw address to offset in the buffer */
+ r_offset = tmc_sg_get_data_page_offset(table, rrp);
+ if (r_offset < 0) {
+ dev_warn(table->dev,
+ "Unable to map RRP %llx to offset\n", rrp);
+ etr_buf->len = 0;
+ return;
+ }
+
+ w_offset = tmc_sg_get_data_page_offset(table, rwp);
+ if (w_offset < 0) {
+ dev_warn(table->dev,
+ "Unable to map RWP %llx to offset\n", rwp);
+ etr_buf->len = 0;
+ return;
+ }
+
+ etr_buf->offset = r_offset;
+ if (etr_buf->full)
+ etr_buf->len = etr_buf->size;
+ else
+ etr_buf->len = ((w_offset < r_offset) ? etr_buf->size : 0) +
+ w_offset - r_offset;
+ tmc_sg_table_sync_data_range(table, r_offset, etr_buf->len);
+}
+
+static const struct etr_buf_operations etr_sg_buf_ops = {
+ .alloc = tmc_etr_alloc_sg_buf,
+ .free = tmc_etr_free_sg_buf,
+ .sync = tmc_etr_sync_sg_buf,
+ .get_data = tmc_etr_get_data_sg_buf,
+};
+
static const struct etr_buf_operations *etr_buf_ops[] = {
[ETR_MODE_FLAT] = &etr_flat_buf_ops,
+ [ETR_MODE_ETR_SG] = &etr_sg_buf_ops,
};
static inline int tmc_etr_mode_alloc_buf(int mode,
@@ -636,6 +714,7 @@ static inline int tmc_etr_mode_alloc_buf(int mode,
switch (mode) {
case ETR_MODE_FLAT:
+ case ETR_MODE_ETR_SG:
rc = etr_buf_ops[mode]->alloc(drvdata, etr_buf, node, pages);
if (!rc)
etr_buf->ops = etr_buf_ops[mode];
@@ -657,17 +736,38 @@ static struct etr_buf *tmc_alloc_etr_buf(struct tmc_drvdata *drvdata,
ssize_t size, int flags,
int node, void **pages)
{
- int rc = 0;
+ int rc = -ENOMEM;
+ bool has_etr_sg, has_iommu;
struct etr_buf *etr_buf;
+ has_etr_sg = tmc_etr_has_cap(drvdata, TMC_ETR_SG);
+ has_iommu = iommu_get_domain_for_dev(drvdata->dev);
+
etr_buf = kzalloc(sizeof(*etr_buf), GFP_KERNEL);
if (!etr_buf)
return ERR_PTR(-ENOMEM);
etr_buf->size = size;
- rc = tmc_etr_mode_alloc_buf(ETR_MODE_FLAT, drvdata,
- etr_buf, node, pages);
+ /*
+ * If we have to use an existing list of pages, we cannot reliably
+ * use a contiguous DMA memory (even if we have an IOMMU). Otherwise,
+ * we use the contiguous DMA memory if at least one of the following
+ * conditions is true:
+ * a) The ETR cannot use Scatter-Gather.
+ * b) we have a backing IOMMU
+ * c) The requested memory size is smaller (< 1M).
+ *
+ * Fallback to available mechanisms.
+ *
+ */
+ if (!pages &&
+ (!has_etr_sg || has_iommu || size < SZ_1M))
+ rc = tmc_etr_mode_alloc_buf(ETR_MODE_FLAT, drvdata,
+ etr_buf, node, pages);
+ if (rc && has_etr_sg)
+ rc = tmc_etr_mode_alloc_buf(ETR_MODE_ETR_SG, drvdata,
+ etr_buf, node, pages);
if (rc) {
kfree(etr_buf);
return ERR_PTR(rc);
@@ -761,6 +861,12 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
axictl |= TMC_AXICTL_ARCACHE_OS;
}
+ if (etr_buf->mode == ETR_MODE_ETR_SG) {
+ if (WARN_ON(!tmc_etr_has_cap(drvdata, TMC_ETR_SG)))
+ return;
+ axictl |= TMC_AXICTL_SCT_GAT_MODE;
+ }
+
writel_relaxed(axictl, drvdata->base + TMC_AXICTL);
tmc_write_dba(drvdata, etr_buf->hwaddr);
/*
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 39ed306..eeeba48 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -125,6 +125,7 @@ enum tmc_mem_intf_width {
enum etr_mode {
ETR_MODE_FLAT, /* Uses contiguous flat buffer */
+ ETR_MODE_ETR_SG, /* Uses in-built TMC ETR SG mechanism */
};
struct etr_buf_operations;
--
2.7.4
^ permalink raw reply related
* [PATCH v2 12/12] coresight: tmc: Add configuration support for trace buffer size
From: Suzuki K Poulose @ 2018-05-29 13:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, mathieu.poirier, mike.leach, robert.walker,
coresight, devicetree, robh, frowand.list, Suzuki K Poulose
In-Reply-To: <1527599737-28408-1-git-send-email-suzuki.poulose@arm.com>
Now that we can dynamically switch between contiguous memory and
SG table depending on the trace buffer size, provide the support
for selecting an appropriate buffer size.
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
.../ABI/testing/sysfs-bus-coresight-devices-tmc | 8 ++++++
.../devicetree/bindings/arm/coresight.txt | 3 +-
drivers/hwtracing/coresight/coresight-tmc.c | 33 ++++++++++++++++++++++
3 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tmc b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tmc
index 4fe677e..ea78714 100644
--- a/Documentation/ABI/testing/sysfs-bus-coresight-devices-tmc
+++ b/Documentation/ABI/testing/sysfs-bus-coresight-devices-tmc
@@ -83,3 +83,11 @@ KernelVersion: 4.7
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (R) Indicates the capabilities of the Coresight TMC.
The value is read directly from the DEVID register, 0xFC8,
+
+What: /sys/bus/coresight/devices/<memory_map>.tmc/buffer_size
+Date: August 2018
+KernelVersion: 4.18
+Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
+Description: (RW) Size of the trace buffer for TMC-ETR when used in SYSFS
+ mode. Writable only for TMC-ETR configurations. The value
+ should be aligned to the kernel pagesize.
diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
index 603d3c6..9aa30a1 100644
--- a/Documentation/devicetree/bindings/arm/coresight.txt
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -84,7 +84,8 @@ its hardware characteristcs.
* Optional property for TMC:
* arm,buffer-size: size of contiguous buffer space for TMC ETR
- (embedded trace router)
+ (embedded trace router). This property is obsolete. The buffer size
+ can be configured dynamically via buffer_size property in sysfs.
* arm,scatter-gather: boolean. Indicates that the TMC-ETR can safely
use the SG mode on this system.
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index bc8fc86..1b817ec 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -277,8 +277,41 @@ static ssize_t trigger_cntr_store(struct device *dev,
}
static DEVICE_ATTR_RW(trigger_cntr);
+static ssize_t buffer_size_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ return sprintf(buf, "%#x\n", drvdata->size);
+}
+
+static ssize_t buffer_size_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ int ret;
+ unsigned long val;
+ struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+
+ /* Only permitted for TMC-ETRs */
+ if (drvdata->config_type != TMC_CONFIG_TYPE_ETR)
+ return -EPERM;
+
+ ret = kstrtoul(buf, 0, &val);
+ if (ret)
+ return ret;
+ /* The buffer size should be page aligned */
+ if (val & (PAGE_SIZE - 1))
+ return -EINVAL;
+ drvdata->size = val;
+ return size;
+}
+
+static DEVICE_ATTR_RW(buffer_size);
+
static struct attribute *coresight_tmc_attrs[] = {
&dev_attr_trigger_cntr.attr,
+ &dev_attr_buffer_size.attr,
NULL,
};
--
2.7.4
^ permalink raw reply related
* [PATCH v2 08/12] coresight: Add generic TMC sg table framework
From: Suzuki K Poulose @ 2018-05-29 13:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, mathieu.poirier, mike.leach, robert.walker,
coresight, devicetree, robh, frowand.list, Suzuki K Poulose
In-Reply-To: <1527599737-28408-1-git-send-email-suzuki.poulose@arm.com>
This patch introduces a generic sg table data structure and
associated operations. An SG table can be used to map a set
of Data pages where the trace data could be stored by the TMC
ETR. The information about the data pages could be stored in
different formats, depending on the type of the underlying
SG mechanism (e.g, TMC ETR SG vs Coresight CATU). The generic
structure provides book keeping of the pages used for the data
as well as the table contents. The table should be filled by
the user of the infrastructure.
A table can be created by specifying the number of data pages
as well as the number of table pages required to hold the
pointers, where the latter could be different for different
types of tables. The pages are mapped in the appropriate dma
data direction mode (i.e, DMA_TO_DEVICE for table pages
and DMA_FROM_DEVICE for data pages). The framework can optionally
accept a set of allocated data pages (e.g, perf ring buffer) and
map them accordingly. The table and data pages are vmap'ed to allow
easier access by the drivers. The framework also provides helpers to
sync the data written to the pages with appropriate directions.
This will be later used by the TMC ETR SG unit and CATU.
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
Changes since previous version:
- Drop helper for table vaddr/paddr, data vaddr as we don't use
them anyways.
---
drivers/hwtracing/coresight/coresight-tmc-etr.c | 268 ++++++++++++++++++++++++
drivers/hwtracing/coresight/coresight-tmc.h | 50 +++++
2 files changed, 318 insertions(+)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 04206ff..402b061 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -6,9 +6,277 @@
#include <linux/coresight.h>
#include <linux/dma-mapping.h>
+#include <linux/slab.h>
#include "coresight-priv.h"
#include "coresight-tmc.h"
+/*
+ * tmc_pages_get_offset: Go through all the pages in the tmc_pages
+ * and map the device address @addr to an offset within the virtual
+ * contiguous buffer.
+ */
+static long
+tmc_pages_get_offset(struct tmc_pages *tmc_pages, dma_addr_t addr)
+{
+ int i;
+ dma_addr_t page_start;
+
+ for (i = 0; i < tmc_pages->nr_pages; i++) {
+ page_start = tmc_pages->daddrs[i];
+ if (addr >= page_start && addr < (page_start + PAGE_SIZE))
+ return i * PAGE_SIZE + (addr - page_start);
+ }
+
+ return -EINVAL;
+}
+
+/*
+ * tmc_pages_free : Unmap and free the pages used by tmc_pages.
+ * If the pages were not allocated in tmc_pages_alloc(), we would
+ * simply drop the refcount.
+ */
+static void tmc_pages_free(struct tmc_pages *tmc_pages,
+ struct device *dev, enum dma_data_direction dir)
+{
+ int i;
+
+ for (i = 0; i < tmc_pages->nr_pages; i++) {
+ if (tmc_pages->daddrs && tmc_pages->daddrs[i])
+ dma_unmap_page(dev, tmc_pages->daddrs[i],
+ PAGE_SIZE, dir);
+ if (tmc_pages->pages && tmc_pages->pages[i])
+ __free_page(tmc_pages->pages[i]);
+ }
+
+ kfree(tmc_pages->pages);
+ kfree(tmc_pages->daddrs);
+ tmc_pages->pages = NULL;
+ tmc_pages->daddrs = NULL;
+ tmc_pages->nr_pages = 0;
+}
+
+/*
+ * tmc_pages_alloc : Allocate and map pages for a given @tmc_pages.
+ * If @pages is not NULL, the list of page virtual addresses are
+ * used as the data pages. The pages are then dma_map'ed for @dev
+ * with dma_direction @dir.
+ *
+ * Returns 0 upon success, else the error number.
+ */
+static int tmc_pages_alloc(struct tmc_pages *tmc_pages,
+ struct device *dev, int node,
+ enum dma_data_direction dir, void **pages)
+{
+ int i, nr_pages;
+ dma_addr_t paddr;
+ struct page *page;
+
+ nr_pages = tmc_pages->nr_pages;
+ tmc_pages->daddrs = kcalloc(nr_pages, sizeof(*tmc_pages->daddrs),
+ GFP_KERNEL);
+ if (!tmc_pages->daddrs)
+ return -ENOMEM;
+ tmc_pages->pages = kcalloc(nr_pages, sizeof(*tmc_pages->pages),
+ GFP_KERNEL);
+ if (!tmc_pages->pages) {
+ kfree(tmc_pages->daddrs);
+ tmc_pages->daddrs = NULL;
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < nr_pages; i++) {
+ if (pages && pages[i]) {
+ page = virt_to_page(pages[i]);
+ /* Hold a refcount on the page */
+ get_page(page);
+ } else {
+ page = alloc_pages_node(node,
+ GFP_KERNEL | __GFP_ZERO, 0);
+ }
+ paddr = dma_map_page(dev, page, 0, PAGE_SIZE, dir);
+ if (dma_mapping_error(dev, paddr))
+ goto err;
+ tmc_pages->daddrs[i] = paddr;
+ tmc_pages->pages[i] = page;
+ }
+ return 0;
+err:
+ tmc_pages_free(tmc_pages, dev, dir);
+ return -ENOMEM;
+}
+
+static inline long
+tmc_sg_get_data_page_offset(struct tmc_sg_table *sg_table, dma_addr_t addr)
+{
+ return tmc_pages_get_offset(&sg_table->data_pages, addr);
+}
+
+static inline void tmc_free_table_pages(struct tmc_sg_table *sg_table)
+{
+ if (sg_table->table_vaddr)
+ vunmap(sg_table->table_vaddr);
+ tmc_pages_free(&sg_table->table_pages, sg_table->dev, DMA_TO_DEVICE);
+}
+
+static void tmc_free_data_pages(struct tmc_sg_table *sg_table)
+{
+ if (sg_table->data_vaddr)
+ vunmap(sg_table->data_vaddr);
+ tmc_pages_free(&sg_table->data_pages, sg_table->dev, DMA_FROM_DEVICE);
+}
+
+void tmc_free_sg_table(struct tmc_sg_table *sg_table)
+{
+ tmc_free_table_pages(sg_table);
+ tmc_free_data_pages(sg_table);
+}
+
+/*
+ * Alloc pages for the table. Since this will be used by the device,
+ * allocate the pages closer to the device (i.e, dev_to_node(dev)
+ * rather than the CPU node).
+ */
+static int tmc_alloc_table_pages(struct tmc_sg_table *sg_table)
+{
+ int rc;
+ struct tmc_pages *table_pages = &sg_table->table_pages;
+
+ rc = tmc_pages_alloc(table_pages, sg_table->dev,
+ dev_to_node(sg_table->dev),
+ DMA_TO_DEVICE, NULL);
+ if (rc)
+ return rc;
+ sg_table->table_vaddr = vmap(table_pages->pages,
+ table_pages->nr_pages,
+ VM_MAP,
+ PAGE_KERNEL);
+ if (!sg_table->table_vaddr)
+ rc = -ENOMEM;
+ else
+ sg_table->table_daddr = table_pages->daddrs[0];
+ return rc;
+}
+
+static int tmc_alloc_data_pages(struct tmc_sg_table *sg_table, void **pages)
+{
+ int rc;
+
+ /* Allocate data pages on the node requested by the caller */
+ rc = tmc_pages_alloc(&sg_table->data_pages,
+ sg_table->dev, sg_table->node,
+ DMA_FROM_DEVICE, pages);
+ if (!rc) {
+ sg_table->data_vaddr = vmap(sg_table->data_pages.pages,
+ sg_table->data_pages.nr_pages,
+ VM_MAP,
+ PAGE_KERNEL);
+ if (!sg_table->data_vaddr)
+ rc = -ENOMEM;
+ }
+ return rc;
+}
+
+/*
+ * tmc_alloc_sg_table: Allocate and setup dma pages for the TMC SG table
+ * and data buffers. TMC writes to the data buffers and reads from the SG
+ * Table pages.
+ *
+ * @dev - Device to which page should be DMA mapped.
+ * @node - Numa node for mem allocations
+ * @nr_tpages - Number of pages for the table entries.
+ * @nr_dpages - Number of pages for Data buffer.
+ * @pages - Optional list of virtual address of pages.
+ */
+struct tmc_sg_table *tmc_alloc_sg_table(struct device *dev,
+ int node,
+ int nr_tpages,
+ int nr_dpages,
+ void **pages)
+{
+ long rc;
+ struct tmc_sg_table *sg_table;
+
+ sg_table = kzalloc(sizeof(*sg_table), GFP_KERNEL);
+ if (!sg_table)
+ return ERR_PTR(-ENOMEM);
+ sg_table->data_pages.nr_pages = nr_dpages;
+ sg_table->table_pages.nr_pages = nr_tpages;
+ sg_table->node = node;
+ sg_table->dev = dev;
+
+ rc = tmc_alloc_data_pages(sg_table, pages);
+ if (!rc)
+ rc = tmc_alloc_table_pages(sg_table);
+ if (rc) {
+ tmc_free_sg_table(sg_table);
+ kfree(sg_table);
+ return ERR_PTR(rc);
+ }
+
+ return sg_table;
+}
+
+/*
+ * tmc_sg_table_sync_data_range: Sync the data buffer written
+ * by the device from @offset upto a @size bytes.
+ */
+void tmc_sg_table_sync_data_range(struct tmc_sg_table *table,
+ u64 offset, u64 size)
+{
+ int i, index, start;
+ int npages = DIV_ROUND_UP(size, PAGE_SIZE);
+ struct device *dev = table->dev;
+ struct tmc_pages *data = &table->data_pages;
+
+ start = offset >> PAGE_SHIFT;
+ for (i = start; i < (start + npages); i++) {
+ index = i % data->nr_pages;
+ dma_sync_single_for_cpu(dev, data->daddrs[index],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ }
+}
+
+/* tmc_sg_sync_table: Sync the page table */
+void tmc_sg_table_sync_table(struct tmc_sg_table *sg_table)
+{
+ int i;
+ struct device *dev = sg_table->dev;
+ struct tmc_pages *table_pages = &sg_table->table_pages;
+
+ for (i = 0; i < table_pages->nr_pages; i++)
+ dma_sync_single_for_device(dev, table_pages->daddrs[i],
+ PAGE_SIZE, DMA_TO_DEVICE);
+}
+
+/*
+ * tmc_sg_table_get_data: Get the buffer pointer for data @offset
+ * in the SG buffer. The @bufpp is updated to point to the buffer.
+ * Returns :
+ * the length of linear data available at @offset.
+ * or
+ * <= 0 if no data is available.
+ */
+ssize_t tmc_sg_table_get_data(struct tmc_sg_table *sg_table,
+ u64 offset, size_t len, char **bufpp)
+{
+ size_t size;
+ int pg_idx = offset >> PAGE_SHIFT;
+ int pg_offset = offset & (PAGE_SIZE - 1);
+ struct tmc_pages *data_pages = &sg_table->data_pages;
+
+ size = tmc_sg_table_buf_size(sg_table);
+ if (offset >= size)
+ return -EINVAL;
+
+ /* Make sure we don't go beyond the end */
+ len = (len < (size - offset)) ? len : size - offset;
+ /* Respect the page boundaries */
+ len = (len < (PAGE_SIZE - pg_offset)) ? len : (PAGE_SIZE - pg_offset);
+ if (len > 0)
+ *bufpp = page_address(data_pages->pages[pg_idx]) + pg_offset;
+ return len;
+}
+
static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
{
u32 axictl, sts;
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index 1d7cd58..cdb668b 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -7,6 +7,7 @@
#ifndef _CORESIGHT_TMC_H
#define _CORESIGHT_TMC_H
+#include <linux/dma-mapping.h>
#include <linux/miscdevice.h>
#define TMC_RSZ 0x004
@@ -160,6 +161,38 @@ struct tmc_drvdata {
u32 etr_caps;
};
+/**
+ * struct tmc_pages - Collection of pages used for SG.
+ * @nr_pages: Number of pages in the list.
+ * @daddrs: Array of DMA'able page address.
+ * @pages: Array pages for the buffer.
+ */
+struct tmc_pages {
+ int nr_pages;
+ dma_addr_t *daddrs;
+ struct page **pages;
+};
+
+/*
+ * struct tmc_sg_table - Generic SG table for TMC
+ * @dev: Device for DMA allocations
+ * @table_vaddr: Contiguous Virtual address for PageTable
+ * @data_vaddr: Contiguous Virtual address for Data Buffer
+ * @table_daddr: DMA address of the PageTable base
+ * @node: Node for Page allocations
+ * @table_pages: List of pages & dma address for Table
+ * @data_pages: List of pages & dma address for Data
+ */
+struct tmc_sg_table {
+ struct device *dev;
+ void *table_vaddr;
+ void *data_vaddr;
+ dma_addr_t table_daddr;
+ int node;
+ struct tmc_pages table_pages;
+ struct tmc_pages data_pages;
+};
+
/* Generic functions */
void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata);
void tmc_flush_and_stop(struct tmc_drvdata *drvdata);
@@ -215,4 +248,21 @@ static inline bool tmc_etr_has_cap(struct tmc_drvdata *drvdata, u32 cap)
return !!(drvdata->etr_caps & cap);
}
+struct tmc_sg_table *tmc_alloc_sg_table(struct device *dev,
+ int node,
+ int nr_tpages,
+ int nr_dpages,
+ void **pages);
+void tmc_free_sg_table(struct tmc_sg_table *sg_table);
+void tmc_sg_table_sync_table(struct tmc_sg_table *sg_table);
+void tmc_sg_table_sync_data_range(struct tmc_sg_table *table,
+ u64 offset, u64 size);
+ssize_t tmc_sg_table_get_data(struct tmc_sg_table *sg_table,
+ u64 offset, size_t len, char **bufpp);
+static inline unsigned long
+tmc_sg_table_buf_size(struct tmc_sg_table *sg_table)
+{
+ return sg_table->data_pages.nr_pages << PAGE_SHIFT;
+}
+
#endif
--
2.7.4
^ permalink raw reply related
* [PATCH v2 04/12] coresight: tmc-etr: Disallow perf mode
From: Suzuki K Poulose @ 2018-05-29 13:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, mathieu.poirier, mike.leach, robert.walker,
coresight, devicetree, robh, frowand.list, Suzuki K Poulose
In-Reply-To: <1527599737-28408-1-git-send-email-suzuki.poulose@arm.com>
We don't support ETR in perf mode yet. So, don't
even try to enable the hardware, even by mistake.
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/hwtracing/coresight/coresight-tmc-etr.c | 28 ++-----------------------
1 file changed, 2 insertions(+), 26 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 1de05c9..18c9a18 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -211,32 +211,8 @@ static int tmc_enable_etr_sink_sysfs(struct coresight_device *csdev)
static int tmc_enable_etr_sink_perf(struct coresight_device *csdev)
{
- int ret = 0;
- unsigned long flags;
- struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
-
- spin_lock_irqsave(&drvdata->spinlock, flags);
- if (drvdata->reading) {
- ret = -EINVAL;
- goto out;
- }
-
- /*
- * In Perf mode there can be only one writer per sink. There
- * is also no need to continue if the ETR is already operated
- * from sysFS.
- */
- if (drvdata->mode != CS_MODE_DISABLED) {
- ret = -EINVAL;
- goto out;
- }
-
- drvdata->mode = CS_MODE_PERF;
- tmc_etr_enable_hw(drvdata);
-out:
- spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
- return ret;
+ /* We don't support perf mode yet ! */
+ return -EINVAL;
}
static int tmc_enable_etr_sink(struct coresight_device *csdev, u32 mode)
--
2.7.4
^ permalink raw reply related
* [PATCH v2 02/12] coresight: tmc: Hide trace buffer handling for file read
From: Suzuki K Poulose @ 2018-05-29 13:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, mathieu.poirier, mike.leach, robert.walker,
coresight, devicetree, robh, frowand.list, Suzuki K Poulose
In-Reply-To: <1527599737-28408-1-git-send-email-suzuki.poulose@arm.com>
At the moment we adjust the buffer pointers for reading the trace
data via misc device in the common code for ETF/ETB and ETR. Since
we are going to change how we manage the buffer for ETR, let us
move the buffer manipulation to the respective driver files, hiding
it from the common code. We do so by adding type specific helpers
for finding the length of data and the pointer to the buffer,
for a given length at a file position.
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
drivers/hwtracing/coresight/coresight-tmc-etf.c | 18 +++++++++++
drivers/hwtracing/coresight/coresight-tmc-etr.c | 34 ++++++++++++++++++++
drivers/hwtracing/coresight/coresight-tmc.c | 41 ++++++++++++++-----------
drivers/hwtracing/coresight/coresight-tmc.h | 4 +++
4 files changed, 79 insertions(+), 18 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c
index 61d849b..73160cd 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etf.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c
@@ -109,6 +109,24 @@ static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
CS_LOCK(drvdata->base);
}
+/*
+ * Return the available trace data in the buffer from @pos, with
+ * a maximum limit of @len, updating the @bufpp on where to
+ * find it.
+ */
+ssize_t tmc_etb_get_sysfs_trace(struct tmc_drvdata *drvdata,
+ loff_t pos, size_t len, char **bufpp)
+{
+ ssize_t actual = len;
+
+ /* Adjust the len to available size @pos */
+ if (pos + actual > drvdata->len)
+ actual = drvdata->len - pos;
+ if (actual > 0)
+ *bufpp = drvdata->buf + pos;
+ return actual;
+}
+
static int tmc_enable_etf_sink_sysfs(struct coresight_device *csdev)
{
int ret = 0;
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index 02f747a..f88342d 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -58,6 +58,40 @@ static void tmc_etr_enable_hw(struct tmc_drvdata *drvdata)
CS_LOCK(drvdata->base);
}
+/*
+ * Return the available trace data in the buffer @pos, with a maximum
+ * limit of @len, also updating the @bufpp on where to find it.
+ */
+ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata,
+ loff_t pos, size_t len, char **bufpp)
+{
+ ssize_t actual = len;
+ char *bufp = drvdata->buf + pos;
+ char *bufend = (char *)(drvdata->vaddr + drvdata->size);
+
+ /* Adjust the len to available size @pos */
+ if (pos + actual > drvdata->len)
+ actual = drvdata->len - pos;
+
+ if (actual <= 0)
+ return actual;
+
+ /*
+ * Since we use a circular buffer, with trace data starting
+ * @drvdata->buf, possibly anywhere in the buffer @drvdata->vaddr,
+ * wrap the current @pos to within the buffer.
+ */
+ if (bufp >= bufend)
+ bufp -= drvdata->size;
+ /*
+ * For simplicity, avoid copying over a wrapped around buffer.
+ */
+ if ((bufp + actual) > bufend)
+ actual = bufend - bufp;
+ *bufpp = bufp;
+ return actual;
+}
+
static void tmc_etr_dump_hw(struct tmc_drvdata *drvdata)
{
const u32 *barrier;
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 456f122..bb57e7f 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -123,35 +123,40 @@ static int tmc_open(struct inode *inode, struct file *file)
return 0;
}
+static inline ssize_t tmc_get_sysfs_trace(struct tmc_drvdata *drvdata,
+ loff_t pos, size_t len, char **bufpp)
+{
+ switch (drvdata->config_type) {
+ case TMC_CONFIG_TYPE_ETB:
+ case TMC_CONFIG_TYPE_ETF:
+ return tmc_etb_get_sysfs_trace(drvdata, pos, len, bufpp);
+ case TMC_CONFIG_TYPE_ETR:
+ return tmc_etr_get_sysfs_trace(drvdata, pos, len, bufpp);
+ }
+
+ return -EINVAL;
+}
+
static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
loff_t *ppos)
{
+ char *bufp;
+ ssize_t actual;
struct tmc_drvdata *drvdata = container_of(file->private_data,
struct tmc_drvdata, miscdev);
- char *bufp = drvdata->buf + *ppos;
+ actual = tmc_get_sysfs_trace(drvdata, *ppos, len, &bufp);
+ if (actual <= 0)
+ return 0;
- if (*ppos + len > drvdata->len)
- len = drvdata->len - *ppos;
-
- if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
- if (bufp == (char *)(drvdata->vaddr + drvdata->size))
- bufp = drvdata->vaddr;
- else if (bufp > (char *)(drvdata->vaddr + drvdata->size))
- bufp -= drvdata->size;
- if ((bufp + len) > (char *)(drvdata->vaddr + drvdata->size))
- len = (char *)(drvdata->vaddr + drvdata->size) - bufp;
- }
-
- if (copy_to_user(data, bufp, len)) {
+ if (copy_to_user(data, bufp, actual)) {
dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
return -EFAULT;
}
- *ppos += len;
+ *ppos += actual;
+ dev_dbg(drvdata->dev, "%zu bytes copied\n", actual);
- dev_dbg(drvdata->dev, "%s: %zu bytes copied, %d bytes left\n",
- __func__, len, (int)(drvdata->len - *ppos));
- return len;
+ return actual;
}
static int tmc_release(struct inode *inode, struct file *file)
diff --git a/drivers/hwtracing/coresight/coresight-tmc.h b/drivers/hwtracing/coresight/coresight-tmc.h
index dfaff07..1d7cd58 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.h
+++ b/drivers/hwtracing/coresight/coresight-tmc.h
@@ -172,10 +172,14 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata);
extern const struct coresight_ops tmc_etb_cs_ops;
extern const struct coresight_ops tmc_etf_cs_ops;
+ssize_t tmc_etb_get_sysfs_trace(struct tmc_drvdata *drvdata,
+ loff_t pos, size_t len, char **bufpp);
/* ETR functions */
int tmc_read_prepare_etr(struct tmc_drvdata *drvdata);
int tmc_read_unprepare_etr(struct tmc_drvdata *drvdata);
extern const struct coresight_ops tmc_etr_cs_ops;
+ssize_t tmc_etr_get_sysfs_trace(struct tmc_drvdata *drvdata,
+ loff_t pos, size_t len, char **bufpp);
#define TMC_REG_PAIR(name, lo_off, hi_off) \
--
2.7.4
^ permalink raw reply related
* [PATCH v2 01/12] coresight: ETM: Add support for Arm Cortex-A73 and Cortex-A35
From: Suzuki K Poulose @ 2018-05-29 13:15 UTC (permalink / raw)
To: linux-arm-kernel
Cc: linux-kernel, mathieu.poirier, mike.leach, robert.walker,
coresight, devicetree, robh, frowand.list, Suzuki K Poulose
In-Reply-To: <1527599737-28408-1-git-send-email-suzuki.poulose@arm.com>
Add ETM PIDs of the Arm cortex-A CPUs to the white list of ETMs.
While at it add a helper macro to make it easier to add the new
entries.
Cc: Mathieu Poirier <mathieu.poirier@linaro.org>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
---
Changes since last version:
- Use ETM's ID register to dump the version, rather than hard
coding it for each CPU.
---
drivers/hwtracing/coresight/coresight-etm4x.c | 31 ++++++++++++---------------
1 file changed, 14 insertions(+), 17 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index 9bc04c5..1d94ebe 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -1027,7 +1027,8 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
}
pm_runtime_put(&adev->dev);
- dev_info(dev, "%s initialized\n", (char *)id->data);
+ dev_info(dev, "CPU%d: ETM v%d.%d initialized\n",
+ drvdata->cpu, drvdata->arch >> 4, drvdata->arch & 0xf);
if (boot_enable) {
coresight_enable(drvdata->csdev);
@@ -1045,23 +1046,19 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
return ret;
}
+#define ETM4x_AMBA_ID(pid) \
+ { \
+ .id = pid, \
+ .mask = 0x000fffff, \
+ }
+
static const struct amba_id etm4_ids[] = {
- { /* ETM 4.0 - Cortex-A53 */
- .id = 0x000bb95d,
- .mask = 0x000fffff,
- .data = "ETM 4.0",
- },
- { /* ETM 4.0 - Cortex-A57 */
- .id = 0x000bb95e,
- .mask = 0x000fffff,
- .data = "ETM 4.0",
- },
- { /* ETM 4.0 - A72, Maia, HiSilicon */
- .id = 0x000bb95a,
- .mask = 0x000fffff,
- .data = "ETM 4.0",
- },
- { 0, 0},
+ ETM4x_AMBA_ID(0x000bb95d), /* Cortex-A53 */
+ ETM4x_AMBA_ID(0x000bb95e), /* Cortex-A57 */
+ ETM4x_AMBA_ID(0x000bb95a), /* Cortex-A72 */
+ ETM4x_AMBA_ID(0x000bb959), /* Cortex-A73 */
+ ETM4x_AMBA_ID(0x000bb9da), /* Cortex-A35 */
+ {},
};
static struct amba_driver etm4x_driver = {
--
2.7.4
^ permalink raw reply related
* [PATCH 05/19] serdev: Introduce modalias field
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Rob Herring, Johan Hovold
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
Name of the driver to use with this device, or an alias for that name,
or an alias for the part.
Required for hardware that is neither an of_node nor part of the ACPI
table.
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
include/linux/serdev.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index 62f1b085a794..bb3b9599c652 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -54,6 +54,7 @@ struct serdev_device {
const struct serdev_device_ops *ops;
struct completion write_comp;
struct mutex write_lock;
+ char modalias[SERDEV_NAME_SIZE];
};
static inline struct serdev_device *to_serdev_device(struct device *d)
--
2.17.0
^ permalink raw reply related
* RE: [GIT PULL 16/20] lightnvm: error handling when whole line is bad
From: Konopko, Igor J @ 2018-05-29 13:15 UTC (permalink / raw)
To: Javier Gonzalez, Matias Bjorling
Cc: Jens Axboe, linux-block@vger.kernel.org, LKML,
Dziegielewski, Marcin
In-Reply-To: <C161E678-ADEE-4E05-AC19-B54358005532@cnexlabs.com>
> From: Javier Gonzalez [mailto:javier@cnexlabs.com]
> This case cannot occur on the only user of the function
> (pblk_recov_l2p()). On the previous check (pblk_line_was_written()), we
> verify the state of the line and the position of the first good chunk. In
> the case of a bad line (less chunks than a given threshold to allow
> emeta), the recovery will not be carried out in the line.
You are right. It looks that during my testing there was some inconsistency between chunks state table which is verified inside pblk_line_was_written() and blk_bitmap which was read from emeta and is verified in pblk_line_smeta_start(). I'm living decision to maintainers whether we should keep this sanity check or not - it really just pass gracefully the result from pblk_line_smeta_start() where similar sanity check is present.
Igor
^ permalink raw reply
* [PATCH 06/19] serdev: Support bus matching with modalias field
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Rob Herring, Johan Hovold,
Greg Kroah-Hartman, Jiri Slaby
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
Match devices to drivers by their modalias when the ACPI and the OF
match fails.
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/tty/serdev/core.c | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index df93b727e984..2c79f47fc0db 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -79,8 +79,23 @@ static const struct device_type serdev_ctrl_type = {
.release = serdev_ctrl_release,
};
+static int serdev_match_id(const struct serdev_device_id *id,
+ const struct serdev_device *sdev)
+{
+ while (id->name[0]) {
+ if (!strcmp(sdev->modalias, id->name))
+ return 1;
+ id++;
+ }
+
+ return 0;
+}
+
static int serdev_device_match(struct device *dev, struct device_driver *drv)
{
+ const struct serdev_device *sdev = to_serdev_device(dev);
+ const struct serdev_device_driver *sdrv = to_serdev_device_driver(drv);
+
if (!is_serdev_device(dev))
return 0;
@@ -88,7 +103,13 @@ static int serdev_device_match(struct device *dev, struct device_driver *drv)
if (acpi_driver_match_device(dev, drv))
return 1;
- return of_driver_match_device(dev, drv);
+ if (of_driver_match_device(dev, drv))
+ return 1;
+
+ if (sdrv->id_table)
+ return serdev_match_id(sdrv->id_table, sdev);
+
+ return strcmp(sdev->modalias, drv->name) == 0;
}
/**
--
2.17.0
^ permalink raw reply related
* [PATCH 07/19] serdev: Allows dynamic creation of devices via sysfs
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Rob Herring, Johan Hovold,
Greg Kroah-Hartman, Jiri Slaby
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
Allow creating and deleting devices via sysfs. Devices created will be
matched to serdev drivers via modalias (the string provided by the user)
and deleted via their name. Eg:
# Create device
root@qt5022:~# echo ttydev > /sys/bus/serial/devices/serial0/new_device
# Delete device
root@qt5022:~#
echo serial0-0 > /sys/bus/serial/devices/serial0/delete_device
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/tty/serdev/core.c | 60 +++++++++++++++++++++++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index 2c79f47fc0db..e695fa649a6d 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -75,7 +75,67 @@ static void serdev_ctrl_release(struct device *dev)
kfree(ctrl);
}
+static ssize_t
+new_device_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct serdev_controller *ctrl = to_serdev_controller(dev);
+ struct serdev_device *serdev;
+ int err;
+ char *nline;
+
+ serdev = serdev_device_alloc(ctrl);
+ if (!serdev)
+ return -ENOMEM;
+
+ nline = strchr(buf, '\n');
+ if (nline)
+ *nline = '\0';
+
+ strncpy(serdev->modalias, buf, SERDEV_NAME_SIZE);
+
+ err = serdev_device_add(serdev);
+ if (err) {
+ serdev_device_put(serdev);
+ return err;
+ }
+
+ return count;
+}
+static DEVICE_ATTR_WO(new_device);
+
+static ssize_t
+delete_device_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct serdev_controller *ctrl = to_serdev_controller(dev);
+ struct serdev_device *serdev = ctrl->serdev;
+ char *nline;
+
+ nline = strchr(buf, '\n');
+ if (nline)
+ *nline = '\0';
+
+ if (!ctrl->serdev ||
+ strncmp(dev_name(&serdev->dev), buf, SERDEV_NAME_SIZE))
+ return -ENODEV;
+
+ serdev_device_remove(serdev);
+
+ return count;
+}
+static DEVICE_ATTR_IGNORE_LOCKDEP(delete_device, 0200, NULL,
+ delete_device_store);
+
+static struct attribute *serdev_ctrl_attrs[] = {
+ &dev_attr_new_device.attr,
+ &dev_attr_delete_device.attr,
+ NULL
+};
+ATTRIBUTE_GROUPS(serdev_ctrl);
+
static const struct device_type serdev_ctrl_type = {
+ .groups = serdev_ctrl_groups,
.release = serdev_ctrl_release,
};
--
2.17.0
^ permalink raw reply related
* [PATCH 08/19] serdev: Provide modalias attribute for modalias devices
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Rob Herring, Johan Hovold,
Greg Kroah-Hartman, Jiri Slaby
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
Create modalias sysfs attribute for modalias devices.
This is required by modprobe/udev to autoload the serdev driver.
Eg:
root@qt5022:~# cat /sys/bus/serial/devices/serial1-0/modalias
serdev:ttydev
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/tty/serdev/core.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index e695fa649a6d..a9c935f68076 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -23,12 +23,17 @@ static ssize_t modalias_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
int len;
+ struct serdev_device *serdev = to_serdev_device(dev);
len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1);
if (len != -ENODEV)
return len;
- return of_device_modalias(dev, buf, PAGE_SIZE);
+ len = of_device_modalias(dev, buf, PAGE_SIZE);
+ if (len != -ENODEV)
+ return len;
+
+ return sprintf(buf, "%s%s\n", SERDEV_MODULE_PREFIX, serdev->modalias);
}
static DEVICE_ATTR_RO(modalias);
--
2.17.0
^ permalink raw reply related
* [PATCH 12/19] Bluetooth: hci_ll: MODULE_DEVICE_TABLE(serdev)
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Marcel Holtmann, Johan Hedberg,
Rob Herring, Johan Hovold, linux-bluetooth
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
Export serdev table to the module header, allowing module autoload via
udev/modprobe.
Cc: Marcel Holtmann <marcel@holtmann.org>
Cc: Johan Hedberg <johan.hedberg@gmail.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Cc: linux-bluetooth@vger.kernel.org
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/bluetooth/hci_ll.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c
index c31942c9b466..5c36d8967a00 100644
--- a/drivers/bluetooth/hci_ll.c
+++ b/drivers/bluetooth/hci_ll.c
@@ -789,8 +789,10 @@ static struct serdev_device_id hci_ti_id[] = {
{ "wl1831-st", },
{ "wl1835-st", },
{ "wl1837-st", },
+ { "hci-ti", },
{},
};
+MODULE_DEVICE_TABLE(serdev, hci_ti_id);
static struct serdev_device_driver hci_ti_drv = {
.driver = {
--
2.17.0
^ permalink raw reply related
* [PATCH 13/19] Bluetooth: hci_nokia: MODULE_DEVICE_TABLE(serdev)
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Marcel Holtmann, Johan Hedberg,
Rob Herring, Johan Hovold, linux-bluetooth
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
Export serdev table to the module header, allowing module autoload via
udev/modprobe.
Cc: Marcel Holtmann <marcel@holtmann.org>
Cc: Johan Hedberg <johan.hedberg@gmail.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Cc: linux-bluetooth@vger.kernel.org
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/bluetooth/hci_nokia.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/bluetooth/hci_nokia.c b/drivers/bluetooth/hci_nokia.c
index e32dfcd56b8d..c283e1ca6064 100644
--- a/drivers/bluetooth/hci_nokia.c
+++ b/drivers/bluetooth/hci_nokia.c
@@ -803,8 +803,10 @@ MODULE_DEVICE_TABLE(of, nokia_bluetooth_of_match);
static struct serdev_device_id nokia_bluetooth_serdev_id[] = {
{ "hp4-bluetooth", },
+ { "nokia-bluetooth", },
{},
};
+MODULE_DEVICE_TABLE(serdev, nokia_bluetooth_serdev_id);
static struct serdev_device_driver nokia_bluetooth_serdev_driver = {
.probe = nokia_bluetooth_serdev_probe,
--
2.17.0
^ permalink raw reply related
* [PATCH 14/19] mfd: rave-sp: MODULE_DEVICE_TABLE(serdev)
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Lee Jones, Rob Herring, Johan Hovold
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
Export serdev table to the module header, allowing module autoload via
udev/modprobe.
Cc: Lee Jones <lee.jones@linaro.org>
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/mfd/rave-sp.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/mfd/rave-sp.c b/drivers/mfd/rave-sp.c
index 5c858e784a89..807c237e061b 100644
--- a/drivers/mfd/rave-sp.c
+++ b/drivers/mfd/rave-sp.c
@@ -694,12 +694,19 @@ static int rave_sp_probe(struct serdev_device *serdev)
MODULE_DEVICE_TABLE(of, rave_sp_dt_ids);
+static struct serdev_device_id rave_sp_serdev_id[] = {
+ { "rave-sp", },
+ {},
+};
+MODULE_DEVICE_TABLE(serdev, rave_sp_serdev_id);
+
static struct serdev_device_driver rave_sp_drv = {
.probe = rave_sp_probe,
.driver = {
.name = "rave-sp",
.of_match_table = rave_sp_dt_ids,
},
+ .id_table = rave_sp_serdev_id,
};
module_serdev_device_driver(rave_sp_drv);
--
2.17.0
^ permalink raw reply related
* [PATCH 15/19] net: qualcomm: MODULE_DEVICE_TABLE(serdev)
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Lino Sanfilippo, David S . Miller,
Stefan Wahren, Rob Herring, Johan Hovold, netdev
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
Export serdev table to the module header, allowing module autoload via
udev/modprobe.
Cc: Lino Sanfilippo <LinoSanfilippo@gmx.de>
Cc: David S. Miller <davem@davemloft.net>
Cc: Stefan Wahren <stefan.wahren@i2se.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Cc: netdev@vger.kernel.org
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/net/ethernet/qualcomm/qca_uart.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/net/ethernet/qualcomm/qca_uart.c b/drivers/net/ethernet/qualcomm/qca_uart.c
index db6068cd7a1f..bb7aed805083 100644
--- a/drivers/net/ethernet/qualcomm/qca_uart.c
+++ b/drivers/net/ethernet/qualcomm/qca_uart.c
@@ -405,6 +405,12 @@ static void qca_uart_remove(struct serdev_device *serdev)
free_netdev(qca->net_dev);
}
+static struct serdev_device_id qca_uart_serdev_id[] = {
+ { QCAUART_DRV_NAME, },
+ {},
+};
+MODULE_DEVICE_TABLE(serdev, qca_uart_serdev_id);
+
static struct serdev_device_driver qca_uart_driver = {
.probe = qca_uart_probe,
.remove = qca_uart_remove,
@@ -412,6 +418,7 @@ static struct serdev_device_driver qca_uart_driver = {
.name = QCAUART_DRV_NAME,
.of_match_table = of_match_ptr(qca_uart_of_match),
},
+ .id_table = qca_uart_serdev_id,
};
module_serdev_device_driver(qca_uart_driver);
--
2.17.0
^ permalink raw reply related
* Re: [REVIEW][PATCH 0/6] Wrapping up the vfs support for unprivileged mounts
From: Eric W. Biederman @ 2018-05-29 13:12 UTC (permalink / raw)
To: Dave Chinner
Cc: Theodore Y. Ts'o, Linux Containers, linux-fsdevel,
Seth Forshee, Serge E. Hallyn, Christian Brauner, linux-kernel
In-Reply-To: <20180525035716.GE10363@dastard>
Dave Chinner <david@fromorbit.com> writes:
> On Thu, May 24, 2018 at 06:23:30PM -0500, Eric W. Biederman wrote:
>> "Theodore Y. Ts'o" <tytso@mit.edu> writes:
>>
>> > On Wed, May 23, 2018 at 06:22:56PM -0500, Eric W. Biederman wrote:
>> >>
>> >> Very slowly the work has been progressing to ensure the vfs has the
>> >> necessary support for mounting filesystems without privilege.
>> >
>> > What's the thinking behind how system administrators and/or file
>> > systems would configure whether or not a particular file system type
>> > will be allowed to be mounted w/o privilege?
>>
>> The mechanism is .fs_flags in file_system_type. If the FS_USERNS_MOUNT
>> flag is set then root in a user namespace (AKA an unprivileged user)
>> will be allowed to mount to mount the filesystem.
>>
>> There are very real concerns about attacking a filesystem with an
>> invalid filesystem image, or by a malicious protocol speaker. So I
>> don't want to enable anything without the file system maintainers
>> consent and without a reasonable expecation that neither a system wide
>> denial of service attack nor a privilege escalation attack is possible
>> from if the filesystem is enabled.
>>
>> So at a practical level what we have in the vfs is the non-fuse specific
>> bits that enable unprivileged mounts of fuse. Things like handling
>> of unmapped uid and gids, how normally trusted xattrs are dealt with,
>> etc.
>>
>> A big practical one for me is that if either the uid or gid is not
>> mapped the vfs avoids writing to the inode.
>>
>> Right now my practical goal is to be able to say: "Go run your
>> filesystem in userspace with fuse if you want stronger security
>> guarantees." I think that will be enough to make removable media
>> reasonably safe from privilege escalation attacks.
>>
>> There is enough code in most filesystems that I don't know what our
>> chances of locking down very many of them are. But I figure a few more
>> of them are possible.
>
> I'm not sure we need to - fusefs-lkl gives users the ability to
> mount any of the kernel filesystems via fuse without us needing to
> support unprivileged kernel mounts for those filesystems.
Maybe.
That certainly seems like a good proof of concept for running
ordinary filesystems with fuse. If we are going to rely on it
someone probably needs to do the work to merge arch/lkl into the
main tree. My quick look suggests that the lkl port lags behind
a little bit and has just made it to 4.16.
Is fusefs-lkl valuable for testing filesystems? If xfs-tests were to
have a mode that used that used the fuse protocol for testing and
fuzzing filesystems without the full weight of the kernel in the middle
that might encourage people to suppor this kind of things as well.
Eric
^ permalink raw reply
* Re: [PATCH v8 4/6] cpuset: Make generate_sched_domains() recognize isolated_cpus
From: Juri Lelli @ 2018-05-29 13:12 UTC (permalink / raw)
To: Waiman Long
Cc: Tejun Heo, Li Zefan, Johannes Weiner, Peter Zijlstra, Ingo Molnar,
cgroups, linux-kernel, linux-doc, kernel-team, pjt, luto,
Mike Galbraith, torvalds, Roman Gushchin
In-Reply-To: <8164a41b-3218-c618-64a6-52747344c4db@redhat.com>
On 29/05/18 08:40, Waiman Long wrote:
> On 05/29/2018 02:27 AM, Juri Lelli wrote:
> > On 28/05/18 21:24, Waiman Long wrote:
> >> On 05/28/2018 09:12 PM, Waiman Long wrote:
> >>> On 05/24/2018 06:28 AM, Juri Lelli wrote:
> >>>> On 17/05/18 16:55, Waiman Long wrote:
> >>>>
> >>>> [...]
> >>>>
> >>>>> @@ -849,7 +860,12 @@ static void rebuild_sched_domains_locked(void)
> >>>>> * passing doms with offlined cpu to partition_sched_domains().
> >>>>> * Anyways, hotplug work item will rebuild sched domains.
> >>>>> */
> >>>>> - if (!cpumask_equal(top_cpuset.effective_cpus, cpu_active_mask))
> >>>>> + if (!top_cpuset.isolation_count &&
> >>>>> + !cpumask_equal(top_cpuset.effective_cpus, cpu_active_mask))
> >>>>> + goto out;
> >>>>> +
> >>>>> + if (top_cpuset.isolation_count &&
> >>>>> + !cpumask_subset(top_cpuset.effective_cpus, cpu_active_mask))
> >>>>> goto out;
> >>>> Do we cover the case in which hotplug removed one of the isolated cpus
> >>>> from cpu_active_mask?
> >>> Yes, you are right. That is the remnant of my original patch that allows
> >>> only one isolated_cpus at root. Thanks for spotting that.
> >> I am sorry. I would like to take it back my previous comment. The code
> >> above looks for inconsistency in the state of the effective_cpus mask to
> >> find out if it is racing with a hotplug event. If it is, we can skip the
> >> domain generation as the hotplug event will do that too. The checks are
> >> still valid with the current patchset. So I don't think we need to make
> >> any change here.
> > Yes, these checks are valid, but don't we also need to check for hotplug
> > races w.r.t. isolated CPUs (of some other sub domain)?
>
> It is not actually a race. Both the hotplug event and any changes to cpu
> lists or flags are serialized by the cpuset_mutex. It is just that we
> may be doing the same work twice that we are wasting cpu cycles. So we
> are doing a quick check to avoid this. The check isn't exhaustive and we
> can certainly miss some cases. Doing a more throughout check may need as
> much time as doing the sched domain generation itself and so you are
> actually wasting more CPU cycles on average as the chance of a hotplug
> event is very low.
Fair enough.
Thanks,
- Juri
^ permalink raw reply
* [PATCH 16/19] serdev: ttyport: Move serport structure to its own header
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Rob Herring, Johan Hovold,
Greg Kroah-Hartman, Jiri Slaby
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
This way we can reuse this structure in other modules.
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/tty/serdev/serdev-ttyport.c | 9 +--------
drivers/tty/serdev/serport.h | 16 ++++++++++++++++
2 files changed, 17 insertions(+), 8 deletions(-)
create mode 100644 drivers/tty/serdev/serport.h
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
index fa1672993b4c..4acc5f41dc67 100644
--- a/drivers/tty/serdev/serdev-ttyport.c
+++ b/drivers/tty/serdev/serdev-ttyport.c
@@ -7,17 +7,10 @@
#include <linux/tty.h>
#include <linux/tty_driver.h>
#include <linux/poll.h>
+#include "serport.h"
#define SERPORT_ACTIVE 1
-struct serport {
- struct tty_port *port;
- struct tty_struct *tty;
- struct tty_driver *tty_drv;
- int tty_idx;
- unsigned long flags;
-};
-
/*
* Callback functions from the tty port.
*/
diff --git a/drivers/tty/serdev/serport.h b/drivers/tty/serdev/serport.h
new file mode 100644
index 000000000000..15bc1ff6326e
--- /dev/null
+++ b/drivers/tty/serdev/serport.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2016-2017 Linaro Ltd., Rob Herring <robh@kernel.org>
+ */
+#ifndef _SERPORT_H
+#define _SERPORT_H
+
+struct serport {
+ struct tty_port *port;
+ struct tty_struct *tty;
+ struct tty_driver *tty_drv;
+ int tty_idx;
+ unsigned long flags;
+};
+
+#endif
--
2.17.0
^ permalink raw reply related
* [PATCH 17/19] serdev: Mark controllers compatible with ttyport
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Rob Herring, Johan Hovold,
Greg Kroah-Hartman, Jiri Slaby
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
This allows us to treat differently this controllers, by creating a tty
compatibility layer.
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/tty/serdev/serdev-ttyport.c | 1 +
include/linux/serdev.h | 1 +
2 files changed, 2 insertions(+)
diff --git a/drivers/tty/serdev/serdev-ttyport.c b/drivers/tty/serdev/serdev-ttyport.c
index 4acc5f41dc67..ae961260e4a4 100644
--- a/drivers/tty/serdev/serdev-ttyport.c
+++ b/drivers/tty/serdev/serdev-ttyport.c
@@ -276,6 +276,7 @@ struct device *serdev_tty_port_register(struct tty_port *port,
serport->tty_drv = drv;
ctrl->ops = &ctrl_ops;
+ ctrl->is_ttyport = true;
old_ops = port->client_ops;
port->client_ops = &client_ops;
diff --git a/include/linux/serdev.h b/include/linux/serdev.h
index bb3b9599c652..07d63933bdb9 100644
--- a/include/linux/serdev.h
+++ b/include/linux/serdev.h
@@ -116,6 +116,7 @@ struct serdev_controller {
unsigned int nr;
struct serdev_device *serdev;
const struct serdev_controller_ops *ops;
+ bool is_ttyport;
};
static inline struct serdev_controller *to_serdev_controller(struct device *d)
--
2.17.0
^ permalink raw reply related
* [PATCH 18/19] serdev: ttydev: Serdev driver that creates an standard TTY port
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Rob Herring, Johan Hovold,
Greg Kroah-Hartman, Jiri Slaby
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
Standard TTY port that can be loaded/unloaded via serdev sysfs. This
serdev driver can only be used by serdev controllers that are compatible
with ttyport.
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/tty/serdev/Kconfig | 11 +++++
drivers/tty/serdev/Makefile | 2 +
drivers/tty/serdev/serdev-ttydev.c | 70 ++++++++++++++++++++++++++++++
3 files changed, 83 insertions(+)
create mode 100644 drivers/tty/serdev/serdev-ttydev.c
diff --git a/drivers/tty/serdev/Kconfig b/drivers/tty/serdev/Kconfig
index 1dbc8352e027..d19bf689a424 100644
--- a/drivers/tty/serdev/Kconfig
+++ b/drivers/tty/serdev/Kconfig
@@ -21,4 +21,15 @@ config SERIAL_DEV_CTRL_TTYPORT
depends on SERIAL_DEV_BUS != m
default y
+config SERIAL_DEV_CTRL_TTYDEV
+ tristate "TTY port dynamically loaded by the Serial Device Bus"
+ help
+ Say Y here if you want to create a bridge driver between the Serial
+ device bus and the TTY chardevice. This driver can be dynamically
+ loaded/unloaded by the Serial Device Bus.
+
+ If unsure, say Y.
+ depends on SERIAL_DEV_CTRL_TTYPORT
+ default m
+
endif
diff --git a/drivers/tty/serdev/Makefile b/drivers/tty/serdev/Makefile
index 0cbdb9444d9d..5c807b77d12d 100644
--- a/drivers/tty/serdev/Makefile
+++ b/drivers/tty/serdev/Makefile
@@ -3,3 +3,5 @@ serdev-objs := core.o
obj-$(CONFIG_SERIAL_DEV_BUS) += serdev.o
obj-$(CONFIG_SERIAL_DEV_CTRL_TTYPORT) += serdev-ttyport.o
+
+obj-$(CONFIG_SERIAL_DEV_CTRL_TTYDEV) += serdev-ttydev.o
diff --git a/drivers/tty/serdev/serdev-ttydev.c b/drivers/tty/serdev/serdev-ttydev.c
new file mode 100644
index 000000000000..66479d6534dd
--- /dev/null
+++ b/drivers/tty/serdev/serdev-ttydev.c
@@ -0,0 +1,70 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018 Ricardo Ribalda <ricardo.ribalda@gmail.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/serdev.h>
+#include <linux/tty.h>
+#include "serport.h"
+
+static int ttydev_serdev_probe(struct serdev_device *serdev)
+{
+ struct serdev_controller *ctrl = serdev->ctrl;
+ struct serport *serport;
+ struct device *dev;
+
+ if (!ctrl->is_ttyport)
+ return -ENODEV;
+
+ serport = serdev_controller_get_drvdata(ctrl);
+
+ dev = tty_register_device_attr(serport->tty_drv, serport->tty_idx,
+ &serdev->dev, NULL, NULL);
+
+ return dev ? 0 : PTR_ERR(dev);
+}
+
+static void ttydev_serdev_remove(struct serdev_device *serdev)
+{
+ struct serdev_controller *ctrl = serdev->ctrl;
+ struct serport *serport;
+
+ serport = serdev_controller_get_drvdata(ctrl);
+ tty_unregister_device(serport->tty_drv, serport->tty_idx);
+}
+
+static const struct serdev_device_id ttydev_serdev_id[] = {
+ { "ttydev", },
+ { "ttydev_serdev", },
+ {}
+};
+MODULE_DEVICE_TABLE(serdev, ttydev_serdev_id);
+
+static struct serdev_device_driver ttydev_serdev_driver = {
+ .probe = ttydev_serdev_probe,
+ .remove = ttydev_serdev_remove,
+ .driver = {
+ .name = "ttydev_serdev",
+ },
+ .id_table = ttydev_serdev_id,
+};
+
+static int __init ttydev_serdev_init(void)
+{
+ return serdev_device_driver_register(&ttydev_serdev_driver);
+}
+module_init(ttydev_serdev_init);
+
+static void __exit ttydev_serdev_exit(void)
+{
+ return serdev_device_driver_unregister(&ttydev_serdev_driver);
+}
+module_exit(ttydev_serdev_exit);
+
+MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Serdev to ttydev module");
--
2.17.0
^ permalink raw reply related
* Re: [patch v23 2/4] drivers: jtag: Add Aspeed SoC 24xx and 25xx families JTAG master driver
From: Greg KH @ 2018-05-29 13:11 UTC (permalink / raw)
To: Oleksandr Shamray
Cc: arnd, linux-kernel, linux-arm-kernel, devicetree, openbmc, joel,
jiri, tklauser, linux-serial, vadimp, system-sw-low-level,
robh+dt, openocd-devel-owner, linux-api, davem, mchehab
In-Reply-To: <1527594545-19870-3-git-send-email-oleksandrs@mellanox.com>
On Tue, May 29, 2018 at 02:49:03PM +0300, Oleksandr Shamray wrote:
> +static int aspeed_jtag_idle(struct jtag *jtag,
> + struct jtag_run_test_idle *runtest)
> +{
> + struct aspeed_jtag *aspeed_jtag = jtag_priv(jtag);
> +
> + dev_dbg(aspeed_jtag->dev, "runtest, status:%d, mode:%s, state:%s, reset:%d, tck:%d\n",
> + aspeed_jtag->status,
> + aspeed_jtag->mode & JTAG_XFER_HW_MODE ? "HW" : "SW",
> + end_status_str[runtest->endstate], runtest->reset,
> + runtest->tck);
You have dev_dbg() lines all over the place. They can all be removed
now, right? ftrace works well, and if you really want to do this
properly, use tracepoints in the jtag core code so that you can get the
information for all devices as needed.
But don't put them all over the driver, now that it's all working,
there's no need, right?
> +static void aspeed_jtag_xfer_push_data_last(struct aspeed_jtag *aspeed_jtag,
> + enum jtag_xfer_type type,
> + u32 shift_bits,
> + enum jtag_endstate endstate)
> +{
> + if (endstate == JTAG_STATE_IDLE) {
> + if (type == JTAG_SIR_XFER) {
> + dev_dbg(aspeed_jtag->dev, "IR Keep Pause\n");
Like this, doesn't provide much info, does it?
thanks,
greg k-h
^ permalink raw reply
* Re: [next-20180517][ppc] watchdog: CPU 88 self-detected hard LOCKUP @ update_cfs_group+0x30/0x150
From: Abdul Haleem @ 2018-05-29 13:09 UTC (permalink / raw)
To: Nicholas Piggin
Cc: sachinp, Stephen Rothwell, linux-kernel, linux-next, linuxppc-dev
In-Reply-To: <20180521165056.5f3dceeb@roar.ozlabs.ibm.com>
On Mon, 2018-05-21 at 16:50 +1000, Nicholas Piggin wrote:
> Ah, it's POWER8.
>
> I'm betting we have a bug with nohz timer offloading somewhere.
>
> I *think* we may have seen similar on P9 as well, but that may be
> related to problems with stop states.
>
> Can you reproduce it easily? I'm thinking maybe adding some
> tracepoints that track decrementer settings and interrupts, and
> nohz offload activity might show something up.
Yes, the problem is reproducible consistently on our CI setup and today
It triggered on 4.17.0-rc6 (mainline) too.
--
Regard's
Abdul Haleem
IBM Linux Technology Centre
^ permalink raw reply
* [PATCH 19/19] serdev: Instantiate a ttydev serdev if acpi and of fails
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Rob Herring, Johan Hovold,
Greg Kroah-Hartman, Jiri Slaby
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
If a serdev ttyport controller does not have an acpi nor an of child,
create a ttydev as a child of that controller.
Doing this allows the removal, addition and replacement of ttydev devices
at runtime.
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Jiri Slaby <jslaby@suse.com>
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/tty/serdev/core.c | 36 ++++++++++++++++++++++++++++++++----
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/serdev/core.c b/drivers/tty/serdev/core.c
index 9414700e6442..34295dacfb84 100644
--- a/drivers/tty/serdev/core.c
+++ b/drivers/tty/serdev/core.c
@@ -619,6 +619,27 @@ static inline int acpi_serdev_register_devices(struct serdev_controller *ctrl)
}
#endif /* CONFIG_ACPI */
+
+#if IS_ENABLED(CONFIG_SERIAL_DEV_CTRL_TTYDEV)
+static int serdev_controller_add_ttydev(struct serdev_controller *ctrl)
+{
+ struct serdev_device *serdev;
+ int err;
+
+ serdev = serdev_device_alloc(ctrl);
+ if (!serdev)
+ return -ENOMEM;
+
+ strcpy(serdev->modalias, "ttydev");
+
+ err = serdev_device_add(serdev);
+ if (err)
+ serdev_device_put(serdev);
+
+ return err;
+}
+#endif
+
/**
* serdev_controller_add() - Add an serdev controller
* @ctrl: controller to be registered.
@@ -628,7 +649,7 @@ static inline int acpi_serdev_register_devices(struct serdev_controller *ctrl)
*/
int serdev_controller_add(struct serdev_controller *ctrl)
{
- int ret_of, ret_acpi, ret;
+ int ret_of, ret_acpi, ret, ret_tty = -ENODEV;
/* Can't register until after driver model init */
if (WARN_ON(!is_registered))
@@ -640,9 +661,16 @@ int serdev_controller_add(struct serdev_controller *ctrl)
ret_of = of_serdev_register_devices(ctrl);
ret_acpi = acpi_serdev_register_devices(ctrl);
- if (ret_of && ret_acpi) {
- dev_dbg(&ctrl->dev, "no devices registered: of:%d acpi:%d\n",
- ret_of, ret_acpi);
+
+#if IS_ENABLED(CONFIG_SERIAL_DEV_CTRL_TTYDEV)
+ if (ret_of && ret_acpi && ctrl->is_ttyport)
+ ret_tty = serdev_controller_add_ttydev(ctrl);
+#endif
+
+ if (ret_of && ret_acpi && ret_tty) {
+ dev_dbg(&ctrl->dev,
+ "no devices registered: of:%d acpi:%d tty:%d\n",
+ ret_of, ret_acpi, ret_tty);
ret = -ENODEV;
goto out_dev_del;
}
--
2.17.0
^ permalink raw reply related
* [PATCH 11/19] Bluetooth: hci_bcm: MODULE_DEVICE_TABLE(serdev)
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Marcel Holtmann, Johan Hedberg,
Rob Herring, Johan Hovold, linux-bluetooth
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
Export serdev table to the module header, allowing module autoload via
udev/modprobe.
Cc: Marcel Holtmann <marcel@holtmann.org>
Cc: Johan Hedberg <johan.hedberg@gmail.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Cc: linux-bluetooth@vger.kernel.org
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
drivers/bluetooth/hci_bcm.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index f4d7846c06b8..ff0fd3502a90 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -1327,8 +1327,10 @@ MODULE_DEVICE_TABLE(of, bcm_bluetooth_of_match);
static const struct serdev_device_id bcm_serdev_id[] = {
{ "bcm43438-bt", },
+ { "hci_uart_bcm", },
{}
};
+MODULE_DEVICE_TABLE(serdev, bcm_serdev_id);
static struct serdev_device_driver bcm_serdev_driver = {
.probe = bcm_serdev_probe,
--
2.17.0
^ permalink raw reply related
* [PATCH 10/19] file2alias: Support for serdev devices
From: Ricardo Ribalda Delgado @ 2018-05-29 13:10 UTC (permalink / raw)
To: linux-kernel, linux-serial
Cc: Ricardo Ribalda Delgado, Greg Kroah-Hartman, Philippe Ombredanne,
Rob Herring, Johan Hovold
In-Reply-To: <20180529131014.18641-1-ricardo.ribalda@gmail.com>
This patch allows file2alias to generate the proper module headers to
support serdev modalias drivers.
Eg:
root@qt5022:~# modinfo serdev:ttydev | grep alias
alias: serdev:ttydev_serdev
alias: serdev:ttydev
root@qt5022:~#
cat /lib/modules/4.16.0-qtec-standard/modules.alias | grep serdev
alias serdev:ttydev_serdev serdev_ttydev
alias serdev:ttydev serdev_ttydev
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Philippe Ombredanne <pombredanne@nexb.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Johan Hovold <johan@kernel.org>
Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com>
---
scripts/mod/devicetable-offsets.c | 3 +++
scripts/mod/file2alias.c | 11 +++++++++++
2 files changed, 14 insertions(+)
diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
index 9fad6afe4c41..6082c41b7ad7 100644
--- a/scripts/mod/devicetable-offsets.c
+++ b/scripts/mod/devicetable-offsets.c
@@ -142,6 +142,9 @@ int main(void)
DEVID(i2c_device_id);
DEVID_FIELD(i2c_device_id, name);
+ DEVID(serdev_device_id);
+ DEVID_FIELD(serdev_device_id, name);
+
DEVID(spi_device_id);
DEVID_FIELD(spi_device_id, name);
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index b9beeaa4695b..dce6df3a159a 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -955,6 +955,17 @@ static int do_i2c_entry(const char *filename, void *symval,
}
ADD_TO_DEVTABLE("i2c", i2c_device_id, do_i2c_entry);
+/* Looks like: serdev:S */
+static int do_serdev_entry(const char *filename, void *symval,
+ char *alias)
+{
+ DEF_FIELD_ADDR(symval, serdev_device_id, name);
+ sprintf(alias, SERDEV_MODULE_PREFIX "%s", *name);
+
+ return 1;
+}
+ADD_TO_DEVTABLE("serdev", serdev_device_id, do_serdev_entry);
+
/* Looks like: spi:S */
static int do_spi_entry(const char *filename, void *symval,
char *alias)
--
2.17.0
^ 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