From 418a3ab1e7785799193c0f8628cd0f01c00a03ae Mon Sep 17 00:00:00 2001 From: Nadav Amit Date: Thu, 25 Apr 2019 04:54:42 -0700 Subject: mm/balloon_compaction: List interfaces Introduce interfaces for ballooning enqueueing and dequeueing of a list of pages. These interfaces reduce the overhead of storing and restoring IRQs by batching the operations. In addition they do not panic if the list of pages is empty. Cc: Jason Wang Cc: linux-mm@kvack.org Cc: virtualization@lists.linux-foundation.org Acked-by: Michael S. Tsirkin Reviewed-by: Xavier Deguillard Signed-off-by: Nadav Amit Signed-off-by: Greg Kroah-Hartman --- include/linux/balloon_compaction.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'include') diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_compaction.h index f31521dcb09a..338aa27e4773 100644 --- a/include/linux/balloon_compaction.h +++ b/include/linux/balloon_compaction.h @@ -64,6 +64,10 @@ extern struct page *balloon_page_alloc(void); extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info, struct page *page); extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info); +extern size_t balloon_page_list_enqueue(struct balloon_dev_info *b_dev_info, + struct list_head *pages); +extern size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info, + struct list_head *pages, size_t n_req_pages); static inline void balloon_devinfo_init(struct balloon_dev_info *balloon) { -- cgit v1.2.3 From 9c3cef54c50d93871eaa46c28a06de8bd03fab63 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Thu, 6 Jun 2019 11:34:28 +0200 Subject: VMCI: Fixup atomic64_t abuse The VMCI driver is abusing atomic64_t and atomic_t, there is no actual atomic RmW operations around. Rewrite the code to use a regular u64 with READ_ONCE() and WRITE_ONCE() and a cast to 'unsigned long'. This fully preserves whatever broken there was (it's not endian-safe for starters, and also looks to be missing ordering). Signed-off-by: Peter Zijlstra (Intel) Signed-off-by: Greg Kroah-Hartman --- include/linux/vmw_vmci_defs.h | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) (limited to 'include') diff --git a/include/linux/vmw_vmci_defs.h b/include/linux/vmw_vmci_defs.h index 0c06178e4985..8ee472118f54 100644 --- a/include/linux/vmw_vmci_defs.h +++ b/include/linux/vmw_vmci_defs.h @@ -438,8 +438,8 @@ enum { struct vmci_queue_header { /* All fields are 64bit and aligned. */ struct vmci_handle handle; /* Identifier. */ - atomic64_t producer_tail; /* Offset in this queue. */ - atomic64_t consumer_head; /* Offset in peer queue. */ + u64 producer_tail; /* Offset in this queue. */ + u64 consumer_head; /* Offset in peer queue. */ }; /* @@ -740,13 +740,9 @@ static inline void *vmci_event_data_payload(struct vmci_event_data *ev_data) * prefix will be used, so correctness isn't an issue, but using a * 64bit operation still adds unnecessary overhead. */ -static inline u64 vmci_q_read_pointer(atomic64_t *var) +static inline u64 vmci_q_read_pointer(u64 *var) { -#if defined(CONFIG_X86_32) - return atomic_read((atomic_t *)var); -#else - return atomic64_read(var); -#endif + return READ_ONCE(*(unsigned long *)var); } /* @@ -755,23 +751,17 @@ static inline u64 vmci_q_read_pointer(atomic64_t *var) * never exceeds a 32bit value in this case. On 32bit SMP, using a * locked cmpxchg8b adds unnecessary overhead. */ -static inline void vmci_q_set_pointer(atomic64_t *var, - u64 new_val) +static inline void vmci_q_set_pointer(u64 *var, u64 new_val) { -#if defined(CONFIG_X86_32) - return atomic_set((atomic_t *)var, (u32)new_val); -#else - return atomic64_set(var, new_val); -#endif + /* XXX buggered on big-endian */ + WRITE_ONCE(*(unsigned long *)var, (unsigned long)new_val); } /* * Helper to add a given offset to a head or tail pointer. Wraps the * value of the pointer around the max size of the queue. */ -static inline void vmci_qp_add_pointer(atomic64_t *var, - size_t add, - u64 size) +static inline void vmci_qp_add_pointer(u64 *var, size_t add, u64 size) { u64 new_val = vmci_q_read_pointer(var); @@ -848,8 +838,8 @@ static inline void vmci_q_header_init(struct vmci_queue_header *q_header, const struct vmci_handle handle) { q_header->handle = handle; - atomic64_set(&q_header->producer_tail, 0); - atomic64_set(&q_header->consumer_head, 0); + q_header->producer_tail = 0; + q_header->consumer_head = 0; } /* -- cgit v1.2.3 From f03631da4be33219021323630a8cf788fd066267 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Wed, 19 Jun 2019 13:52:54 -0600 Subject: coresight: Introduce generic platform data helper So far we have hard coded the DT platform parsing code in every driver. Introduce generic helper to parse the information provided by the firmware in a platform agnostic manner, in preparation for the ACPI support. Signed-off-by: Suzuki K Poulose Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/coresight/coresight-catu.c | 13 ++--- drivers/hwtracing/coresight/coresight-etb10.c | 11 ++-- drivers/hwtracing/coresight/coresight-etm3x.c | 12 ++--- drivers/hwtracing/coresight/coresight-etm4x.c | 11 ++-- drivers/hwtracing/coresight/coresight-funnel.c | 11 ++-- drivers/hwtracing/coresight/coresight-platform.c | 58 ++++++++++++++++------ drivers/hwtracing/coresight/coresight-replicator.c | 11 ++-- drivers/hwtracing/coresight/coresight-stm.c | 11 ++-- drivers/hwtracing/coresight/coresight-tmc.c | 13 ++--- drivers/hwtracing/coresight/coresight-tpiu.c | 11 ++-- include/linux/coresight.h | 7 +-- 11 files changed, 83 insertions(+), 86 deletions(-) (limited to 'include') diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index 63109c98765c..799ba1dd877e 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -503,17 +503,14 @@ static int catu_probe(struct amba_device *adev, const struct amba_id *id) struct coresight_desc catu_desc; struct coresight_platform_data *pdata = NULL; struct device *dev = &adev->dev; - struct device_node *np = dev->of_node; void __iomem *base; - if (np) { - pdata = of_get_coresight_platform_data(dev, np); - if (IS_ERR(pdata)) { - ret = PTR_ERR(pdata); - goto out; - } - dev->platform_data = pdata; + pdata = coresight_get_platform_data(dev); + if (IS_ERR(pdata)) { + ret = PTR_ERR(pdata); + goto out; } + dev->platform_data = pdata; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) { diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index 0c9161fe4233..cb8cb03e0cdb 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -732,14 +732,11 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id) struct etb_drvdata *drvdata; struct resource *res = &adev->res; struct coresight_desc desc = { 0 }; - struct device_node *np = adev->dev.of_node; - if (np) { - pdata = of_get_coresight_platform_data(dev, np); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - adev->dev.platform_data = pdata; - } + pdata = coresight_get_platform_data(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + adev->dev.platform_data = pdata; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index fa2f1417cafb..fa2164ff07c2 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -790,20 +790,16 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id) struct etm_drvdata *drvdata; struct resource *res = &adev->res; struct coresight_desc desc = { 0 }; - struct device_node *np = adev->dev.of_node; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; - if (np) { - pdata = of_get_coresight_platform_data(dev, np); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - - adev->dev.platform_data = pdata; - } + pdata = coresight_get_platform_data(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + adev->dev.platform_data = pdata; drvdata->use_cp14 = fwnode_property_read_bool(dev->fwnode, "arm,cp14"); dev_set_drvdata(dev, drvdata); diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 77d1d837da52..4355b2e8c308 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -1084,18 +1084,15 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) struct etmv4_drvdata *drvdata; struct resource *res = &adev->res; struct coresight_desc desc = { 0 }; - struct device_node *np = adev->dev.of_node; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; - if (np) { - pdata = of_get_coresight_platform_data(dev, np); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - adev->dev.platform_data = pdata; - } + pdata = coresight_get_platform_data(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + adev->dev.platform_data = pdata; dev_set_drvdata(dev, drvdata); diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 3423042e7a52..fc033fdb6cd5 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -187,14 +187,11 @@ static int funnel_probe(struct device *dev, struct resource *res) struct coresight_platform_data *pdata = NULL; struct funnel_drvdata *drvdata; struct coresight_desc desc = { 0 }; - struct device_node *np = dev->of_node; - if (np) { - pdata = of_get_coresight_platform_data(dev, np); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - dev->platform_data = pdata; - } + pdata = coresight_get_platform_data(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + dev->platform_data = pdata; if (is_of_node(dev_fwnode(dev)) && of_device_is_compatible(dev->of_node, "arm,coresight-funnel")) diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index 4c31299607cf..5d78f4fbd97d 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -230,23 +230,16 @@ static int of_coresight_parse_endpoint(struct device *dev, return ret; } -struct coresight_platform_data * -of_get_coresight_platform_data(struct device *dev, - const struct device_node *node) +static int of_get_coresight_platform_data(struct device *dev, + struct coresight_platform_data *pdata) { int ret = 0; - struct coresight_platform_data *pdata; struct coresight_connection *conn; struct device_node *ep = NULL; const struct device_node *parent = NULL; bool legacy_binding = false; + struct device_node *node = dev->of_node; - pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return ERR_PTR(-ENOMEM); - - /* Use device name as sysfs handle */ - pdata->name = dev_name(dev); pdata->cpu = of_coresight_get_cpu(node); /* Get the number of input and output port for this component */ @@ -254,11 +247,11 @@ of_get_coresight_platform_data(struct device *dev, /* If there are no output connections, we are done */ if (!pdata->nr_outport) - return pdata; + return 0; ret = coresight_alloc_conns(dev, pdata); if (ret) - return ERR_PTR(ret); + return ret; parent = of_coresight_get_output_ports_node(node); /* @@ -292,11 +285,46 @@ of_get_coresight_platform_data(struct device *dev, case 0: break; default: - return ERR_PTR(ret); + return ret; } } - return pdata; + return 0; +} +#else +static inline int +of_get_coresight_platform_data(struct device *dev, + struct coresight_platform_data *pdata) +{ + return -ENOENT; } -EXPORT_SYMBOL_GPL(of_get_coresight_platform_data); #endif + +struct coresight_platform_data * +coresight_get_platform_data(struct device *dev) +{ + int ret = -ENOENT; + struct coresight_platform_data *pdata; + struct fwnode_handle *fwnode = dev_fwnode(dev); + + if (IS_ERR_OR_NULL(fwnode)) + goto error; + + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + ret = -ENOMEM; + goto error; + } + + /* Use device name as sysfs handle */ + pdata->name = dev_name(dev); + + if (is_of_node(fwnode)) + ret = of_get_coresight_platform_data(dev, pdata); + + if (!ret) + return pdata; +error: + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(coresight_get_platform_data); diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 7e0514557920..054b33554695 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -177,15 +177,12 @@ static int replicator_probe(struct device *dev, struct resource *res) struct coresight_platform_data *pdata = NULL; struct replicator_drvdata *drvdata; struct coresight_desc desc = { 0 }; - struct device_node *np = dev->of_node; void __iomem *base; - if (np) { - pdata = of_get_coresight_platform_data(dev, np); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - dev->platform_data = pdata; - } + pdata = coresight_get_platform_data(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + dev->platform_data = pdata; if (is_of_node(dev_fwnode(dev)) && of_device_is_compatible(dev->of_node, "arm,coresight-replicator")) diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index 3992a35e34e4..9faa1ed01500 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -809,14 +809,11 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id) struct resource ch_res; size_t bitmap_size; struct coresight_desc desc = { 0 }; - struct device_node *np = adev->dev.of_node; - if (np) { - pdata = of_get_coresight_platform_data(dev, np); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - adev->dev.platform_data = pdata; - } + pdata = coresight_get_platform_data(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + adev->dev.platform_data = pdata; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 9c5e615c1486..be0bd98ca8c1 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -397,16 +397,13 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) struct tmc_drvdata *drvdata; struct resource *res = &adev->res; struct coresight_desc desc = { 0 }; - struct device_node *np = adev->dev.of_node; - if (np) { - pdata = of_get_coresight_platform_data(dev, np); - if (IS_ERR(pdata)) { - ret = PTR_ERR(pdata); - goto out; - } - adev->dev.platform_data = pdata; + pdata = coresight_get_platform_data(dev); + if (IS_ERR(pdata)) { + ret = PTR_ERR(pdata); + goto out; } + adev->dev.platform_data = pdata; ret = -ENOMEM; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index 4dd3e7f63050..aec0ed7bf924 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -124,14 +124,11 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id) struct tpiu_drvdata *drvdata; struct resource *res = &adev->res; struct coresight_desc desc = { 0 }; - struct device_node *np = adev->dev.of_node; - if (np) { - pdata = of_get_coresight_platform_data(dev, np); - if (IS_ERR(pdata)) - return PTR_ERR(pdata); - adev->dev.platform_data = pdata; - } + pdata = coresight_get_platform_data(dev); + if (IS_ERR(pdata)) + return PTR_ERR(pdata); + dev->platform_data = pdata; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 62a520df8add..e2b95e05e0be 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -294,14 +294,11 @@ static inline void coresight_disclaim_device_unlocked(void __iomem *base) {} #ifdef CONFIG_OF extern int of_coresight_get_cpu(const struct device_node *node); -extern struct coresight_platform_data * -of_get_coresight_platform_data(struct device *dev, - const struct device_node *node); #else static inline int of_coresight_get_cpu(const struct device_node *node) { return 0; } -static inline struct coresight_platform_data *of_get_coresight_platform_data( - struct device *dev, const struct device_node *node) { return NULL; } #endif +struct coresight_platform_data *coresight_get_platform_data(struct device *dev); + #endif -- cgit v1.2.3 From 91824db2ea2d2bacacd54de55a7faba10c63b166 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Wed, 19 Jun 2019 13:52:55 -0600 Subject: coresight: Make device to CPU mapping generic The CoreSight components ETM and CPU-Debug are always associated with CPUs. Replace the of_coresight_get_cpu() with a platform agnostic helper, in preparation to add ACPI support. Signed-off-by: Suzuki K Poulose Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/coresight/coresight-cpu-debug.c | 3 +-- drivers/hwtracing/coresight/coresight-platform.c | 18 +++++++++++++----- include/linux/coresight.h | 7 +------ 3 files changed, 15 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c index e8819d750938..07a1367c733f 100644 --- a/drivers/hwtracing/coresight/coresight-cpu-debug.c +++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c @@ -572,14 +572,13 @@ static int debug_probe(struct amba_device *adev, const struct amba_id *id) struct device *dev = &adev->dev; struct debug_drvdata *drvdata; struct resource *res = &adev->res; - struct device_node *np = adev->dev.of_node; int ret; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; - drvdata->cpu = np ? of_coresight_get_cpu(np) : 0; + drvdata->cpu = coresight_get_cpu(dev); if (per_cpu(debug_drvdata, drvdata->cpu)) { dev_err(dev, "CPU%d drvdata has already been initialized\n", drvdata->cpu); diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index 5d78f4fbd97d..ba8c14635c6b 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -151,12 +151,14 @@ static void of_coresight_get_ports(const struct device_node *node, } } -int of_coresight_get_cpu(const struct device_node *node) +static int of_coresight_get_cpu(struct device *dev) { int cpu; struct device_node *dn; - dn = of_parse_phandle(node, "cpu", 0); + if (!dev->of_node) + return 0; + dn = of_parse_phandle(dev->of_node, "cpu", 0); /* Affinity defaults to CPU0 */ if (!dn) return 0; @@ -166,7 +168,6 @@ int of_coresight_get_cpu(const struct device_node *node) /* Affinity to CPU0 if no cpu nodes are found */ return (cpu < 0) ? 0 : cpu; } -EXPORT_SYMBOL_GPL(of_coresight_get_cpu); /* * of_coresight_parse_endpoint : Parse the given output endpoint @ep @@ -240,8 +241,6 @@ static int of_get_coresight_platform_data(struct device *dev, bool legacy_binding = false; struct device_node *node = dev->of_node; - pdata->cpu = of_coresight_get_cpu(node); - /* Get the number of input and output port for this component */ of_coresight_get_ports(node, &pdata->nr_inport, &pdata->nr_outport); @@ -300,6 +299,14 @@ of_get_coresight_platform_data(struct device *dev, } #endif +int coresight_get_cpu(struct device *dev) +{ + if (is_of_node(dev->fwnode)) + return of_coresight_get_cpu(dev); + return 0; +} +EXPORT_SYMBOL_GPL(coresight_get_cpu); + struct coresight_platform_data * coresight_get_platform_data(struct device *dev) { @@ -318,6 +325,7 @@ coresight_get_platform_data(struct device *dev) /* Use device name as sysfs handle */ pdata->name = dev_name(dev); + pdata->cpu = coresight_get_cpu(dev); if (is_of_node(fwnode)) ret = of_get_coresight_platform_data(dev, pdata); diff --git a/include/linux/coresight.h b/include/linux/coresight.h index e2b95e05e0be..98a4440dea3e 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -292,12 +292,7 @@ static inline void coresight_disclaim_device_unlocked(void __iomem *base) {} #endif -#ifdef CONFIG_OF -extern int of_coresight_get_cpu(const struct device_node *node); -#else -static inline int of_coresight_get_cpu(const struct device_node *node) -{ return 0; } -#endif +extern int coresight_get_cpu(struct device *dev); struct coresight_platform_data *coresight_get_platform_data(struct device *dev); -- cgit v1.2.3 From aff70a45fe3120b08ae459a6e3996346d2766b1f Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Wed, 19 Jun 2019 13:52:56 -0600 Subject: coresight: Remove cpu field from platform data CPU field is only used by ETMs and there is a separate API for fetching the same. So, let us use that instead of using the common platform probing helper. Also, remove it from the platform_data. Signed-off-by: Suzuki K Poulose Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/coresight/coresight-etm3x.c | 2 +- drivers/hwtracing/coresight/coresight-etm4x.c | 2 +- drivers/hwtracing/coresight/coresight-platform.c | 1 - include/linux/coresight.h | 2 -- 4 files changed, 2 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index fa2164ff07c2..722fab9632ef 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -819,7 +819,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id) return ret; } - drvdata->cpu = pdata ? pdata->cpu : 0; + drvdata->cpu = coresight_get_cpu(dev); cpus_read_lock(); etmdrvdata[drvdata->cpu] = drvdata; diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 4355b2e8c308..03576f3ed22d 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -1105,7 +1105,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) spin_lock_init(&drvdata->spinlock); - drvdata->cpu = pdata ? pdata->cpu : 0; + drvdata->cpu = coresight_get_cpu(dev); cpus_read_lock(); etmdrvdata[drvdata->cpu] = drvdata; diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index ba8c14635c6b..541e500a83c2 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -325,7 +325,6 @@ coresight_get_platform_data(struct device *dev) /* Use device name as sysfs handle */ pdata->name = dev_name(dev); - pdata->cpu = coresight_get_cpu(dev); if (is_of_node(fwnode)) ret = of_get_coresight_platform_data(dev, pdata); diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 98a4440dea3e..bf241dbf99c5 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -91,14 +91,12 @@ union coresight_dev_subtype { /** * struct coresight_platform_data - data harvested from the DT specification - * @cpu: the CPU a source belongs to. Only applicable for ETM/PTMs. * @name: name of the component as shown under sysfs. * @nr_inport: number of input ports for this component. * @nr_outport: number of output ports for this component. * @conns: Array of nr_outport connections from this component */ struct coresight_platform_data { - int cpu; const char *name; int nr_inport; int nr_outport; -- cgit v1.2.3 From 2ede79a6e8a541d1bc7c033b1198f05088e7cefb Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Wed, 19 Jun 2019 13:52:57 -0600 Subject: coresight: Remove name from platform description We are about to use a name independent of the parent AMBA device name. As such, there is no need to have it in the platform description. Let us move this to coresight description instead. Signed-off-by: Suzuki K Poulose Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/coresight/coresight-catu.c | 2 ++ drivers/hwtracing/coresight/coresight-etb10.c | 3 ++- drivers/hwtracing/coresight/coresight-etm3x.c | 1 + drivers/hwtracing/coresight/coresight-etm4x.c | 1 + drivers/hwtracing/coresight/coresight-funnel.c | 1 + drivers/hwtracing/coresight/coresight-platform.c | 3 --- drivers/hwtracing/coresight/coresight-replicator.c | 2 ++ drivers/hwtracing/coresight/coresight-stm.c | 1 + drivers/hwtracing/coresight/coresight-tmc.c | 5 +++-- drivers/hwtracing/coresight/coresight-tpiu.c | 1 + drivers/hwtracing/coresight/coresight.c | 2 +- include/linux/coresight.h | 8 ++++---- 12 files changed, 19 insertions(+), 11 deletions(-) (limited to 'include') diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index 799ba1dd877e..05c73045532a 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -551,6 +551,8 @@ static int catu_probe(struct amba_device *adev, const struct amba_id *id) catu_desc.type = CORESIGHT_DEV_TYPE_HELPER; catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU; catu_desc.ops = &catu_ops; + catu_desc.name = dev_name(dev); + drvdata->csdev = coresight_register(&catu_desc); if (IS_ERR(drvdata->csdev)) ret = PTR_ERR(drvdata->csdev); diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index cb8cb03e0cdb..8726d6c7663c 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -777,12 +777,13 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id) desc.ops = &etb_cs_ops; desc.pdata = pdata; desc.dev = dev; + desc.name = dev_name(dev); desc.groups = coresight_etb_groups; drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) return PTR_ERR(drvdata->csdev); - drvdata->miscdev.name = pdata->name; + drvdata->miscdev.name = desc.name; drvdata->miscdev.minor = MISC_DYNAMIC_MINOR; drvdata->miscdev.fops = &etb_fops; ret = misc_register(&drvdata->miscdev); diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index 722fab9632ef..101fb01e20de 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -854,6 +854,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id) desc.ops = &etm_cs_ops; desc.pdata = pdata; desc.dev = dev; + desc.name = dev_name(dev); desc.groups = coresight_etm_groups; drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) { diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 03576f3ed22d..8adc1485cd89 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -1142,6 +1142,7 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) desc.pdata = pdata; desc.dev = dev; desc.groups = coresight_etmv4_groups; + desc.name = dev_name(dev); drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) { ret = PTR_ERR(drvdata->csdev); diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index fc033fdb6cd5..ded33f5e7d43 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -229,6 +229,7 @@ static int funnel_probe(struct device *dev, struct resource *res) desc.ops = &funnel_cs_ops; desc.pdata = pdata; desc.dev = dev; + desc.name = dev_name(dev); drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) { ret = PTR_ERR(drvdata->csdev); diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index 541e500a83c2..f500de61e7f9 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -323,9 +323,6 @@ coresight_get_platform_data(struct device *dev) goto error; } - /* Use device name as sysfs handle */ - pdata->name = dev_name(dev); - if (is_of_node(fwnode)) ret = of_get_coresight_platform_data(dev, pdata); diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 054b33554695..f28bafd98995 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -220,6 +220,8 @@ static int replicator_probe(struct device *dev, struct resource *res) desc.ops = &replicator_cs_ops; desc.pdata = dev->platform_data; desc.dev = dev; + desc.name = dev_name(dev); + drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) { ret = PTR_ERR(drvdata->csdev); diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index 9faa1ed01500..02031d93fb8b 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -871,6 +871,7 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id) desc.ops = &stm_cs_ops; desc.pdata = pdata; desc.dev = dev; + desc.name = dev_name(dev); desc.groups = coresight_stm_groups; drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) { diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index be0bd98ca8c1..44a571988219 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -437,6 +437,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) desc.pdata = pdata; desc.dev = dev; desc.groups = coresight_tmc_groups; + desc.name = dev_name(dev); switch (drvdata->config_type) { case TMC_CONFIG_TYPE_ETB: @@ -461,7 +462,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) desc.ops = &tmc_etf_cs_ops; break; default: - pr_err("%s: Unsupported TMC config\n", pdata->name); + pr_err("%s: Unsupported TMC config\n", desc.name); ret = -EINVAL; goto out; } @@ -472,7 +473,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) goto out; } - drvdata->miscdev.name = pdata->name; + drvdata->miscdev.name = desc.name; drvdata->miscdev.minor = MISC_DYNAMIC_MINOR; drvdata->miscdev.fops = &tmc_fops; ret = misc_register(&drvdata->miscdev); diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index aec0ed7bf924..d8a2e3991c7e 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -157,6 +157,7 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id) desc.ops = &tpiu_cs_ops; desc.pdata = pdata; desc.dev = dev; + desc.name = dev_name(dev); drvdata->csdev = coresight_register(&desc); if (!IS_ERR(drvdata->csdev)) { diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 4b130281236a..04b5d3c2bb3a 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -1199,7 +1199,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) csdev->dev.parent = desc->dev; csdev->dev.release = coresight_device_release; csdev->dev.bus = &coresight_bustype; - dev_set_name(&csdev->dev, "%s", desc->pdata->name); + dev_set_name(&csdev->dev, "%s", desc->name); ret = device_register(&csdev->dev); if (ret) { diff --git a/include/linux/coresight.h b/include/linux/coresight.h index bf241dbf99c5..298db20ba8ce 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -91,13 +91,11 @@ union coresight_dev_subtype { /** * struct coresight_platform_data - data harvested from the DT specification - * @name: name of the component as shown under sysfs. * @nr_inport: number of input ports for this component. * @nr_outport: number of output ports for this component. * @conns: Array of nr_outport connections from this component */ struct coresight_platform_data { - const char *name; int nr_inport; int nr_outport; struct coresight_connection *conns; @@ -108,11 +106,12 @@ struct coresight_platform_data { * @type: as defined by @coresight_dev_type. * @subtype: as defined by @coresight_dev_subtype. * @ops: generic operations for this component, as defined - by @coresight_ops. + * by @coresight_ops. * @pdata: platform data collected from DT. * @dev: The device entity associated to this component. * @groups: operations specific to this component. These will end up - in the component's sysfs sub-directory. + * in the component's sysfs sub-directory. + * @name: name for the coresight device, also shown under sysfs. */ struct coresight_desc { enum coresight_dev_type type; @@ -121,6 +120,7 @@ struct coresight_desc { struct coresight_platform_data *pdata; struct device *dev; const struct attribute_group **groups; + const char *name; }; /** -- cgit v1.2.3 From b77e3ed038c0d877f6f3b6ad278b931048a48e34 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Wed, 19 Jun 2019 13:52:59 -0600 Subject: coresight: Reuse platform data structure for connection tracking The platform specific information describes the connections and the ports of a given coresigh device. This information is also recorded in the coresight device as separate fields. Let us reuse the original platform description to streamline the handling of the data. Signed-off-by: Suzuki K Poulose Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/coresight/coresight-tmc-etr.c | 4 +-- drivers/hwtracing/coresight/coresight.c | 46 ++++++++++++------------- include/linux/coresight.h | 8 ++--- 3 files changed, 27 insertions(+), 31 deletions(-) (limited to 'include') diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c index 709448cf2dff..ce0114a5435c 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c @@ -756,8 +756,8 @@ tmc_etr_get_catu_device(struct tmc_drvdata *drvdata) if (!IS_ENABLED(CONFIG_CORESIGHT_CATU)) return NULL; - for (i = 0; i < etr->nr_outport; i++) { - tmp = etr->conns[i].child_dev; + for (i = 0; i < etr->pdata->nr_outport; i++) { + tmp = etr->pdata->conns[i].child_dev; if (tmp && coresight_is_catu_device(tmp)) return tmp; } diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 068bd2fc0985..96e15154a566 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -100,8 +100,8 @@ static int coresight_find_link_inport(struct coresight_device *csdev, int i; struct coresight_connection *conn; - for (i = 0; i < parent->nr_outport; i++) { - conn = &parent->conns[i]; + for (i = 0; i < parent->pdata->nr_outport; i++) { + conn = &parent->pdata->conns[i]; if (conn->child_dev == csdev) return conn->child_port; } @@ -118,8 +118,8 @@ static int coresight_find_link_outport(struct coresight_device *csdev, int i; struct coresight_connection *conn; - for (i = 0; i < csdev->nr_outport; i++) { - conn = &csdev->conns[i]; + for (i = 0; i < csdev->pdata->nr_outport; i++) { + conn = &csdev->pdata->conns[i]; if (conn->child_dev == child) return conn->outport; } @@ -306,10 +306,10 @@ static void coresight_disable_link(struct coresight_device *csdev, if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_MERG) { refport = inport; - nr_conns = csdev->nr_inport; + nr_conns = csdev->pdata->nr_inport; } else if (link_subtype == CORESIGHT_DEV_SUBTYPE_LINK_SPLIT) { refport = outport; - nr_conns = csdev->nr_outport; + nr_conns = csdev->pdata->nr_outport; } else { refport = 0; nr_conns = 1; @@ -595,9 +595,10 @@ static void coresight_grab_device(struct coresight_device *csdev) { int i; - for (i = 0; i < csdev->nr_outport; i++) { - struct coresight_device *child = csdev->conns[i].child_dev; + for (i = 0; i < csdev->pdata->nr_outport; i++) { + struct coresight_device *child; + child = csdev->pdata->conns[i].child_dev; if (child && child->type == CORESIGHT_DEV_TYPE_HELPER) pm_runtime_get_sync(child->dev.parent); } @@ -613,9 +614,10 @@ static void coresight_drop_device(struct coresight_device *csdev) int i; pm_runtime_put(csdev->dev.parent); - for (i = 0; i < csdev->nr_outport; i++) { - struct coresight_device *child = csdev->conns[i].child_dev; + for (i = 0; i < csdev->pdata->nr_outport; i++) { + struct coresight_device *child; + child = csdev->pdata->conns[i].child_dev; if (child && child->type == CORESIGHT_DEV_TYPE_HELPER) pm_runtime_put(child->dev.parent); } @@ -645,9 +647,10 @@ static int _coresight_build_path(struct coresight_device *csdev, goto out; /* Not a sink - recursively explore each port found on this element */ - for (i = 0; i < csdev->nr_outport; i++) { - struct coresight_device *child_dev = csdev->conns[i].child_dev; + for (i = 0; i < csdev->pdata->nr_outport; i++) { + struct coresight_device *child_dev; + child_dev = csdev->pdata->conns[i].child_dev; if (child_dev && _coresight_build_path(child_dev, sink, path) == 0) { found = true; @@ -1000,8 +1003,8 @@ static int coresight_orphan_match(struct device *dev, void *data) * Circle throuch all the connection of that component. If we find * an orphan connection whose name matches @csdev, link it. */ - for (i = 0; i < i_csdev->nr_outport; i++) { - conn = &i_csdev->conns[i]; + for (i = 0; i < i_csdev->pdata->nr_outport; i++) { + conn = &i_csdev->pdata->conns[i]; /* We have found at least one orphan connection */ if (conn->child_dev == NULL) { @@ -1040,8 +1043,8 @@ static void coresight_fixup_device_conns(struct coresight_device *csdev) { int i; - for (i = 0; i < csdev->nr_outport; i++) { - struct coresight_connection *conn = &csdev->conns[i]; + for (i = 0; i < csdev->pdata->nr_outport; i++) { + struct coresight_connection *conn = &csdev->pdata->conns[i]; struct device *dev = NULL; if (conn->child_name) @@ -1075,8 +1078,8 @@ static int coresight_remove_match(struct device *dev, void *data) * Circle throuch all the connection of that component. If we find * a connection whose name matches @csdev, remove it. */ - for (i = 0; i < iterator->nr_outport; i++) { - conn = &iterator->conns[i]; + for (i = 0; i < iterator->pdata->nr_outport; i++) { + conn = &iterator->pdata->conns[i]; if (conn->child_dev == NULL) continue; @@ -1108,7 +1111,7 @@ static void coresight_remove_conns(struct coresight_device *csdev) * doesn't have at least one input port, there is no point * in searching all the devices. */ - if (csdev->nr_inport) + if (csdev->pdata->nr_inport) bus_for_each_dev(&coresight_bustype, NULL, csdev, coresight_remove_match); } @@ -1195,10 +1198,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) csdev->refcnt = refcnts; - csdev->nr_inport = desc->pdata->nr_inport; - csdev->nr_outport = desc->pdata->nr_outport; - - csdev->conns = desc->pdata->conns; + csdev->pdata = desc->pdata; csdev->type = desc->type; csdev->subtype = desc->subtype; diff --git a/include/linux/coresight.h b/include/linux/coresight.h index 298db20ba8ce..b67d5074ece0 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -140,9 +140,7 @@ struct coresight_connection { /** * struct coresight_device - representation of a device as used by the framework - * @conns: array of coresight_connections associated to this component. - * @nr_inport: number of input port associated to this component. - * @nr_outport: number of output port associated to this component. + * @pdata: Platform data with device connections associated to this device. * @type: as defined by @coresight_dev_type. * @subtype: as defined by @coresight_dev_subtype. * @ops: generic operations for this component, as defined @@ -157,9 +155,7 @@ struct coresight_connection { * @ea: Device attribute for sink representation under PMU directory. */ struct coresight_device { - struct coresight_connection *conns; - int nr_inport; - int nr_outport; + struct coresight_platform_data *pdata; enum coresight_dev_type type; union coresight_dev_subtype subtype; const struct coresight_ops *ops; -- cgit v1.2.3 From 37ea1ffddffa63c920ce826786fe610c78f57842 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Wed, 19 Jun 2019 13:53:03 -0600 Subject: coresight: Use fwnode handle instead of device names We rely on the device names to find a CoreSight device on the coresight bus. The device name however is obtained from the platform, which is bound to the real platform/amba device. As we are about to use different naming scheme for the coresight devices, we can't rely on the platform device name to find the corresponding coresight device. Instead we use the platform agnostic "fwnode handle" of the parent device to find the devices. We also reuse the same fwnode as the parent for the Coresight device we create. Signed-off-by: Suzuki K Poulose Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/coresight/coresight-platform.c | 14 +++++--- drivers/hwtracing/coresight/coresight-priv.h | 6 ++-- drivers/hwtracing/coresight/coresight.c | 42 +++++++++++++++++++----- include/linux/coresight.h | 4 +-- 4 files changed, 49 insertions(+), 17 deletions(-) (limited to 'include') diff --git a/drivers/hwtracing/coresight/coresight-platform.c b/drivers/hwtracing/coresight/coresight-platform.c index 4394095ad224..49112a58478e 100644 --- a/drivers/hwtracing/coresight/coresight-platform.c +++ b/drivers/hwtracing/coresight/coresight-platform.c @@ -36,7 +36,7 @@ static int coresight_alloc_conns(struct device *dev, return 0; } -static int coresight_device_fwnode_match(struct device *dev, void *fwnode) +int coresight_device_fwnode_match(struct device *dev, void *fwnode) { return dev_fwnode(dev) == fwnode; } @@ -219,9 +219,15 @@ static int of_coresight_parse_endpoint(struct device *dev, } conn->outport = endpoint.port; - conn->child_name = devm_kstrdup(dev, - dev_name(rdev), - GFP_KERNEL); + /* + * Hold the refcount to the target device. This could be + * released via: + * 1) coresight_release_platform_data() if the probe fails or + * this device is unregistered. + * 2) While removing the target device via + * coresight_remove_match() + */ + conn->child_fwnode = fwnode_handle_get(rdev_fwnode); conn->child_port = rendpoint.port; /* Connection record updated */ ret = 1; diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h index c21642114fc3..8b07fe55395a 100644 --- a/drivers/hwtracing/coresight/coresight-priv.h +++ b/drivers/hwtracing/coresight/coresight-priv.h @@ -200,8 +200,8 @@ static inline void *coresight_get_uci_data(const struct amba_id *id) return 0; } -static inline void -coresight_release_platform_data(struct coresight_platform_data *pdata) -{} +void coresight_release_platform_data(struct coresight_platform_data *pdata); + +int coresight_device_fwnode_match(struct device *dev, void *fwnode); #endif diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 526141c2f876..1287778c3be5 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -978,6 +978,7 @@ static void coresight_device_release(struct device *dev) { struct coresight_device *csdev = to_coresight_device(dev); + fwnode_handle_put(csdev->dev.fwnode); kfree(csdev->refcnt); kfree(csdev); } @@ -1009,13 +1010,11 @@ static int coresight_orphan_match(struct device *dev, void *data) /* We have found at least one orphan connection */ if (conn->child_dev == NULL) { /* Does it match this newly added device? */ - if (conn->child_name && - !strcmp(dev_name(&csdev->dev), conn->child_name)) { + if (conn->child_fwnode == csdev->dev.fwnode) conn->child_dev = csdev; - } else { + else /* This component still has an orphan */ still_orphan = true; - } } } @@ -1047,9 +1046,9 @@ static void coresight_fixup_device_conns(struct coresight_device *csdev) struct coresight_connection *conn = &csdev->pdata->conns[i]; struct device *dev = NULL; - if (conn->child_name) - dev = bus_find_device_by_name(&coresight_bustype, NULL, - conn->child_name); + dev = bus_find_device(&coresight_bustype, NULL, + (void *)conn->child_fwnode, + coresight_device_fwnode_match); if (dev) { conn->child_dev = to_coresight_device(dev); /* and put reference from 'bus_find_device()' */ @@ -1084,9 +1083,15 @@ static int coresight_remove_match(struct device *dev, void *data) if (conn->child_dev == NULL) continue; - if (!strcmp(dev_name(&csdev->dev), conn->child_name)) { + if (csdev->dev.fwnode == conn->child_fwnode) { iterator->orphan = true; conn->child_dev = NULL; + /* + * Drop the reference to the handle for the remote + * device acquired in parsing the connections from + * platform data. + */ + fwnode_handle_put(conn->child_fwnode); /* No need to continue */ break; } @@ -1166,6 +1171,22 @@ static int __init coresight_init(void) } postcore_initcall(coresight_init); +/* + * coresight_release_platform_data: Release references to the devices connected + * to the output port of this device. + */ +void coresight_release_platform_data(struct coresight_platform_data *pdata) +{ + int i; + + for (i = 0; i < pdata->nr_outport; i++) { + if (pdata->conns[i].child_fwnode) { + fwnode_handle_put(pdata->conns[i].child_fwnode); + pdata->conns[i].child_fwnode = NULL; + } + } +} + struct coresight_device *coresight_register(struct coresight_desc *desc) { int ret; @@ -1210,6 +1231,11 @@ struct coresight_device *coresight_register(struct coresight_desc *desc) csdev->dev.parent = desc->dev; csdev->dev.release = coresight_device_release; csdev->dev.bus = &coresight_bustype; + /* + * Hold the reference to our parent device. This will be + * dropped only in coresight_device_release(). + */ + csdev->dev.fwnode = fwnode_handle_get(dev_fwnode(desc->dev)); dev_set_name(&csdev->dev, "%s", desc->name); ret = device_register(&csdev->dev); diff --git a/include/linux/coresight.h b/include/linux/coresight.h index b67d5074ece0..b40544bc06fe 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -126,15 +126,15 @@ struct coresight_desc { /** * struct coresight_connection - representation of a single connection * @outport: a connection's output port number. - * @chid_name: remote component's name. * @child_port: remote component's port number @output is connected to. + * @chid_fwnode: remote component's fwnode handle. * @child_dev: a @coresight_device representation of the component connected to @outport. */ struct coresight_connection { int outport; - const char *child_name; int child_port; + struct fwnode_handle *child_fwnode; struct coresight_device *child_dev; }; -- cgit v1.2.3 From 0f5f9b6ba9e1a706f5a3b1bd467e9242ab31b352 Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Wed, 19 Jun 2019 13:53:04 -0600 Subject: coresight: Use platform agnostic names So far we have reused the name of the "platform" device for the CoreSight device. But this is not very intuitive when we move to ACPI. Also, the ACPI device names have ":" in them (e.g, ARMHC97C:01), which the perf tool doesn't like very much. This patch introduces a generic naming scheme, givin more intuitive names for the devices that appear on the CoreSight bus. The names follow the pattern "prefix" followed by "index" (e.g, etm5). We maintain a list of allocated devices per "prefix" to make sure we don't allocate a new name when it is reprobed (e.g, due to unsatisifed device dependencies). So, we maintain the list of "fwnodes" of the parent devices to allocate a consistent name. All devices except the ETMs get an index allocated in the order of probing. ETMs get an index based on the CPU they are attached to. TMC devices are named using "tmc_etf", "tmc_etb", and "tmc_etr" prefixes depending on the configuration of the device. The replicators and funnels are not classified as dynamic/static anymore. One could easily figure that out by checking the presence of "mgmt" registers under sysfs. Signed-off-by: Suzuki K Poulose Signed-off-by: Mathieu Poirier Signed-off-by: Greg Kroah-Hartman --- drivers/hwtracing/coresight/coresight-catu.c | 7 ++- drivers/hwtracing/coresight/coresight-etb10.c | 7 ++- drivers/hwtracing/coresight/coresight-etm3x.c | 4 +- drivers/hwtracing/coresight/coresight-etm4x.c | 4 +- drivers/hwtracing/coresight/coresight-funnel.c | 7 ++- drivers/hwtracing/coresight/coresight-replicator.c | 7 ++- drivers/hwtracing/coresight/coresight-stm.c | 12 +++-- drivers/hwtracing/coresight/coresight-tmc.c | 15 +++++- drivers/hwtracing/coresight/coresight-tpiu.c | 7 ++- drivers/hwtracing/coresight/coresight.c | 58 ++++++++++++++++++++++ include/linux/coresight.h | 25 +++++++++- 11 files changed, 141 insertions(+), 12 deletions(-) (limited to 'include') diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c index 1c1ad1268b9d..16ebf38a9f66 100644 --- a/drivers/hwtracing/coresight/coresight-catu.c +++ b/drivers/hwtracing/coresight/coresight-catu.c @@ -28,6 +28,8 @@ #define catu_dbg(x, ...) do {} while (0) #endif +DEFINE_CORESIGHT_DEVLIST(catu_devs, "catu"); + struct catu_etr_buf { struct tmc_sg_table *catu_table; dma_addr_t sladdr; @@ -505,6 +507,10 @@ static int catu_probe(struct amba_device *adev, const struct amba_id *id) struct device *dev = &adev->dev; void __iomem *base; + catu_desc.name = coresight_alloc_device_name(&catu_devs, dev); + if (!catu_desc.name) + return -ENOMEM; + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) { ret = -ENOMEM; @@ -551,7 +557,6 @@ static int catu_probe(struct amba_device *adev, const struct amba_id *id) catu_desc.type = CORESIGHT_DEV_TYPE_HELPER; catu_desc.subtype.helper_subtype = CORESIGHT_DEV_SUBTYPE_HELPER_CATU; catu_desc.ops = &catu_ops; - catu_desc.name = dev_name(dev); drvdata->csdev = coresight_register(&catu_desc); if (IS_ERR(drvdata->csdev)) diff --git a/drivers/hwtracing/coresight/coresight-etb10.c b/drivers/hwtracing/coresight/coresight-etb10.c index fffaac3e3677..d5b9edecf76e 100644 --- a/drivers/hwtracing/coresight/coresight-etb10.c +++ b/drivers/hwtracing/coresight/coresight-etb10.c @@ -63,6 +63,8 @@ #define ETB_FFSR_BIT 1 #define ETB_FRAME_SIZE_WORDS 4 +DEFINE_CORESIGHT_DEVLIST(etb_devs, "etb"); + /** * struct etb_drvdata - specifics associated to an ETB component * @base: memory mapped base address for this component. @@ -733,6 +735,10 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id) struct resource *res = &adev->res; struct coresight_desc desc = { 0 }; + desc.name = coresight_alloc_device_name(&etb_devs, dev); + if (!desc.name) + return -ENOMEM; + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; @@ -777,7 +783,6 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id) desc.ops = &etb_cs_ops; desc.pdata = pdata; desc.dev = dev; - desc.name = dev_name(dev); desc.groups = coresight_etb_groups; drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c index f2d461610a2f..bed729140718 100644 --- a/drivers/hwtracing/coresight/coresight-etm3x.c +++ b/drivers/hwtracing/coresight/coresight-etm3x.c @@ -815,6 +815,9 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id) } drvdata->cpu = coresight_get_cpu(dev); + desc.name = devm_kasprintf(dev, GFP_KERNEL, "etm%d", drvdata->cpu); + if (!desc.name) + return -ENOMEM; cpus_read_lock(); etmdrvdata[drvdata->cpu] = drvdata; @@ -856,7 +859,6 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id) desc.ops = &etm_cs_ops; desc.pdata = pdata; desc.dev = dev; - desc.name = dev_name(dev); desc.groups = coresight_etm_groups; drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) { diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c index 1609da1eaf83..7fe266194ab5 100644 --- a/drivers/hwtracing/coresight/coresight-etm4x.c +++ b/drivers/hwtracing/coresight/coresight-etm4x.c @@ -1101,6 +1101,9 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) spin_lock_init(&drvdata->spinlock); drvdata->cpu = coresight_get_cpu(dev); + desc.name = devm_kasprintf(dev, GFP_KERNEL, "etm%d", drvdata->cpu); + if (!desc.name) + return -ENOMEM; cpus_read_lock(); etmdrvdata[drvdata->cpu] = drvdata; @@ -1144,7 +1147,6 @@ static int etm4_probe(struct amba_device *adev, const struct amba_id *id) desc.pdata = pdata; desc.dev = dev; desc.groups = coresight_etmv4_groups; - desc.name = dev_name(dev); drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) { ret = PTR_ERR(drvdata->csdev); diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c index 75fa2d3ad9b4..5867fcb4503b 100644 --- a/drivers/hwtracing/coresight/coresight-funnel.c +++ b/drivers/hwtracing/coresight/coresight-funnel.c @@ -29,6 +29,8 @@ #define FUNNEL_HOLDTIME (0x7 << FUNNEL_HOLDTIME_SHFT) #define FUNNEL_ENSx_MASK 0xff +DEFINE_CORESIGHT_DEVLIST(funnel_devs, "funnel"); + /** * struct funnel_drvdata - specifics associated to a funnel component * @base: memory mapped base address for this component. @@ -192,6 +194,10 @@ static int funnel_probe(struct device *dev, struct resource *res) of_device_is_compatible(dev->of_node, "arm,coresight-funnel")) pr_warn_once("Uses OBSOLETE CoreSight funnel binding\n"); + desc.name = coresight_alloc_device_name(&funnel_devs, dev); + if (!desc.name) + return -ENOMEM; + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; @@ -231,7 +237,6 @@ static int funnel_probe(struct device *dev, struct resource *res) desc.ops = &funnel_cs_ops; desc.pdata = pdata; desc.dev = dev; - desc.name = dev_name(dev); drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) { ret = PTR_ERR(drvdata->csdev); diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c index 64dfde7241c1..c0e42253dfe7 100644 --- a/drivers/hwtracing/coresight/coresight-replicator.c +++ b/drivers/hwtracing/coresight/coresight-replicator.c @@ -22,6 +22,8 @@ #define REPLICATOR_IDFILTER0 0x000 #define REPLICATOR_IDFILTER1 0x004 +DEFINE_CORESIGHT_DEVLIST(replicator_devs, "replicator"); + /** * struct replicator_drvdata - specifics associated to a replicator component * @base: memory mapped base address for this component. Also indicates @@ -183,6 +185,10 @@ static int replicator_probe(struct device *dev, struct resource *res) of_device_is_compatible(dev->of_node, "arm,coresight-replicator")) pr_warn_once("Uses OBSOLETE CoreSight replicator binding\n"); + desc.name = coresight_alloc_device_name(&replicator_devs, dev); + if (!desc.name) + return -ENOMEM; + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; @@ -222,7 +228,6 @@ static int replicator_probe(struct device *dev, struct resource *res) desc.ops = &replicator_cs_ops; desc.pdata = dev->platform_data; desc.dev = dev; - desc.name = dev_name(dev); drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) { diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c index 03528f3fa9ff..e3e2b000cfb7 100644 --- a/drivers/hwtracing/coresight/coresight-stm.c +++ b/drivers/hwtracing/coresight/coresight-stm.c @@ -107,6 +107,8 @@ struct channel_space { unsigned long *guaranteed; }; +DEFINE_CORESIGHT_DEVLIST(stm_devs, "stm"); + /** * struct stm_drvdata - specifics associated to an STM component * @base: memory mapped base address for this component. @@ -810,6 +812,10 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id) size_t bitmap_size; struct coresight_desc desc = { 0 }; + desc.name = coresight_alloc_device_name(&stm_devs, dev); + if (!desc.name) + return -ENOMEM; + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; @@ -854,11 +860,12 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id) spin_lock_init(&drvdata->spinlock); stm_init_default_data(drvdata); - stm_init_generic_data(drvdata, dev_name(dev)); + stm_init_generic_data(drvdata, desc.name); if (stm_register_device(dev, &drvdata->stm, THIS_MODULE)) { dev_info(dev, - "stm_register_device failed, probing deferred\n"); + "%s : stm_register_device failed, probing deferred\n", + desc.name); return -EPROBE_DEFER; } @@ -874,7 +881,6 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id) desc.ops = &stm_cs_ops; desc.pdata = pdata; desc.dev = dev; - desc.name = dev_name(dev); desc.groups = coresight_stm_groups; drvdata->csdev = coresight_register(&desc); if (IS_ERR(drvdata->csdev)) { diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c index 212630e65cca..be37aff573b4 100644 --- a/drivers/hwtracing/coresight/coresight-tmc.c +++ b/drivers/hwtracing/coresight/coresight-tmc.c @@ -27,6 +27,10 @@ #include "coresight-priv.h" #include "coresight-tmc.h" +DEFINE_CORESIGHT_DEVLIST(etb_devs, "tmc_etb"); +DEFINE_CORESIGHT_DEVLIST(etf_devs, "tmc_etf"); +DEFINE_CORESIGHT_DEVLIST(etr_devs, "tmc_etr"); + void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata) { /* Ensure formatter, unformatter and hardware fifo are empty */ @@ -397,6 +401,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) struct tmc_drvdata *drvdata; struct resource *res = &adev->res; struct coresight_desc desc = { 0 }; + struct coresight_dev_list *dev_list = NULL; ret = -ENOMEM; drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); @@ -429,13 +434,13 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) desc.dev = dev; desc.groups = coresight_tmc_groups; - desc.name = dev_name(dev); switch (drvdata->config_type) { case TMC_CONFIG_TYPE_ETB: desc.type = CORESIGHT_DEV_TYPE_SINK; desc.subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER; desc.ops = &tmc_etb_cs_ops; + dev_list = &etb_devs; break; case TMC_CONFIG_TYPE_ETR: desc.type = CORESIGHT_DEV_TYPE_SINK; @@ -447,11 +452,13 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) goto out; idr_init(&drvdata->idr); mutex_init(&drvdata->idr_mutex); + dev_list = &etr_devs; break; case TMC_CONFIG_TYPE_ETF: desc.type = CORESIGHT_DEV_TYPE_LINKSINK; desc.subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO; desc.ops = &tmc_etf_cs_ops; + dev_list = &etf_devs; break; default: pr_err("%s: Unsupported TMC config\n", desc.name); @@ -459,6 +466,12 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id) goto out; } + desc.name = coresight_alloc_device_name(dev_list, dev); + if (!desc.name) { + ret = -ENOMEM; + goto out; + } + pdata = coresight_get_platform_data(dev); if (IS_ERR(pdata)) { ret = PTR_ERR(pdata); diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c index b699d613425d..f8583e4032a6 100644 --- a/drivers/hwtracing/coresight/coresight-tpiu.c +++ b/drivers/hwtracing/coresight/coresight-tpiu.c @@ -47,6 +47,8 @@ #define FFCR_FON_MAN BIT(6) #define FFCR_STOP_FI BIT(12) +DEFINE_CORESIGHT_DEVLIST(tpiu_devs, "tpiu"); + /** * @base: memory mapped base address for this component. * @atclk: optional clock for the core parts of the TPIU. @@ -125,6 +127,10 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id) struct resource *res = &adev->res; struct coresight_desc desc = { 0 }; + desc.name = coresight_alloc_device_name(&tpiu_devs, dev); + if (!desc.name) + return -ENOMEM; + drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL); if (!drvdata) return -ENOMEM; @@ -157,7 +163,6 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id) desc.ops = &tpiu_cs_ops; desc.pdata = pdata; desc.dev = dev; - desc.name = dev_name(dev); drvdata->csdev = coresight_register(&desc); if (!IS_ERR(drvdata->csdev)) { diff --git a/drivers/hwtracing/coresight/coresight.c b/drivers/hwtracing/coresight/coresight.c index 1287778c3be5..86d1fc2c1bd4 100644 --- a/drivers/hwtracing/coresight/coresight.c +++ b/drivers/hwtracing/coresight/coresight.c @@ -1291,3 +1291,61 @@ void coresight_unregister(struct coresight_device *csdev) device_unregister(&csdev->dev); } EXPORT_SYMBOL_GPL(coresight_unregister); + + +/* + * coresight_search_device_idx - Search the fwnode handle of a device + * in the given dev_idx list. Must be called with the coresight_mutex held. + * + * Returns the index of the entry, when found. Otherwise, -ENOENT. + */ +static inline int coresight_search_device_idx(struct coresight_dev_list *dict, + struct fwnode_handle *fwnode) +{ + int i; + + for (i = 0; i < dict->nr_idx; i++) + if (dict->fwnode_list[i] == fwnode) + return i; + return -ENOENT; +} + +/* + * coresight_alloc_device_name - Get an index for a given device in the + * device index list specific to a driver. An index is allocated for a + * device and is tracked with the fwnode_handle to prevent allocating + * duplicate indices for the same device (e.g, if we defer probing of + * a device due to dependencies), in case the index is requested again. + */ +char *coresight_alloc_device_name(struct coresight_dev_list *dict, + struct device *dev) +{ + int idx; + char *name = NULL; + struct fwnode_handle **list; + + mutex_lock(&coresight_mutex); + + idx = coresight_search_device_idx(dict, dev_fwnode(dev)); + if (idx < 0) { + /* Make space for the new entry */ + idx = dict->nr_idx; + list = krealloc(dict->fwnode_list, + (idx + 1) * sizeof(*dict->fwnode_list), + GFP_KERNEL); + if (ZERO_OR_NULL_PTR(list)) { + idx = -ENOMEM; + goto done; + } + + list[idx] = dev_fwnode(dev); + dict->fwnode_list = list; + dict->nr_idx = idx + 1; + } + + name = devm_kasprintf(dev, GFP_KERNEL, "%s%d", dict->pfx, idx); +done: + mutex_unlock(&coresight_mutex); + return name; +} +EXPORT_SYMBOL_GPL(coresight_alloc_device_name); diff --git a/include/linux/coresight.h b/include/linux/coresight.h index b40544bc06fe..a2b68823717b 100644 --- a/include/linux/coresight.h +++ b/include/linux/coresight.h @@ -168,6 +168,28 @@ struct coresight_device { struct dev_ext_attribute *ea; }; +/* + * coresight_dev_list - Mapping for devices to "name" index for device + * names. + * + * @nr_idx: Number of entries already allocated. + * @pfx: Prefix pattern for device name. + * @fwnode_list: Array of fwnode_handles associated with each allocated + * index, upto nr_idx entries. + */ +struct coresight_dev_list { + int nr_idx; + const char *pfx; + struct fwnode_handle **fwnode_list; +}; + +#define DEFINE_CORESIGHT_DEVLIST(var, dev_pfx) \ +static struct coresight_dev_list (var) = { \ + .pfx = dev_pfx, \ + .nr_idx = 0, \ + .fwnode_list = NULL, \ +} + #define to_coresight_device(d) container_of(d, struct coresight_device, dev) #define source_ops(csdev) csdev->ops->source_ops @@ -261,7 +283,8 @@ extern int coresight_claim_device_unlocked(void __iomem *base); extern void coresight_disclaim_device(void __iomem *base); extern void coresight_disclaim_device_unlocked(void __iomem *base); - +extern char *coresight_alloc_device_name(struct coresight_dev_list *devs, + struct device *dev); #else static inline struct coresight_device * coresight_register(struct coresight_desc *desc) { return NULL; } -- cgit v1.2.3 From 84705f9f8c64cc3d8409ac63e5dd06ed97886fb7 Mon Sep 17 00:00:00 2001 From: Jolly Shah Date: Wed, 19 Jun 2019 13:59:34 -0700 Subject: firmware: xilinx: zynqmp: Remove unused macro ZYNQMP_PM_CAPABILITY_POWER capability is not supported by firmware and hence needs to be removed Signed-off-by: Tejas Patel Signed-off-by: Michal Simek Signed-off-by: Jolly Shah Signed-off-by: Greg Kroah-Hartman --- include/linux/firmware/xlnx-zynqmp.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/linux/firmware/xlnx-zynqmp.h b/include/linux/firmware/xlnx-zynqmp.h index 1262ea6a1f4b..778abbbc7d94 100644 --- a/include/linux/firmware/xlnx-zynqmp.h +++ b/include/linux/firmware/xlnx-zynqmp.h @@ -46,7 +46,6 @@ #define ZYNQMP_PM_CAPABILITY_ACCESS 0x1U #define ZYNQMP_PM_CAPABILITY_CONTEXT 0x2U #define ZYNQMP_PM_CAPABILITY_WAKEUP 0x4U -#define ZYNQMP_PM_CAPABILITY_POWER 0x8U /* * Firmware FPGA Manager flags -- cgit v1.2.3 From 1c2eb5b2853c9f513690ba6b71072d8eb65da16a Mon Sep 17 00:00:00 2001 From: Vishnu DASA Date: Fri, 24 May 2019 15:13:10 +0000 Subject: VMCI: Fix integer overflow in VMCI handle arrays The VMCI handle array has an integer overflow in vmci_handle_arr_append_entry when it tries to expand the array. This can be triggered from a guest, since the doorbell link hypercall doesn't impose a limit on the number of doorbell handles that a VM can create in the hypervisor, and these handles are stored in a handle array. In this change, we introduce a mandatory max capacity for handle arrays/lists to avoid excessive memory usage. Signed-off-by: Vishnu Dasa Reviewed-by: Adit Ranadive Reviewed-by: Jorgen Hansen Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/misc/vmw_vmci/vmci_context.c | 80 +++++++++++++++++-------------- drivers/misc/vmw_vmci/vmci_handle_array.c | 38 ++++++++++----- drivers/misc/vmw_vmci/vmci_handle_array.h | 29 +++++++---- include/linux/vmw_vmci_defs.h | 11 ++++- 4 files changed, 99 insertions(+), 59 deletions(-) (limited to 'include') diff --git a/drivers/misc/vmw_vmci/vmci_context.c b/drivers/misc/vmw_vmci/vmci_context.c index 300ed69fe2c7..16695366ec92 100644 --- a/drivers/misc/vmw_vmci/vmci_context.c +++ b/drivers/misc/vmw_vmci/vmci_context.c @@ -21,6 +21,9 @@ #include "vmci_driver.h" #include "vmci_event.h" +/* Use a wide upper bound for the maximum contexts. */ +#define VMCI_MAX_CONTEXTS 2000 + /* * List of current VMCI contexts. Contexts can be added by * vmci_ctx_create() and removed via vmci_ctx_destroy(). @@ -117,19 +120,22 @@ struct vmci_ctx *vmci_ctx_create(u32 cid, u32 priv_flags, /* Initialize host-specific VMCI context. */ init_waitqueue_head(&context->host_context.wait_queue); - context->queue_pair_array = vmci_handle_arr_create(0); + context->queue_pair_array = + vmci_handle_arr_create(0, VMCI_MAX_GUEST_QP_COUNT); if (!context->queue_pair_array) { error = -ENOMEM; goto err_free_ctx; } - context->doorbell_array = vmci_handle_arr_create(0); + context->doorbell_array = + vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT); if (!context->doorbell_array) { error = -ENOMEM; goto err_free_qp_array; } - context->pending_doorbell_array = vmci_handle_arr_create(0); + context->pending_doorbell_array = + vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT); if (!context->pending_doorbell_array) { error = -ENOMEM; goto err_free_db_array; @@ -204,7 +210,7 @@ static int ctx_fire_notification(u32 context_id, u32 priv_flags) * We create an array to hold the subscribers we find when * scanning through all contexts. */ - subscriber_array = vmci_handle_arr_create(0); + subscriber_array = vmci_handle_arr_create(0, VMCI_MAX_CONTEXTS); if (subscriber_array == NULL) return VMCI_ERROR_NO_MEM; @@ -623,20 +629,26 @@ int vmci_ctx_add_notification(u32 context_id, u32 remote_cid) spin_lock(&context->lock); - list_for_each_entry(n, &context->notifier_list, node) { - if (vmci_handle_is_equal(n->handle, notifier->handle)) { - exists = true; - break; + if (context->n_notifiers < VMCI_MAX_CONTEXTS) { + list_for_each_entry(n, &context->notifier_list, node) { + if (vmci_handle_is_equal(n->handle, notifier->handle)) { + exists = true; + break; + } } - } - if (exists) { - kfree(notifier); - result = VMCI_ERROR_ALREADY_EXISTS; + if (exists) { + kfree(notifier); + result = VMCI_ERROR_ALREADY_EXISTS; + } else { + list_add_tail_rcu(¬ifier->node, + &context->notifier_list); + context->n_notifiers++; + result = VMCI_SUCCESS; + } } else { - list_add_tail_rcu(¬ifier->node, &context->notifier_list); - context->n_notifiers++; - result = VMCI_SUCCESS; + kfree(notifier); + result = VMCI_ERROR_NO_MEM; } spin_unlock(&context->lock); @@ -721,8 +733,7 @@ static int vmci_ctx_get_chkpt_doorbells(struct vmci_ctx *context, u32 *buf_size, void **pbuf) { struct dbell_cpt_state *dbells; - size_t n_doorbells; - int i; + u32 i, n_doorbells; n_doorbells = vmci_handle_arr_get_size(context->doorbell_array); if (n_doorbells > 0) { @@ -860,7 +871,8 @@ int vmci_ctx_rcv_notifications_get(u32 context_id, spin_lock(&context->lock); *db_handle_array = context->pending_doorbell_array; - context->pending_doorbell_array = vmci_handle_arr_create(0); + context->pending_doorbell_array = + vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT); if (!context->pending_doorbell_array) { context->pending_doorbell_array = *db_handle_array; *db_handle_array = NULL; @@ -942,12 +954,11 @@ int vmci_ctx_dbell_create(u32 context_id, struct vmci_handle handle) return VMCI_ERROR_NOT_FOUND; spin_lock(&context->lock); - if (!vmci_handle_arr_has_entry(context->doorbell_array, handle)) { - vmci_handle_arr_append_entry(&context->doorbell_array, handle); - result = VMCI_SUCCESS; - } else { + if (!vmci_handle_arr_has_entry(context->doorbell_array, handle)) + result = vmci_handle_arr_append_entry(&context->doorbell_array, + handle); + else result = VMCI_ERROR_DUPLICATE_ENTRY; - } spin_unlock(&context->lock); vmci_ctx_put(context); @@ -1083,15 +1094,16 @@ int vmci_ctx_notify_dbell(u32 src_cid, if (!vmci_handle_arr_has_entry( dst_context->pending_doorbell_array, handle)) { - vmci_handle_arr_append_entry( + result = vmci_handle_arr_append_entry( &dst_context->pending_doorbell_array, handle); - - ctx_signal_notify(dst_context); - wake_up(&dst_context->host_context.wait_queue); - + if (result == VMCI_SUCCESS) { + ctx_signal_notify(dst_context); + wake_up(&dst_context->host_context.wait_queue); + } + } else { + result = VMCI_SUCCESS; } - result = VMCI_SUCCESS; } spin_unlock(&dst_context->lock); } @@ -1118,13 +1130,11 @@ int vmci_ctx_qp_create(struct vmci_ctx *context, struct vmci_handle handle) if (context == NULL || vmci_handle_is_invalid(handle)) return VMCI_ERROR_INVALID_ARGS; - if (!vmci_handle_arr_has_entry(context->queue_pair_array, handle)) { - vmci_handle_arr_append_entry(&context->queue_pair_array, - handle); - result = VMCI_SUCCESS; - } else { + if (!vmci_handle_arr_has_entry(context->queue_pair_array, handle)) + result = vmci_handle_arr_append_entry( + &context->queue_pair_array, handle); + else result = VMCI_ERROR_DUPLICATE_ENTRY; - } return result; } diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.c b/drivers/misc/vmw_vmci/vmci_handle_array.c index c527388f5d7b..de7fee7ead1b 100644 --- a/drivers/misc/vmw_vmci/vmci_handle_array.c +++ b/drivers/misc/vmw_vmci/vmci_handle_array.c @@ -8,24 +8,29 @@ #include #include "vmci_handle_array.h" -static size_t handle_arr_calc_size(size_t capacity) +static size_t handle_arr_calc_size(u32 capacity) { - return sizeof(struct vmci_handle_arr) + + return VMCI_HANDLE_ARRAY_HEADER_SIZE + capacity * sizeof(struct vmci_handle); } -struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity) +struct vmci_handle_arr *vmci_handle_arr_create(u32 capacity, u32 max_capacity) { struct vmci_handle_arr *array; + if (max_capacity == 0 || capacity > max_capacity) + return NULL; + if (capacity == 0) - capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE; + capacity = min((u32)VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY, + max_capacity); array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC); if (!array) return NULL; array->capacity = capacity; + array->max_capacity = max_capacity; array->size = 0; return array; @@ -36,27 +41,34 @@ void vmci_handle_arr_destroy(struct vmci_handle_arr *array) kfree(array); } -void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, - struct vmci_handle handle) +int vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, + struct vmci_handle handle) { struct vmci_handle_arr *array = *array_ptr; if (unlikely(array->size >= array->capacity)) { /* reallocate. */ struct vmci_handle_arr *new_array; - size_t new_capacity = array->capacity * VMCI_ARR_CAP_MULT; - size_t new_size = handle_arr_calc_size(new_capacity); + u32 capacity_bump = min(array->max_capacity - array->capacity, + array->capacity); + size_t new_size = handle_arr_calc_size(array->capacity + + capacity_bump); + + if (array->size >= array->max_capacity) + return VMCI_ERROR_NO_MEM; new_array = krealloc(array, new_size, GFP_ATOMIC); if (!new_array) - return; + return VMCI_ERROR_NO_MEM; - new_array->capacity = new_capacity; + new_array->capacity += capacity_bump; *array_ptr = array = new_array; } array->entries[array->size] = handle; array->size++; + + return VMCI_SUCCESS; } /* @@ -66,7 +78,7 @@ struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array, struct vmci_handle entry_handle) { struct vmci_handle handle = VMCI_INVALID_HANDLE; - size_t i; + u32 i; for (i = 0; i < array->size; i++) { if (vmci_handle_is_equal(array->entries[i], entry_handle)) { @@ -101,7 +113,7 @@ struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array) * Handle at given index, VMCI_INVALID_HANDLE if invalid index. */ struct vmci_handle -vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index) +vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, u32 index) { if (unlikely(index >= array->size)) return VMCI_INVALID_HANDLE; @@ -112,7 +124,7 @@ vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index) bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array, struct vmci_handle entry_handle) { - size_t i; + u32 i; for (i = 0; i < array->size; i++) if (vmci_handle_is_equal(array->entries[i], entry_handle)) diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.h b/drivers/misc/vmw_vmci/vmci_handle_array.h index bd1559a548e9..96193f85be5b 100644 --- a/drivers/misc/vmw_vmci/vmci_handle_array.h +++ b/drivers/misc/vmw_vmci/vmci_handle_array.h @@ -9,32 +9,41 @@ #define _VMCI_HANDLE_ARRAY_H_ #include +#include #include -#define VMCI_HANDLE_ARRAY_DEFAULT_SIZE 4 -#define VMCI_ARR_CAP_MULT 2 /* Array capacity multiplier */ - struct vmci_handle_arr { - size_t capacity; - size_t size; + u32 capacity; + u32 max_capacity; + u32 size; + u32 pad; struct vmci_handle entries[]; }; -struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity); +#define VMCI_HANDLE_ARRAY_HEADER_SIZE \ + offsetof(struct vmci_handle_arr, entries) +/* Select a default capacity that results in a 64 byte sized array */ +#define VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY 6 +/* Make sure that the max array size can be expressed by a u32 */ +#define VMCI_HANDLE_ARRAY_MAX_CAPACITY \ + ((U32_MAX - VMCI_HANDLE_ARRAY_HEADER_SIZE - 1) / \ + sizeof(struct vmci_handle)) + +struct vmci_handle_arr *vmci_handle_arr_create(u32 capacity, u32 max_capacity); void vmci_handle_arr_destroy(struct vmci_handle_arr *array); -void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, - struct vmci_handle handle); +int vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, + struct vmci_handle handle); struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array, struct vmci_handle entry_handle); struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array); struct vmci_handle -vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index); +vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, u32 index); bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array, struct vmci_handle entry_handle); struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array); -static inline size_t vmci_handle_arr_get_size( +static inline u32 vmci_handle_arr_get_size( const struct vmci_handle_arr *array) { return array->size; diff --git a/include/linux/vmw_vmci_defs.h b/include/linux/vmw_vmci_defs.h index 606504bf376a..fefb5292403b 100644 --- a/include/linux/vmw_vmci_defs.h +++ b/include/linux/vmw_vmci_defs.h @@ -62,9 +62,18 @@ enum { /* * A single VMCI device has an upper limit of 128MB on the amount of - * memory that can be used for queue pairs. + * memory that can be used for queue pairs. Since each queue pair + * consists of at least two pages, the memory limit also dictates the + * number of queue pairs a guest can create. */ #define VMCI_MAX_GUEST_QP_MEMORY (128 * 1024 * 1024) +#define VMCI_MAX_GUEST_QP_COUNT (VMCI_MAX_GUEST_QP_MEMORY / PAGE_SIZE / 2) + +/* + * There can be at most PAGE_SIZE doorbells since there is one doorbell + * per byte in the doorbell bitmap page. + */ +#define VMCI_MAX_GUEST_DOORBELL_COUNT PAGE_SIZE /* * Queues with pre-mapped data pages must be small, so that we don't pin -- cgit v1.2.3 From f50dfaf772db187deb562764e7aa3b988d6bc538 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 30 Jun 2019 16:03:02 +0200 Subject: misc: fsa9480: Delete this driver The FSA9480 has a new driver more appropriately located in the drivers/extcon subsystem. It is also more complete and includes device tree support. Delete the old misc driver. Cc: Arnd Bergmann Signed-off-by: Linus Walleij Reviewed-by: Chanwoo Choi Reviewed-by: Pawe Chmiel Link: https://lore.kernel.org/r/20190630140302.16245-1-linus.walleij@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/Kconfig | 9 - drivers/misc/Makefile | 1 - drivers/misc/fsa9480.c | 547 ---------------------------------- include/linux/platform_data/fsa9480.h | 24 -- 4 files changed, 581 deletions(-) delete mode 100644 drivers/misc/fsa9480.c delete mode 100644 include/linux/platform_data/fsa9480.h (limited to 'include') diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 8110d6a00c86..6abfc8e92fcc 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -422,15 +422,6 @@ config PCH_PHUB To compile this driver as a module, choose M here: the module will be called pch_phub. -config USB_SWITCH_FSA9480 - tristate "FSA9480 USB Switch" - depends on I2C - help - The FSA9480 is a USB port accessory detector and switch. - The FSA9480 is fully controlled using I2C and enables USB data, - stereo and mono audio, video, microphone and UART data to use - a common connector port. - config LATTICE_ECP3_CONFIG tristate "Lattice ECP3 FPGA bitstream configuration via SPI" depends on SPI && SYSFS diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 0cb35466c578..abd8ae249746 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -42,7 +42,6 @@ obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o obj-$(CONFIG_PCH_PHUB) += pch_phub.o obj-y += ti-st/ obj-y += lis3lv02d/ -obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ obj-$(CONFIG_INTEL_MEI) += mei/ obj-$(CONFIG_VMWARE_VMCI) += vmw_vmci/ diff --git a/drivers/misc/fsa9480.c b/drivers/misc/fsa9480.c deleted file mode 100644 index 4e11807040d3..000000000000 --- a/drivers/misc/fsa9480.c +++ /dev/null @@ -1,547 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * fsa9480.c - FSA9480 micro USB switch device driver - * - * Copyright (C) 2010 Samsung Electronics - * Minkyu Kang - * Wonguk Jeong - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* FSA9480 I2C registers */ -#define FSA9480_REG_DEVID 0x01 -#define FSA9480_REG_CTRL 0x02 -#define FSA9480_REG_INT1 0x03 -#define FSA9480_REG_INT2 0x04 -#define FSA9480_REG_INT1_MASK 0x05 -#define FSA9480_REG_INT2_MASK 0x06 -#define FSA9480_REG_ADC 0x07 -#define FSA9480_REG_TIMING1 0x08 -#define FSA9480_REG_TIMING2 0x09 -#define FSA9480_REG_DEV_T1 0x0a -#define FSA9480_REG_DEV_T2 0x0b -#define FSA9480_REG_BTN1 0x0c -#define FSA9480_REG_BTN2 0x0d -#define FSA9480_REG_CK 0x0e -#define FSA9480_REG_CK_INT1 0x0f -#define FSA9480_REG_CK_INT2 0x10 -#define FSA9480_REG_CK_INTMASK1 0x11 -#define FSA9480_REG_CK_INTMASK2 0x12 -#define FSA9480_REG_MANSW1 0x13 -#define FSA9480_REG_MANSW2 0x14 - -/* Control */ -#define CON_SWITCH_OPEN (1 << 4) -#define CON_RAW_DATA (1 << 3) -#define CON_MANUAL_SW (1 << 2) -#define CON_WAIT (1 << 1) -#define CON_INT_MASK (1 << 0) -#define CON_MASK (CON_SWITCH_OPEN | CON_RAW_DATA | \ - CON_MANUAL_SW | CON_WAIT) - -/* Device Type 1 */ -#define DEV_USB_OTG (1 << 7) -#define DEV_DEDICATED_CHG (1 << 6) -#define DEV_USB_CHG (1 << 5) -#define DEV_CAR_KIT (1 << 4) -#define DEV_UART (1 << 3) -#define DEV_USB (1 << 2) -#define DEV_AUDIO_2 (1 << 1) -#define DEV_AUDIO_1 (1 << 0) - -#define DEV_T1_USB_MASK (DEV_USB_OTG | DEV_USB) -#define DEV_T1_UART_MASK (DEV_UART) -#define DEV_T1_CHARGER_MASK (DEV_DEDICATED_CHG | DEV_USB_CHG) - -/* Device Type 2 */ -#define DEV_AV (1 << 6) -#define DEV_TTY (1 << 5) -#define DEV_PPD (1 << 4) -#define DEV_JIG_UART_OFF (1 << 3) -#define DEV_JIG_UART_ON (1 << 2) -#define DEV_JIG_USB_OFF (1 << 1) -#define DEV_JIG_USB_ON (1 << 0) - -#define DEV_T2_USB_MASK (DEV_JIG_USB_OFF | DEV_JIG_USB_ON) -#define DEV_T2_UART_MASK (DEV_JIG_UART_OFF | DEV_JIG_UART_ON) -#define DEV_T2_JIG_MASK (DEV_JIG_USB_OFF | DEV_JIG_USB_ON | \ - DEV_JIG_UART_OFF | DEV_JIG_UART_ON) - -/* - * Manual Switch - * D- [7:5] / D+ [4:2] - * 000: Open all / 001: USB / 010: AUDIO / 011: UART / 100: V_AUDIO - */ -#define SW_VAUDIO ((4 << 5) | (4 << 2)) -#define SW_UART ((3 << 5) | (3 << 2)) -#define SW_AUDIO ((2 << 5) | (2 << 2)) -#define SW_DHOST ((1 << 5) | (1 << 2)) -#define SW_AUTO ((0 << 5) | (0 << 2)) - -/* Interrupt 1 */ -#define INT_DETACH (1 << 1) -#define INT_ATTACH (1 << 0) - -struct fsa9480_usbsw { - struct i2c_client *client; - struct fsa9480_platform_data *pdata; - int dev1; - int dev2; - int mansw; -}; - -static struct fsa9480_usbsw *chip; - -static int fsa9480_write_reg(struct i2c_client *client, - int reg, int value) -{ - int ret; - - ret = i2c_smbus_write_byte_data(client, reg, value); - - if (ret < 0) - dev_err(&client->dev, "%s: err %d\n", __func__, ret); - - return ret; -} - -static int fsa9480_read_reg(struct i2c_client *client, int reg) -{ - int ret; - - ret = i2c_smbus_read_byte_data(client, reg); - - if (ret < 0) - dev_err(&client->dev, "%s: err %d\n", __func__, ret); - - return ret; -} - -static int fsa9480_read_irq(struct i2c_client *client, int *value) -{ - int ret; - - ret = i2c_smbus_read_i2c_block_data(client, - FSA9480_REG_INT1, 2, (u8 *)value); - *value &= 0xffff; - - if (ret < 0) - dev_err(&client->dev, "%s: err %d\n", __func__, ret); - - return ret; -} - -static void fsa9480_set_switch(const char *buf) -{ - struct fsa9480_usbsw *usbsw = chip; - struct i2c_client *client = usbsw->client; - unsigned int value; - unsigned int path = 0; - - value = fsa9480_read_reg(client, FSA9480_REG_CTRL); - - if (!strncmp(buf, "VAUDIO", 6)) { - path = SW_VAUDIO; - value &= ~CON_MANUAL_SW; - } else if (!strncmp(buf, "UART", 4)) { - path = SW_UART; - value &= ~CON_MANUAL_SW; - } else if (!strncmp(buf, "AUDIO", 5)) { - path = SW_AUDIO; - value &= ~CON_MANUAL_SW; - } else if (!strncmp(buf, "DHOST", 5)) { - path = SW_DHOST; - value &= ~CON_MANUAL_SW; - } else if (!strncmp(buf, "AUTO", 4)) { - path = SW_AUTO; - value |= CON_MANUAL_SW; - } else { - printk(KERN_ERR "Wrong command\n"); - return; - } - - usbsw->mansw = path; - fsa9480_write_reg(client, FSA9480_REG_MANSW1, path); - fsa9480_write_reg(client, FSA9480_REG_CTRL, value); -} - -static ssize_t fsa9480_get_switch(char *buf) -{ - struct fsa9480_usbsw *usbsw = chip; - struct i2c_client *client = usbsw->client; - unsigned int value; - - value = fsa9480_read_reg(client, FSA9480_REG_MANSW1); - - if (value == SW_VAUDIO) - return sprintf(buf, "VAUDIO\n"); - else if (value == SW_UART) - return sprintf(buf, "UART\n"); - else if (value == SW_AUDIO) - return sprintf(buf, "AUDIO\n"); - else if (value == SW_DHOST) - return sprintf(buf, "DHOST\n"); - else if (value == SW_AUTO) - return sprintf(buf, "AUTO\n"); - else - return sprintf(buf, "%x", value); -} - -static ssize_t fsa9480_show_device(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct fsa9480_usbsw *usbsw = dev_get_drvdata(dev); - struct i2c_client *client = usbsw->client; - int dev1, dev2; - - dev1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1); - dev2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2); - - if (!dev1 && !dev2) - return sprintf(buf, "NONE\n"); - - /* USB */ - if (dev1 & DEV_T1_USB_MASK || dev2 & DEV_T2_USB_MASK) - return sprintf(buf, "USB\n"); - - /* UART */ - if (dev1 & DEV_T1_UART_MASK || dev2 & DEV_T2_UART_MASK) - return sprintf(buf, "UART\n"); - - /* CHARGER */ - if (dev1 & DEV_T1_CHARGER_MASK) - return sprintf(buf, "CHARGER\n"); - - /* JIG */ - if (dev2 & DEV_T2_JIG_MASK) - return sprintf(buf, "JIG\n"); - - return sprintf(buf, "UNKNOWN\n"); -} - -static ssize_t fsa9480_show_manualsw(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return fsa9480_get_switch(buf); - -} - -static ssize_t fsa9480_set_manualsw(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - fsa9480_set_switch(buf); - - return count; -} - -static DEVICE_ATTR(device, S_IRUGO, fsa9480_show_device, NULL); -static DEVICE_ATTR(switch, S_IRUGO | S_IWUSR, - fsa9480_show_manualsw, fsa9480_set_manualsw); - -static struct attribute *fsa9480_attributes[] = { - &dev_attr_device.attr, - &dev_attr_switch.attr, - NULL -}; - -static const struct attribute_group fsa9480_group = { - .attrs = fsa9480_attributes, -}; - -static void fsa9480_detect_dev(struct fsa9480_usbsw *usbsw, int intr) -{ - int val1, val2, ctrl; - struct fsa9480_platform_data *pdata = usbsw->pdata; - struct i2c_client *client = usbsw->client; - - val1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1); - val2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2); - ctrl = fsa9480_read_reg(client, FSA9480_REG_CTRL); - - dev_info(&client->dev, "intr: 0x%x, dev1: 0x%x, dev2: 0x%x\n", - intr, val1, val2); - - if (!intr) - goto out; - - if (intr & INT_ATTACH) { /* Attached */ - /* USB */ - if (val1 & DEV_T1_USB_MASK || val2 & DEV_T2_USB_MASK) { - if (pdata->usb_cb) - pdata->usb_cb(FSA9480_ATTACHED); - - if (usbsw->mansw) { - fsa9480_write_reg(client, - FSA9480_REG_MANSW1, usbsw->mansw); - } - } - - /* UART */ - if (val1 & DEV_T1_UART_MASK || val2 & DEV_T2_UART_MASK) { - if (pdata->uart_cb) - pdata->uart_cb(FSA9480_ATTACHED); - - if (!(ctrl & CON_MANUAL_SW)) { - fsa9480_write_reg(client, - FSA9480_REG_MANSW1, SW_UART); - } - } - - /* CHARGER */ - if (val1 & DEV_T1_CHARGER_MASK) { - if (pdata->charger_cb) - pdata->charger_cb(FSA9480_ATTACHED); - } - - /* JIG */ - if (val2 & DEV_T2_JIG_MASK) { - if (pdata->jig_cb) - pdata->jig_cb(FSA9480_ATTACHED); - } - } else if (intr & INT_DETACH) { /* Detached */ - /* USB */ - if (usbsw->dev1 & DEV_T1_USB_MASK || - usbsw->dev2 & DEV_T2_USB_MASK) { - if (pdata->usb_cb) - pdata->usb_cb(FSA9480_DETACHED); - } - - /* UART */ - if (usbsw->dev1 & DEV_T1_UART_MASK || - usbsw->dev2 & DEV_T2_UART_MASK) { - if (pdata->uart_cb) - pdata->uart_cb(FSA9480_DETACHED); - } - - /* CHARGER */ - if (usbsw->dev1 & DEV_T1_CHARGER_MASK) { - if (pdata->charger_cb) - pdata->charger_cb(FSA9480_DETACHED); - } - - /* JIG */ - if (usbsw->dev2 & DEV_T2_JIG_MASK) { - if (pdata->jig_cb) - pdata->jig_cb(FSA9480_DETACHED); - } - } - - usbsw->dev1 = val1; - usbsw->dev2 = val2; - -out: - ctrl &= ~CON_INT_MASK; - fsa9480_write_reg(client, FSA9480_REG_CTRL, ctrl); -} - -static irqreturn_t fsa9480_irq_handler(int irq, void *data) -{ - struct fsa9480_usbsw *usbsw = data; - struct i2c_client *client = usbsw->client; - int intr; - - /* clear interrupt */ - fsa9480_read_irq(client, &intr); - - /* device detection */ - fsa9480_detect_dev(usbsw, intr); - - return IRQ_HANDLED; -} - -static int fsa9480_irq_init(struct fsa9480_usbsw *usbsw) -{ - struct fsa9480_platform_data *pdata = usbsw->pdata; - struct i2c_client *client = usbsw->client; - int ret; - int intr; - unsigned int ctrl = CON_MASK; - - /* clear interrupt */ - fsa9480_read_irq(client, &intr); - - /* unmask interrupt (attach/detach only) */ - fsa9480_write_reg(client, FSA9480_REG_INT1_MASK, 0xfc); - fsa9480_write_reg(client, FSA9480_REG_INT2_MASK, 0x1f); - - usbsw->mansw = fsa9480_read_reg(client, FSA9480_REG_MANSW1); - - if (usbsw->mansw) - ctrl &= ~CON_MANUAL_SW; /* Manual Switching Mode */ - - fsa9480_write_reg(client, FSA9480_REG_CTRL, ctrl); - - if (pdata && pdata->cfg_gpio) - pdata->cfg_gpio(); - - if (client->irq) { - ret = request_threaded_irq(client->irq, NULL, - fsa9480_irq_handler, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, - "fsa9480 micro USB", usbsw); - if (ret) { - dev_err(&client->dev, "failed to request IRQ\n"); - return ret; - } - - if (pdata) - device_init_wakeup(&client->dev, pdata->wakeup); - } - - return 0; -} - -static int fsa9480_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter = client->adapter; - struct fsa9480_usbsw *usbsw; - int ret = 0; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EIO; - - usbsw = kzalloc(sizeof(struct fsa9480_usbsw), GFP_KERNEL); - if (!usbsw) { - dev_err(&client->dev, "failed to allocate driver data\n"); - return -ENOMEM; - } - - usbsw->client = client; - usbsw->pdata = client->dev.platform_data; - - chip = usbsw; - - i2c_set_clientdata(client, usbsw); - - ret = fsa9480_irq_init(usbsw); - if (ret) - goto fail1; - - ret = sysfs_create_group(&client->dev.kobj, &fsa9480_group); - if (ret) { - dev_err(&client->dev, - "failed to create fsa9480 attribute group\n"); - goto fail2; - } - - /* ADC Detect Time: 500ms */ - fsa9480_write_reg(client, FSA9480_REG_TIMING1, 0x6); - - if (chip->pdata->reset_cb) - chip->pdata->reset_cb(); - - /* device detection */ - fsa9480_detect_dev(usbsw, INT_ATTACH); - - pm_runtime_set_active(&client->dev); - - return 0; - -fail2: - if (client->irq) - free_irq(client->irq, usbsw); -fail1: - kfree(usbsw); - return ret; -} - -static int fsa9480_remove(struct i2c_client *client) -{ - struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client); - - if (client->irq) - free_irq(client->irq, usbsw); - - sysfs_remove_group(&client->dev.kobj, &fsa9480_group); - device_init_wakeup(&client->dev, 0); - kfree(usbsw); - return 0; -} - -#ifdef CONFIG_PM_SLEEP - -static int fsa9480_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client); - struct fsa9480_platform_data *pdata = usbsw->pdata; - - if (device_may_wakeup(&client->dev) && client->irq) - enable_irq_wake(client->irq); - - if (pdata->usb_power) - pdata->usb_power(0); - - return 0; -} - -static int fsa9480_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct fsa9480_usbsw *usbsw = i2c_get_clientdata(client); - int dev1, dev2; - - if (device_may_wakeup(&client->dev) && client->irq) - disable_irq_wake(client->irq); - - /* - * Clear Pending interrupt. Note that detect_dev does what - * the interrupt handler does. So, we don't miss pending and - * we reenable interrupt if there is one. - */ - fsa9480_read_reg(client, FSA9480_REG_INT1); - fsa9480_read_reg(client, FSA9480_REG_INT2); - - dev1 = fsa9480_read_reg(client, FSA9480_REG_DEV_T1); - dev2 = fsa9480_read_reg(client, FSA9480_REG_DEV_T2); - - /* device detection */ - fsa9480_detect_dev(usbsw, (dev1 || dev2) ? INT_ATTACH : INT_DETACH); - - return 0; -} - -static SIMPLE_DEV_PM_OPS(fsa9480_pm_ops, fsa9480_suspend, fsa9480_resume); -#define FSA9480_PM_OPS (&fsa9480_pm_ops) - -#else - -#define FSA9480_PM_OPS NULL - -#endif /* CONFIG_PM_SLEEP */ - -static const struct i2c_device_id fsa9480_id[] = { - {"fsa9480", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, fsa9480_id); - -static struct i2c_driver fsa9480_i2c_driver = { - .driver = { - .name = "fsa9480", - .pm = FSA9480_PM_OPS, - }, - .probe = fsa9480_probe, - .remove = fsa9480_remove, - .id_table = fsa9480_id, -}; - -module_i2c_driver(fsa9480_i2c_driver); - -MODULE_AUTHOR("Minkyu Kang "); -MODULE_DESCRIPTION("FSA9480 USB Switch driver"); -MODULE_LICENSE("GPL"); diff --git a/include/linux/platform_data/fsa9480.h b/include/linux/platform_data/fsa9480.h deleted file mode 100644 index dea8d84448ec..000000000000 --- a/include/linux/platform_data/fsa9480.h +++ /dev/null @@ -1,24 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) 2010 Samsung Electronics - * Minkyu Kang - */ - -#ifndef _FSA9480_H_ -#define _FSA9480_H_ - -#define FSA9480_ATTACHED 1 -#define FSA9480_DETACHED 0 - -struct fsa9480_platform_data { - void (*cfg_gpio) (void); - void (*usb_cb) (u8 attached); - void (*uart_cb) (u8 attached); - void (*charger_cb) (u8 attached); - void (*jig_cb) (u8 attached); - void (*reset_cb) (void); - void (*usb_power) (u8 on); - int wakeup; -}; - -#endif /* _FSA9480_H_ */ -- cgit v1.2.3 From 8242c59315b7b40ac97e1274d715665569992ff4 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 22 May 2019 14:47:19 -0500 Subject: soundwire: add port-related definitions Somehow previous header files did not include definition for sink/source, flow and grouping. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Vinod Koul --- include/linux/soundwire/sdw.h | 53 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) (limited to 'include') diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 35662d9c2c62..69ae680a5a21 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -41,6 +41,31 @@ struct sdw_slave; #define SDW_DAI_ID_RANGE_START 100 #define SDW_DAI_ID_RANGE_END 200 +enum { + SDW_PORT_DIRN_SINK = 0, + SDW_PORT_DIRN_SOURCE, + SDW_PORT_DIRN_MAX, +}; + +/* + * constants for flow control, ports and transport + * + * these are bit masks as devices can have multiple capabilities + */ + +/* + * flow modes for SDW port. These can be isochronous, tx controlled, + * rx controlled or async + */ +#define SDW_PORT_FLOW_MODE_ISOCH 0 +#define SDW_PORT_FLOW_MODE_TX_CNTRL BIT(0) +#define SDW_PORT_FLOW_MODE_RX_CNTRL BIT(1) +#define SDW_PORT_FLOW_MODE_ASYNC GENMASK(1, 0) + +/* sample packaging for block. It can be per port or per channel */ +#define SDW_BLOCK_PACKG_PER_PORT BIT(0) +#define SDW_BLOCK_PACKG_PER_CH BIT(1) + /** * enum sdw_slave_status - Slave status * @SDW_SLAVE_UNATTACHED: Slave is not attached with the bus. @@ -76,6 +101,14 @@ enum sdw_command_response { SDW_CMD_FAIL_OTHER = 4, }; +/* block group count enum */ +enum sdw_dpn_grouping { + SDW_BLK_GRP_CNT_1 = 0, + SDW_BLK_GRP_CNT_2 = 1, + SDW_BLK_GRP_CNT_3 = 2, + SDW_BLK_GRP_CNT_4 = 3, +}; + /** * enum sdw_stream_type: data stream type * @@ -100,6 +133,26 @@ enum sdw_data_direction { SDW_DATA_DIR_TX = 1, }; +/** + * enum sdw_port_data_mode: Data Port mode + * + * @SDW_PORT_DATA_MODE_NORMAL: Normal data mode where audio data is received + * and transmitted. + * @SDW_PORT_DATA_MODE_STATIC_1: Simple test mode which uses static value of + * logic 1. The encoding will result in signal transitions at every bitslot + * owned by this Port + * @SDW_PORT_DATA_MODE_STATIC_0: Simple test mode which uses static value of + * logic 0. The encoding will result in no signal transitions + * @SDW_PORT_DATA_MODE_PRBS: Test mode which uses a PRBS generator to produce + * a pseudo random data pattern that is transferred + */ +enum sdw_port_data_mode { + SDW_PORT_DATA_MODE_NORMAL = 0, + SDW_PORT_DATA_MODE_STATIC_1 = 1, + SDW_PORT_DATA_MODE_STATIC_0 = 2, + SDW_PORT_DATA_MODE_PRBS = 3, +}; + /* * SDW properties, defined in MIPI DisCo spec v1.0 */ -- cgit v1.2.3 From 53f3c097375c94e87b41227ebdff83c4f4e3af41 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 22 May 2019 14:47:20 -0500 Subject: soundwire: remove master data port properties The SoundWire and DisCo specifications do not define Master data ports or related properties. Data ports are only defined for Slave devices, so remove the unused member in properties. Credits: this patch is based on an earlier internal contribution by Vinod Koul, Sanyog Kale, Shreyas Nc and Hardik Shah. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Vinod Koul --- include/linux/soundwire/sdw.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 69ae680a5a21..831a370eaedd 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -377,7 +377,6 @@ struct sdw_slave_prop { * @dynamic_frame: Dynamic frame supported * @err_threshold: Number of times that software may retry sending a single * command - * @dpn_prop: Data Port N properties */ struct sdw_master_prop { u32 revision; @@ -393,7 +392,6 @@ struct sdw_master_prop { u32 default_col; bool dynamic_frame; u32 err_threshold; - struct sdw_dpn_prop *dpn_prop; }; int sdw_master_read_prop(struct sdw_bus *bus); -- cgit v1.2.3 From 446701d1d161f04aa107903bfe7ec14e1f6cd17f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 22 May 2019 14:47:21 -0500 Subject: soundwire: mipi-disco: remove master_count property for masters The master_count is only defined for a Controller or a Slave in the MIPI DisCo for SoundWire document. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Vinod Koul --- include/linux/soundwire/sdw.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 831a370eaedd..14376d8458c3 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -364,7 +364,6 @@ struct sdw_slave_prop { /** * struct sdw_master_prop - Master properties * @revision: MIPI spec version of the implementation - * @master_count: Number of masters * @clk_stop_mode: Bitmap for Clock Stop modes supported * @max_freq: Maximum Bus clock frequency, in Hz * @num_clk_gears: Number of clock gears supported @@ -380,7 +379,6 @@ struct sdw_slave_prop { */ struct sdw_master_prop { u32 revision; - u32 master_count; enum sdw_clk_stop_mode clk_stop_mode; u32 max_freq; u32 num_clk_gears; -- cgit v1.2.3 From 3424305b8be456a8e23c951b8c9aebad0c765ff7 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 22 May 2019 14:47:22 -0500 Subject: soundwire: rename 'freq' fields Rename all fields with 'freq' as 'clk_freq' to follow the MIPI specification and avoid confusion between bus clock and audio clocks. No functionality change. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 4 ++-- drivers/soundwire/intel.c | 11 ++++++----- drivers/soundwire/mipi_disco.c | 23 ++++++++++++----------- drivers/soundwire/stream.c | 2 +- include/linux/soundwire/sdw.h | 12 ++++++------ 5 files changed, 27 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index aac35fc3cf22..96e42df8f458 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -87,7 +87,7 @@ int sdw_add_bus_master(struct sdw_bus *bus) /* * Initialize clock values based on Master properties. The max - * frequency is read from max_freq property. Current assumption + * frequency is read from max_clk_freq property. Current assumption * is that the bus will start at highest clock frequency when * powered on. * @@ -95,7 +95,7 @@ int sdw_add_bus_master(struct sdw_bus *bus) * to start with bank 0 (Table 40 of Spec) */ prop = &bus->prop; - bus->params.max_dr_freq = prop->max_freq * SDW_DOUBLE_RATE_FACTOR; + bus->params.max_dr_freq = prop->max_clk_freq * SDW_DOUBLE_RATE_FACTOR; bus->params.curr_dr_freq = bus->params.max_dr_freq; bus->params.curr_bank = SDW_BANK0; bus->params.next_bank = SDW_BANK1; diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index 31336b0271b0..4ac141730b13 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -796,13 +796,14 @@ static int intel_prop_read(struct sdw_bus *bus) sdw_master_read_prop(bus); /* BIOS is not giving some values correctly. So, lets override them */ - bus->prop.num_freq = 1; - bus->prop.freq = devm_kcalloc(bus->dev, bus->prop.num_freq, - sizeof(*bus->prop.freq), GFP_KERNEL); - if (!bus->prop.freq) + bus->prop.num_clk_freq = 1; + bus->prop.clk_freq = devm_kcalloc(bus->dev, bus->prop.num_clk_freq, + sizeof(*bus->prop.clk_freq), + GFP_KERNEL); + if (!bus->prop.clk_freq) return -ENOMEM; - bus->prop.freq[0] = bus->prop.max_freq; + bus->prop.clk_freq[0] = bus->prop.max_clk_freq; bus->prop.err_threshold = 5; return 0; diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index 6df68584c963..b1770af43fa8 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -58,31 +58,32 @@ int sdw_master_read_prop(struct sdw_bus *bus) fwnode_property_read_u32(link, "mipi-sdw-max-clock-frequency", - &prop->max_freq); + &prop->max_clk_freq); nval = fwnode_property_read_u32_array(link, "mipi-sdw-clock-frequencies-supported", NULL, 0); if (nval > 0) { - prop->num_freq = nval; - prop->freq = devm_kcalloc(bus->dev, prop->num_freq, - sizeof(*prop->freq), GFP_KERNEL); - if (!prop->freq) + prop->num_clk_freq = nval; + prop->clk_freq = devm_kcalloc(bus->dev, prop->num_clk_freq, + sizeof(*prop->clk_freq), + GFP_KERNEL); + if (!prop->clk_freq) return -ENOMEM; fwnode_property_read_u32_array(link, "mipi-sdw-clock-frequencies-supported", - prop->freq, prop->num_freq); + prop->clk_freq, prop->num_clk_freq); } /* * Check the frequencies supported. If FW doesn't provide max * freq, then populate here by checking values. */ - if (!prop->max_freq && prop->freq) { - prop->max_freq = prop->freq[0]; - for (i = 1; i < prop->num_freq; i++) { - if (prop->freq[i] > prop->max_freq) - prop->max_freq = prop->freq[i]; + if (!prop->max_clk_freq && prop->clk_freq) { + prop->max_clk_freq = prop->clk_freq[0]; + for (i = 1; i < prop->num_clk_freq; i++) { + if (prop->clk_freq[i] > prop->max_clk_freq) + prop->max_clk_freq = prop->clk_freq[i]; } } diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index d01060dbee96..89edc897b8eb 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -1474,7 +1474,7 @@ static int _sdw_prepare_stream(struct sdw_stream_runtime *stream) memcpy(¶ms, &bus->params, sizeof(params)); /* TODO: Support Asynchronous mode */ - if ((prop->max_freq % stream->params.rate) != 0) { + if ((prop->max_clk_freq % stream->params.rate) != 0) { dev_err(bus->dev, "Async mode not supported\n"); return -EINVAL; } diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 14376d8458c3..c6ded0d7a9f2 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -365,11 +365,11 @@ struct sdw_slave_prop { * struct sdw_master_prop - Master properties * @revision: MIPI spec version of the implementation * @clk_stop_mode: Bitmap for Clock Stop modes supported - * @max_freq: Maximum Bus clock frequency, in Hz + * @max_clk_freq: Maximum Bus clock frequency, in Hz * @num_clk_gears: Number of clock gears supported * @clk_gears: Clock gears supported - * @num_freq: Number of clock frequencies supported, in Hz - * @freq: Clock frequencies supported, in Hz + * @num_clk_freq: Number of clock frequencies supported, in Hz + * @clk_freq: Clock frequencies supported, in Hz * @default_frame_rate: Controller default Frame rate, in Hz * @default_row: Number of rows * @default_col: Number of columns @@ -380,11 +380,11 @@ struct sdw_slave_prop { struct sdw_master_prop { u32 revision; enum sdw_clk_stop_mode clk_stop_mode; - u32 max_freq; + u32 max_clk_freq; u32 num_clk_gears; u32 *clk_gears; - u32 num_freq; - u32 *freq; + u32 num_clk_freq; + u32 *clk_freq; u32 default_frame_rate; u32 default_row; u32 default_col; -- cgit v1.2.3 From 53d2e9c3773478d00d1851cc048d7ef9e60c7b6d Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 22 May 2019 14:47:23 -0500 Subject: soundwire: mipi-disco: fix clock stop modes Fix support for clock_stop_mode0 and 1. The existing code uses a bitmask between enums, one of which being zero. Or-ing with zero is not very useful in general...Fix by or-ing with a BIT dependent on the enum value. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Vinod Koul --- drivers/soundwire/mipi_disco.c | 4 ++-- include/linux/soundwire/sdw.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index b1770af43fa8..efb87ee0e7fc 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -50,11 +50,11 @@ int sdw_master_read_prop(struct sdw_bus *bus) if (fwnode_property_read_bool(link, "mipi-sdw-clock-stop-mode0-supported")) - prop->clk_stop_mode = SDW_CLK_STOP_MODE0; + prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE0); if (fwnode_property_read_bool(link, "mipi-sdw-clock-stop-mode1-supported")) - prop->clk_stop_mode |= SDW_CLK_STOP_MODE1; + prop->clk_stop_modes |= BIT(SDW_CLK_STOP_MODE1); fwnode_property_read_u32(link, "mipi-sdw-max-clock-frequency", diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index c6ded0d7a9f2..0e3fdd03e589 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -364,7 +364,7 @@ struct sdw_slave_prop { /** * struct sdw_master_prop - Master properties * @revision: MIPI spec version of the implementation - * @clk_stop_mode: Bitmap for Clock Stop modes supported + * @clk_stop_modes: Bitmap, bit N set when clock-stop-modeN supported * @max_clk_freq: Maximum Bus clock frequency, in Hz * @num_clk_gears: Number of clock gears supported * @clk_gears: Clock gears supported @@ -379,7 +379,7 @@ struct sdw_slave_prop { */ struct sdw_master_prop { u32 revision; - enum sdw_clk_stop_mode clk_stop_mode; + u32 clk_stop_modes; u32 max_clk_freq; u32 num_clk_gears; u32 *clk_gears; -- cgit v1.2.3 From f6686a7d026dc00cecca2d2cefb7f75bb2f84801 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 22 May 2019 14:47:24 -0500 Subject: soundwire: clarify comment The MIPI DisCo spec refers to dynamic frame shape, not to dynamic shape. Clarify. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Vinod Koul --- include/linux/soundwire/sdw.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index 0e3fdd03e589..b7efa819d425 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -373,7 +373,7 @@ struct sdw_slave_prop { * @default_frame_rate: Controller default Frame rate, in Hz * @default_row: Number of rows * @default_col: Number of columns - * @dynamic_frame: Dynamic frame supported + * @dynamic_frame: Dynamic frame shape supported * @err_threshold: Number of times that software may retry sending a single * command */ -- cgit v1.2.3 From 8acbbfec280f1ee72ebeec407e39aa0d1b879b59 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 22 May 2019 14:47:25 -0500 Subject: soundwire: rename/clarify MIPI DisCo properties The existing definitions are ambiguous and possibly misleading. For DP0, 'flow-control' is only relevant for the BRA protocol and should not be confused with async modes explicitly not supported for DP0, add prefix to follow MIPI DisCo definition The use of 'device_interrupts' is also questionable. The MIPI SoundWire spec defines Slave-, DP0- and DPN-level implementation-defined interrupts. Using the 'device' prefix in the last two cases is misleading, not only is the term 'device' overloaded but these properties are only valid at the DP0 and DPn levels. Rename to follow the MIPI definitions, no need to be creative here. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Vinod Koul --- drivers/soundwire/bus.c | 2 +- drivers/soundwire/mipi_disco.c | 6 +++--- drivers/soundwire/stream.c | 6 +++--- include/linux/soundwire/sdw.h | 13 +++++++------ 4 files changed, 14 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 96e42df8f458..fe745830a261 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -648,7 +648,7 @@ static int sdw_initialize_slave(struct sdw_slave *slave) return 0; /* Enable DP0 interrupts */ - val = prop->dp0_prop->device_interrupts; + val = prop->dp0_prop->imp_def_interrupts; val |= SDW_DP0_INT_PORT_READY | SDW_DP0_INT_BRA_FAILURE; ret = sdw_update(slave, SDW_DP0_INTMASK, val, val); diff --git a/drivers/soundwire/mipi_disco.c b/drivers/soundwire/mipi_disco.c index efb87ee0e7fc..79fee1b21ab6 100644 --- a/drivers/soundwire/mipi_disco.c +++ b/drivers/soundwire/mipi_disco.c @@ -150,13 +150,13 @@ static int sdw_slave_read_dp0(struct sdw_slave *slave, dp0->words, dp0->num_words); } - dp0->flow_controlled = fwnode_property_read_bool(port, + dp0->BRA_flow_controlled = fwnode_property_read_bool(port, "mipi-sdw-bra-flow-controlled"); dp0->simple_ch_prep_sm = fwnode_property_read_bool(port, "mipi-sdw-simplified-channel-prepare-sm"); - dp0->device_interrupts = fwnode_property_read_bool(port, + dp0->imp_def_interrupts = fwnode_property_read_bool(port, "mipi-sdw-imp-def-dp0-interrupts-supported"); return 0; @@ -225,7 +225,7 @@ static int sdw_slave_read_dpn(struct sdw_slave *slave, fwnode_property_read_u32(node, "mipi-sdw-imp-def-dpn-interrupts-supported", - &dpn[i].device_interrupts); + &dpn[i].imp_def_interrupts); fwnode_property_read_u32(node, "mipi-sdw-min-channel-number", &dpn[i].min_ch); diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index 89edc897b8eb..ce9cb7fa4724 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -439,7 +439,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus, prep_ch.bank = bus->params.next_bank; - if (dpn_prop->device_interrupts || !dpn_prop->simple_ch_prep_sm) + if (dpn_prop->imp_def_interrupts || !dpn_prop->simple_ch_prep_sm) intr = true; /* @@ -449,7 +449,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus, */ if (prep && intr) { ret = sdw_configure_dpn_intr(s_rt->slave, p_rt->num, prep, - dpn_prop->device_interrupts); + dpn_prop->imp_def_interrupts); if (ret < 0) return ret; } @@ -493,7 +493,7 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus, /* Disable interrupt after Port de-prepare */ if (!prep && intr) ret = sdw_configure_dpn_intr(s_rt->slave, p_rt->num, prep, - dpn_prop->device_interrupts); + dpn_prop->imp_def_interrupts); return ret; } diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index b7efa819d425..bea46bd8b6ce 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -206,10 +206,11 @@ enum sdw_clk_stop_mode { * (inclusive) * @num_words: number of wordlengths supported * @words: wordlengths supported - * @flow_controlled: Slave implementation results in an OK_NotReady + * @BRA_flow_controlled: Slave implementation results in an OK_NotReady * response * @simple_ch_prep_sm: If channel prepare sequence is required - * @device_interrupts: If implementation-defined interrupts are supported + * @imp_def_interrupts: If set, each bit corresponds to support for + * implementation-defined interrupts * * The wordlengths are specified by Spec as max, min AND number of * discrete values, implementation can define based on the wordlengths they @@ -220,9 +221,9 @@ struct sdw_dp0_prop { u32 min_word; u32 num_words; u32 *words; - bool flow_controlled; + bool BRA_flow_controlled; bool simple_ch_prep_sm; - bool device_interrupts; + bool imp_def_interrupts; }; /** @@ -272,7 +273,7 @@ struct sdw_dpn_audio_mode { * @simple_ch_prep_sm: If the port supports simplified channel prepare state * machine * @ch_prep_timeout: Port-specific timeout value, in milliseconds - * @device_interrupts: If set, each bit corresponds to support for + * @imp_def_interrupts: If set, each bit corresponds to support for * implementation-defined interrupts * @max_ch: Maximum channels supported * @min_ch: Minimum channels supported @@ -297,7 +298,7 @@ struct sdw_dpn_prop { u32 max_grouping; bool simple_ch_prep_sm; u32 ch_prep_timeout; - u32 device_interrupts; + u32 imp_def_interrupts; u32 max_ch; u32 min_ch; u32 num_ch; -- cgit v1.2.3 From 2aeac95d1a4cc85aae57ab842d5c3340df0f817f Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Tue, 11 Jun 2019 11:40:41 +0100 Subject: soundwire: add module_sdw_driver helper macro This Helper macro is for SoundWire drivers which do not do anything special in module init/exit. This eliminates a lot of boilerplate. Each module may only use this macro once, and calling it replaces module_init() and module_exit() Signed-off-by: Srinivas Kandagatla Signed-off-by: Vinod Koul --- include/linux/soundwire/sdw_type.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'include') diff --git a/include/linux/soundwire/sdw_type.h b/include/linux/soundwire/sdw_type.h index 9c756b5a0dfe..aaa7f4267c14 100644 --- a/include/linux/soundwire/sdw_type.h +++ b/include/linux/soundwire/sdw_type.h @@ -16,4 +16,15 @@ void sdw_unregister_driver(struct sdw_driver *drv); int sdw_slave_modalias(const struct sdw_slave *slave, char *buf, size_t size); +/** + * module_sdw_driver() - Helper macro for registering a Soundwire driver + * @__sdw_driver: soundwire slave driver struct + * + * Helper macro for Soundwire drivers which do not do anything special in + * module init/exit. This eliminates a lot of boilerplate. Each module may only + * use this macro once, and calling it replaces module_init() and module_exit() + */ +#define module_sdw_driver(__sdw_driver) \ + module_driver(__sdw_driver, sdw_register_driver, \ + sdw_unregister_driver) #endif /* __SOUNDWIRE_TYPES_H */ -- cgit v1.2.3 From e8960ca06bb22d0d84edf246b0bf395e8322e127 Mon Sep 17 00:00:00 2001 From: Tomer Tayar Date: Mon, 1 Jul 2019 13:59:45 +0000 Subject: habanalabs: Add busy engines bitmask to HW idle IOCTL The information which is currently provided as a response to the "HL_INFO_HW_IDLE" IOCTL is merely a general boolean value. This patch extends it and provides also a bitmask that indicates which of the device engines are busy. Signed-off-by: Tomer Tayar Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/debugfs.c | 2 +- drivers/misc/habanalabs/goya/goya.c | 11 +++++++++-- drivers/misc/habanalabs/habanalabs.h | 3 ++- drivers/misc/habanalabs/habanalabs_ioctl.c | 3 ++- include/uapi/misc/habanalabs.h | 30 +++++++++++++++++++++++++++++- 5 files changed, 43 insertions(+), 6 deletions(-) (limited to 'include') diff --git a/drivers/misc/habanalabs/debugfs.c b/drivers/misc/habanalabs/debugfs.c index 6a5dfb14eca1..18e499c900c7 100644 --- a/drivers/misc/habanalabs/debugfs.c +++ b/drivers/misc/habanalabs/debugfs.c @@ -506,7 +506,7 @@ static int engines_show(struct seq_file *s, void *data) struct hl_dbg_device_entry *dev_entry = entry->dev_entry; struct hl_device *hdev = dev_entry->hdev; - hdev->asic_funcs->is_device_idle(hdev, s); + hdev->asic_funcs->is_device_idle(hdev, NULL, s); return 0; } diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c index 41e97531f300..75294ec65257 100644 --- a/drivers/misc/habanalabs/goya/goya.c +++ b/drivers/misc/habanalabs/goya/goya.c @@ -2828,7 +2828,7 @@ static int goya_send_job_on_qman0(struct hl_device *hdev, struct hl_cs_job *job) else timeout = HL_DEVICE_TIMEOUT_USEC; - if (!hdev->asic_funcs->is_device_idle(hdev, NULL)) { + if (!hdev->asic_funcs->is_device_idle(hdev, NULL, NULL)) { dev_err_ratelimited(hdev->dev, "Can't send KMD job on QMAN0 because the device is not idle\n"); return -EBUSY; @@ -4914,7 +4914,8 @@ int goya_armcp_info_get(struct hl_device *hdev) return 0; } -static bool goya_is_device_idle(struct hl_device *hdev, struct seq_file *s) +static bool goya_is_device_idle(struct hl_device *hdev, u32 *mask, + struct seq_file *s) { const char *fmt = "%-5d%-9s%#-14x%#-16x%#x\n"; const char *dma_fmt = "%-5d%-9s%#-14x%#x\n"; @@ -4937,6 +4938,8 @@ static bool goya_is_device_idle(struct hl_device *hdev, struct seq_file *s) IS_DMA_IDLE(dma_core_sts0); is_idle &= is_eng_idle; + if (mask) + *mask |= !is_eng_idle << (GOYA_ENGINE_ID_DMA_0 + i); if (s) seq_printf(s, dma_fmt, i, is_eng_idle ? "Y" : "N", qm_glbl_sts0, dma_core_sts0); @@ -4958,6 +4961,8 @@ static bool goya_is_device_idle(struct hl_device *hdev, struct seq_file *s) IS_TPC_IDLE(tpc_cfg_sts); is_idle &= is_eng_idle; + if (mask) + *mask |= !is_eng_idle << (GOYA_ENGINE_ID_TPC_0 + i); if (s) seq_printf(s, fmt, i, is_eng_idle ? "Y" : "N", qm_glbl_sts0, cmdq_glbl_sts0, tpc_cfg_sts); @@ -4976,6 +4981,8 @@ static bool goya_is_device_idle(struct hl_device *hdev, struct seq_file *s) IS_MME_IDLE(mme_arch_sts); is_idle &= is_eng_idle; + if (mask) + *mask |= !is_eng_idle << GOYA_ENGINE_ID_MME_0; if (s) { seq_printf(s, fmt, 0, is_eng_idle ? "Y" : "N", qm_glbl_sts0, cmdq_glbl_sts0, mme_arch_sts); diff --git a/drivers/misc/habanalabs/habanalabs.h b/drivers/misc/habanalabs/habanalabs.h index 2c9ea61099b4..10da9940ee0d 100644 --- a/drivers/misc/habanalabs/habanalabs.h +++ b/drivers/misc/habanalabs/habanalabs.h @@ -557,7 +557,8 @@ struct hl_asic_funcs { u32 asid, u64 va, u64 size); int (*send_heartbeat)(struct hl_device *hdev); int (*debug_coresight)(struct hl_device *hdev, void *data); - bool (*is_device_idle)(struct hl_device *hdev, struct seq_file *s); + bool (*is_device_idle)(struct hl_device *hdev, u32 *mask, + struct seq_file *s); int (*soft_reset_late_init)(struct hl_device *hdev); void (*hw_queues_lock)(struct hl_device *hdev); void (*hw_queues_unlock)(struct hl_device *hdev); diff --git a/drivers/misc/habanalabs/habanalabs_ioctl.c b/drivers/misc/habanalabs/habanalabs_ioctl.c index b04585af27ad..07127576b3e8 100644 --- a/drivers/misc/habanalabs/habanalabs_ioctl.c +++ b/drivers/misc/habanalabs/habanalabs_ioctl.c @@ -119,7 +119,8 @@ static int hw_idle(struct hl_device *hdev, struct hl_info_args *args) if ((!max_size) || (!out)) return -EINVAL; - hw_idle.is_idle = hdev->asic_funcs->is_device_idle(hdev, NULL); + hw_idle.is_idle = hdev->asic_funcs->is_device_idle(hdev, + &hw_idle.busy_engines_mask, NULL); return copy_to_user(out, &hw_idle, min((size_t) max_size, sizeof(hw_idle))) ? -EFAULT : 0; diff --git a/include/uapi/misc/habanalabs.h b/include/uapi/misc/habanalabs.h index 204ab9b4ae67..3956c226ca35 100644 --- a/include/uapi/misc/habanalabs.h +++ b/include/uapi/misc/habanalabs.h @@ -45,6 +45,30 @@ enum goya_queue_id { GOYA_QUEUE_ID_SIZE }; +/* + * Engine Numbering + * + * Used in the "busy_engines_mask" field in `struct hl_info_hw_idle' + */ + +enum goya_engine_id { + GOYA_ENGINE_ID_DMA_0 = 0, + GOYA_ENGINE_ID_DMA_1, + GOYA_ENGINE_ID_DMA_2, + GOYA_ENGINE_ID_DMA_3, + GOYA_ENGINE_ID_DMA_4, + GOYA_ENGINE_ID_MME_0, + GOYA_ENGINE_ID_TPC_0, + GOYA_ENGINE_ID_TPC_1, + GOYA_ENGINE_ID_TPC_2, + GOYA_ENGINE_ID_TPC_3, + GOYA_ENGINE_ID_TPC_4, + GOYA_ENGINE_ID_TPC_5, + GOYA_ENGINE_ID_TPC_6, + GOYA_ENGINE_ID_TPC_7, + GOYA_ENGINE_ID_SIZE +}; + enum hl_device_status { HL_DEVICE_STATUS_OPERATIONAL, HL_DEVICE_STATUS_IN_RESET, @@ -86,7 +110,11 @@ struct hl_info_dram_usage { struct hl_info_hw_idle { __u32 is_idle; - __u32 pad; + /* + * Bitmask of busy engines. + * Bits definition is according to `enum _enging_id'. + */ + __u32 busy_engines_mask; }; struct hl_info_device_status { -- cgit v1.2.3