From ee9bfe5eb9de9aafcc76d3e89534ca6d3bbef85f Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 2 Oct 2019 10:53:09 +0200 Subject: [PATCH 01/16] clk: samsung: exynos5433: Fix error paths Add checking the value returned by samsung_clk_alloc_reg_dump() and devm_kcalloc(). While fixing this, also release all gathered clocks. Signed-off-by: Marek Szyprowski Reviewed-by: Krzysztof Kozlowski Acked-by: Chanwoo Choi Change-Id: I08e35e458e51f07e4c05c4101ffb4b86d187aded --- drivers/clk/samsung/clk-exynos5433.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 32ef8d6..01ead7e 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -5675,6 +5675,8 @@ static int __init exynos5433_cmu_probe(struct platform_device *pdev) data->clk_save = samsung_clk_alloc_reg_dump(info->clk_regs, info->nr_clk_regs); + if (!data->clk_save) + return -ENOMEM; data->nr_clk_save = info->nr_clk_regs; data->clk_suspend = info->suspend_regs; data->nr_clk_suspend = info->nr_suspend_regs; @@ -5683,12 +5685,19 @@ static int __init exynos5433_cmu_probe(struct platform_device *pdev) if (data->nr_pclks > 0) { data->pclks = devm_kcalloc(dev, sizeof(struct clk *), data->nr_pclks, GFP_KERNEL); - + if (!data->pclks) { + kfree(data->clk_save); + return -ENOMEM; + } for (i = 0; i < data->nr_pclks; i++) { struct clk *clk = of_clk_get(dev->of_node, i); - if (IS_ERR(clk)) + if (IS_ERR(clk)) { + kfree(data->clk_save); + while (--i >= 0) + clk_put(data->pclks[i]); return PTR_ERR(clk); + } data->pclks[i] = clk; } } -- 2.7.4 From 184bbf7f5c028617521e1cb3ed9b7fe40527298a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Thu, 26 Apr 2018 13:51:33 +0200 Subject: [PATCH 02/16] thermal: exynos: remove trip reporting to user-space Remove trip reporting to user-space - I'm not aware of any user-space program which relies on it and there is a thermal user-space governor which does it in proper way nowadays. Signed-off-by: Bartlomiej Zolnierkiewicz Reviewed-by: Daniel Lezcano Signed-off-by: Eduardo Valentin [sw0312.kim: apply mainline commit b43e3cfe232a to remove unnecessary overhead uevent] Signed-off-by: Seung-Woo Kim Change-Id: I618b1c0c2285f823ecad527b76d38153068a6d32 --- drivers/thermal/samsung/exynos_tmu.c | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index d60069b..0918cf2 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -215,33 +215,6 @@ struct exynos_tmu_data { void (*tmu_clear_irqs)(struct exynos_tmu_data *data); }; -static void exynos_report_trigger(struct exynos_tmu_data *p) -{ - char data[10], *envp[] = { data, NULL }; - struct thermal_zone_device *tz = p->tzd; - int temp; - unsigned int i; - - if (!tz) { - pr_err("No thermal zone device defined\n"); - return; - } - - thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED); - - mutex_lock(&tz->lock); - /* Find the level for which trip happened */ - for (i = 0; i < of_thermal_get_ntrips(tz); i++) { - tz->ops->get_trip_temp(tz, i, &temp); - if (tz->last_temperature < temp) - break; - } - - snprintf(data, sizeof(data), "%u", i); - kobject_uevent_env(&tz->device.kobj, KOBJ_CHANGE, envp); - mutex_unlock(&tz->lock); -} - /* * TMU treats temperature as a mapped temperature code. * The temperature is converted differently depending on the calibration type. @@ -1042,7 +1015,8 @@ static void exynos_tmu_work(struct work_struct *work) if (!IS_ERR(data->clk_sec)) clk_disable(data->clk_sec); - exynos_report_trigger(data); + thermal_zone_device_update(data->tzd, THERMAL_EVENT_UNSPECIFIED); + mutex_lock(&data->lock); clk_enable(data->clk); -- 2.7.4 From 9137facd97fc5c91c16e12397e7ca52a42b1fa79 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 31 Oct 2019 11:20:26 +0900 Subject: [PATCH 03/16] clk: samsung: exynos5433: add missing slab.h header After the commit ee9bfe5eb9de9a ("clk: samsung: exynos5433: Fix error paths"), missing slab.h header causes build issue for using kfree(). Add missing header as like mainline commit faac3604d05e which is upstream version of ee9bfe5eb9de9a. Change-Id: Ib47a3fe79a049fca11d6ac3f2a626156dd5696a7 Fixes: ee9bfe5eb9de9a ("clk: samsung: exynos5433: Fix error paths") Cc: Marek Szyprowski Cc: Sylwester Nawrocki Signed-off-by: Seung-Woo Kim --- drivers/clk/samsung/clk-exynos5433.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 01ead7e..dde8039 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -16,6 +16,7 @@ #include #include #include +#include #include -- 2.7.4 From 8bb97bc80e24ac66f6762b9e0212267ebaa93240 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Fri, 18 Oct 2019 07:20:52 -0300 Subject: [PATCH 04/16] media: exynos4-is: Fix recursive locking in isp_video_release() >From isp_video_release(), &isp->video_lock is held and subsequent vb2_fop_release() tries to lock vdev->lock which is same with the previous one. Replace vb2_fop_release() with _vb2_fop_release() to fix the recursive locking. Fixes: 1380f5754cb0 ("[media] videobuf2: Add missing lock held on vb2_fop_release") Signed-off-by: Seung-Woo Kim Reviewed-by: Sylwester Nawrocki Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab [sw0312.kim: cherry-pick mainline commit 704c6c80fb47 to handle exynos4-is issue] Signed-off-by: Seung-Woo Kim Change-Id: Ibbfbc33b83dc17e86d8b030c0f7f7e101d6293c7 --- drivers/media/platform/exynos4-is/fimc-isp-video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c index a920164..39340ab 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c @@ -316,7 +316,7 @@ static int isp_video_release(struct file *file) ivc->streaming = 0; } - vb2_fop_release(file); + _vb2_fop_release(file, NULL); if (v4l2_fh_is_singular_file(file)) { fimc_pipeline_call(&ivc->ve, close); -- 2.7.4 From edb919ff8e0cc48644dd179f2708663a43b6351b Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Mon, 4 Nov 2019 10:46:32 +0100 Subject: [PATCH 05/16] media: exynos4-is: fix wrong mdev and v4l2 dev order in error path When driver is built as module and probe during insmod is deferred because of sensor subdevs, there is NULL pointer deference because mdev is cleaned up and then access it from v4l2_device_unregister(). Fix the wrong mdev and v4l2 dev order in error path of probe. This fixes below null pointer deference: Unable to handle kernel NULL pointer dereference at virtual address 00000000 pgd = ca026f68 [00000000] *pgd=00000000 Internal error: Oops: 5 [#1] PREEMPT SMP ARM [...] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree) PC is at ida_free+0x7c/0x160 LR is at xas_start+0x44/0x204 [...] [] (ida_free) from [] (__media_device_unregister_entity+0x18/0xc0) [] (__media_device_unregister_entity) from [] (media_device_unregister_entity+0x2c/0x38) [] (media_device_unregister_entity) from [] (v4l2_device_release+0xd0/0x104) [] (v4l2_device_release) from [] (device_release+0x28/0x98) [] (device_release) from [] (kobject_put+0xa4/0x208) [] (kct_put) from [] (fimc_capture_subdev_unregistered+0x58/0x6c [s5p_fimc]) [] (fimc_capture_subdev_unregistered [s5p_fimc]) from [] (v4l2_device_unregister_subdev+0x6c/0xa8) [] (v4l2_device_unregister_subdev) from [] (v4l2_device_unregister+0x64/0x94) [] (v4l2_device_unregister) from [] (fimc_md_probe+0x4ec/0xaf8 [s5p_fimc]) [...] Signed-off-by: Seung-Woo Kim Reviewed-by: Sylwester Nawrocki Fixes: 9832e155f1ed ("[media] media-device: split media initialization and registration") Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab [sw0312.kim: cherry-pick mainline commit 4d741cbd58bf to handle exynos4-is issue] Signed-off-by: Seung-Woo Kim Change-Id: Ib2f757574a180145d4972b861057f090a19d5f8f --- drivers/media/platform/exynos4-is/media-dev.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index d4656d5..70a626c 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -1438,12 +1438,12 @@ static int fimc_md_probe(struct platform_device *pdev) ret = v4l2_device_register(dev, &fmd->v4l2_dev); if (ret < 0) { v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); - return ret; + goto err_md; } ret = fimc_md_get_clocks(fmd); if (ret) - goto err_md; + goto err_v4l2dev; ret = fimc_md_get_pinctrl(fmd); if (ret < 0) { @@ -1499,9 +1499,10 @@ err_clk: fimc_md_put_clocks(fmd); err_m_ent: fimc_md_unregister_entities(fmd); +err_v4l2dev: + v4l2_device_unregister(&fmd->v4l2_dev); err_md: media_device_cleanup(&fmd->media_dev); - v4l2_device_unregister(&fmd->v4l2_dev); return ret; } -- 2.7.4 From 83fc863a23621ea12de6ebb21387ba69fc1ac17c Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 5 Dec 2019 19:16:13 +0900 Subject: [PATCH 06/16] drm/exynos: add debugfs interface and gem_info node The memps requires gem_info with gem_names to analyze graphics shared memory, so this patch adds gem_info node with debugfs interface. Change-Id: I467527da85978b7a07ec638139cec02ea29b6297 Signed-off-by: YoungJun Cho Signed-off-by: Seung-Woo Kim --- drivers/gpu/drm/exynos/Makefile | 1 + drivers/gpu/drm/exynos/exynos_drm_debugfs.c | 86 +++++++++++++++++++++++++++++ drivers/gpu/drm/exynos/exynos_drm_debugfs.h | 22 ++++++++ drivers/gpu/drm/exynos/exynos_drm_drv.c | 8 +++ drivers/gpu/drm/exynos/exynos_drm_drv.h | 3 + 5 files changed, 120 insertions(+) create mode 100644 drivers/gpu/drm/exynos/exynos_drm_debugfs.c create mode 100644 drivers/gpu/drm/exynos/exynos_drm_debugfs.h diff --git a/drivers/gpu/drm/exynos/Makefile b/drivers/gpu/drm/exynos/Makefile index 3b323f1..2065e1d 100644 --- a/drivers/gpu/drm/exynos/Makefile +++ b/drivers/gpu/drm/exynos/Makefile @@ -24,5 +24,6 @@ exynosdrm-$(CONFIG_DRM_EXYNOS_ROTATOR) += exynos_drm_rotator.o exynosdrm-$(CONFIG_DRM_EXYNOS_SCALER) += exynos_drm_scaler.o exynosdrm-$(CONFIG_DRM_EXYNOS_GSC) += exynos_drm_gsc.o exynosdrm-$(CONFIG_DRM_EXYNOS_MIC) += exynos_drm_mic.o +exynosdrm-$(CONFIG_DEBUG_FS) += exynos_drm_debugfs.o obj-$(CONFIG_DRM_EXYNOS) += exynosdrm.o diff --git a/drivers/gpu/drm/exynos/exynos_drm_debugfs.c b/drivers/gpu/drm/exynos/exynos_drm_debugfs.c new file mode 100644 index 0000000..375ccab --- /dev/null +++ b/drivers/gpu/drm/exynos/exynos_drm_debugfs.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2014 Samsung Electronics Co., Ltd + * Author: YoungJun Cho + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#include + +#include + +#include "exynos_drm_drv.h" +#include "exynos_drm_gem.h" + +struct exynos_drm_debugfs_gem_info_data { + struct drm_file *filp; + struct seq_file *m; +}; + +static int exynos_drm_debugfs_gem_one_info(int id, void *ptr, void *data) +{ + struct exynos_drm_debugfs_gem_info_data *gem_info_data = + (struct exynos_drm_debugfs_gem_info_data *)data; + struct drm_file *filp = gem_info_data->filp; + struct drm_exynos_file_private *file_priv = filp->driver_priv; + struct drm_gem_object *obj = (struct drm_gem_object *)ptr; + struct exynos_drm_gem *exynos_gem = to_exynos_gem(obj); + + seq_printf(gem_info_data->m, + "%5d\t%5d\t%4d\t%4d\t%4d\t0x%08lx\t0x%x\t%4d\t%4d\t" + "%4d\t0x%p\n", + pid_nr(filp->pid), + file_priv->tgid, + id, + kref_read(&obj->refcount), + obj->handle_count, + exynos_gem->size, + exynos_gem->flags, + 0, + obj->dma_buf ? 1 : 0, + obj->import_attach ? 1 : 0, + obj); + + return 0; +} + +static int exynos_drm_debugfs_gem_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *)m->private; + struct drm_minor *minor = node->minor; + struct drm_device *drm_dev = minor->dev; + struct exynos_drm_debugfs_gem_info_data gem_info_data; + struct drm_file *filp; + + gem_info_data.m = m; + + seq_puts(m, "pid\ttgid\thandle\tref_cnt\thdl_cnt\tsize\t\tflags\t" + "pfnmap\texport\timport\tobj_addr\n"); + + mutex_lock(&drm_dev->struct_mutex); + list_for_each_entry(filp, &drm_dev->filelist, lhead) { + gem_info_data.filp = filp; + + spin_lock(&filp->table_lock); + idr_for_each(&filp->object_idr, exynos_drm_debugfs_gem_one_info, + &gem_info_data); + spin_unlock(&filp->table_lock); + } + mutex_unlock(&drm_dev->struct_mutex); + + return 0; +} + +static struct drm_info_list exynos_drm_debugfs_list[] = { + {"gem_info", exynos_drm_debugfs_gem_info, DRIVER_GEM}, +}; +#define EXYNOS_DRM_DEBUGFS_ENTRIES ARRAY_SIZE(exynos_drm_debugfs_list) + +int exynos_drm_debugfs_init(struct drm_minor *minor) +{ + return drm_debugfs_create_files(exynos_drm_debugfs_list, + EXYNOS_DRM_DEBUGFS_ENTRIES, + minor->debugfs_root, minor); +} diff --git a/drivers/gpu/drm/exynos/exynos_drm_debugfs.h b/drivers/gpu/drm/exynos/exynos_drm_debugfs.h new file mode 100644 index 0000000..5dccc79 --- /dev/null +++ b/drivers/gpu/drm/exynos/exynos_drm_debugfs.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2014 Samsung Electronics Co.Ltd + * Author: YoungJun Cho + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundationr + */ + +#ifndef _EXYNOS_DRM_DEBUGFS_H_ +#define _EXYNOS_DRM_DEBUGFS_H_ + +#if defined(CONFIG_DEBUG_FS) +extern int exynos_drm_debugfs_init(struct drm_minor *minor); +#else +static inline int exynos_drm_debugfs_init(struct drm_minor *minor) +{ + return 0; +} +#endif + +#endif /* _EXYNOS_DRM_DEBUGFS_H_ */ diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 80d12ef..8c1fc20b 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -30,6 +30,7 @@ #include "exynos_drm_vidi.h" #include "exynos_drm_g2d.h" #include "exynos_drm_iommu.h" +#include "exynos_drm_debugfs.h" #define DRIVER_NAME "exynos" #define DRIVER_DESC "Samsung SoC DRM" @@ -73,6 +74,10 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file) if (!file_priv) return -ENOMEM; +#if defined(CONFIG_DEBUG_FS) + file_priv->tgid = task_tgid_nr(current); +#endif + file->driver_priv = file_priv; ret = exynos_drm_subdrv_open(dev, file); @@ -149,6 +154,9 @@ static struct drm_driver exynos_drm_driver = { .open = exynos_drm_open, .lastclose = exynos_drm_lastclose, .postclose = exynos_drm_postclose, +#if defined(CONFIG_DEBUG_FS) + .debugfs_init = exynos_drm_debugfs_init, +#endif .gem_free_object_unlocked = exynos_drm_gem_free_object, .gem_vm_ops = &exynos_drm_gem_vm_ops, .dumb_create = exynos_drm_gem_dumb_create, diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index 309da10..1732c66 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -187,6 +187,9 @@ struct exynos_drm_g2d_private { struct drm_exynos_file_private { struct exynos_drm_g2d_private *g2d_priv; +#if defined(CONFIG_DEBUG_FS) + pid_t tgid; +#endif }; /* -- 2.7.4 From 748ba3e3a192a81ac242a80c48295b45929ffc5b Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Fri, 8 Feb 2019 23:51:05 +0100 Subject: [PATCH 07/16] Compiler Attributes: add support for __copy (gcc >= 9) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit commit c0d9782f5b6d7157635ae2fd782a4b27d55a6013 upstream. From the GCC manual: copy copy(function) The copy attribute applies the set of attributes with which function has been declared to the declaration of the function to which the attribute is applied. The attribute is designed for libraries that define aliases or function resolvers that are expected to specify the same set of attributes as their targets. The copy attribute can be used with functions, variables, or types. However, the kind of symbol to which the attribute is applied (either function or variable) must match the kind of symbol to which the argument refers. The copy attribute copies only syntactic and semantic attributes but not attributes that affect a symbol’s linkage or visibility such as alias, visibility, or weak. The deprecated attribute is also not copied. https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html The upcoming GCC 9 release extends the -Wmissing-attributes warnings (enabled by -Wall) to C and aliases: it warns when particular function attributes are missing in the aliases but not in their target, e.g.: void __cold f(void) {} void __alias("f") g(void); diagnoses: warning: 'g' specifies less restrictive attribute than its target 'f': 'cold' [-Wmissing-attributes] Using __copy(f) we can copy the __cold attribute from f to g: void __cold f(void) {} void __copy(f) __alias("f") g(void); This attribute is most useful to deal with situations where an alias is declared but we don't know the exact attributes the target has. For instance, in the kernel, the widely used module_init/exit macros define the init/cleanup_module aliases, but those cannot be marked always as __init/__exit since some modules do not have their functions marked as such. Suggested-by: Martin Sebor Reviewed-by: Nick Desaulniers Signed-off-by: Miguel Ojeda Signed-off-by: Stefan Agner Signed-off-by: Greg Kroah-Hartman [sw0312.kim: cherry-pick from stable linux-4.14.y commit b00c958ceb6c for gcc 9 build] Signed-off-by: Seung-Woo Kim Change-Id: Ie34d9679530b16ea8da7bc3ea109b546710f2b1b --- include/linux/compiler-gcc.h | 4 ++++ include/linux/compiler_types.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 4816355..6d7ead2 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -343,6 +343,10 @@ #define __designated_init __attribute__((designated_init)) #endif +#if GCC_VERSION >= 90100 +#define __copy(symbol) __attribute__((__copy__(symbol))) +#endif + #endif /* gcc version >= 40000 specific checks */ #if !defined(__noclone) diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h index 4be464a..222fcef 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -230,6 +230,10 @@ struct ftrace_likely_data { # define __latent_entropy #endif +#ifndef __copy +# define __copy(symbol) +#endif + #ifndef __randomize_layout # define __randomize_layout __designated_init #endif -- 2.7.4 From 0242840943e0631d3f6f0a07d1616768e26eabf7 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Sat, 19 Jan 2019 20:59:34 +0100 Subject: [PATCH 08/16] include/linux/module.h: copy __init/__exit attrs to init/cleanup_module commit a6e60d84989fa0e91db7f236eda40453b0e44afa upstream. The upcoming GCC 9 release extends the -Wmissing-attributes warnings (enabled by -Wall) to C and aliases: it warns when particular function attributes are missing in the aliases but not in their target. In particular, it triggers for all the init/cleanup_module aliases in the kernel (defined by the module_init/exit macros), ending up being very noisy. These aliases point to the __init/__exit functions of a module, which are defined as __cold (among other attributes). However, the aliases themselves do not have the __cold attribute. Since the compiler behaves differently when compiling a __cold function as well as when compiling paths leading to calls to __cold functions, the warning is trying to point out the possibly-forgotten attribute in the alias. In order to keep the warning enabled, we decided to silence this case. Ideally, we would mark the aliases directly as __init/__exit. However, there are currently around 132 modules in the kernel which are missing __init/__exit in their init/cleanup functions (either because they are missing, or for other reasons, e.g. the functions being called from somewhere else); and a section mismatch is a hard error. A conservative alternative was to mark the aliases as __cold only. However, since we would like to eventually enforce __init/__exit to be always marked, we chose to use the new __copy function attribute (introduced by GCC 9 as well to deal with this). With it, we copy the attributes used by the target functions into the aliases. This way, functions that were not marked as __init/__exit won't have their aliases marked either, and therefore there won't be a section mismatch. Note that the warning would go away marking either the extern declaration, the definition, or both. However, we only mark the definition of the alias, since we do not want callers (which only see the declaration) to be compiled as if the function was __cold (and therefore the paths leading to those calls would be assumed to be unlikely). Link: https://lore.kernel.org/lkml/20190123173707.GA16603@gmail.com/ Link: https://lore.kernel.org/lkml/20190206175627.GA20399@gmail.com/ Suggested-by: Martin Sebor Acked-by: Jessica Yu Signed-off-by: Miguel Ojeda Signed-off-by: Stefan Agner Signed-off-by: Greg Kroah-Hartman [sw0312.kim: cherry-pick from stable linux-4.14.y commit 08aaa79ba25b for gcc 9 build] Signed-off-by: Seung-Woo Kim Change-Id: If5f04446d064b3daf6532852d5193a47fffb0d30 --- include/linux/module.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/linux/module.h b/include/linux/module.h index a9d546c..c290de0 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -128,13 +128,13 @@ extern void cleanup_module(void); #define module_init(initfn) \ static inline initcall_t __maybe_unused __inittest(void) \ { return initfn; } \ - int init_module(void) __attribute__((alias(#initfn))); + int init_module(void) __copy(initfn) __attribute__((alias(#initfn))); /* This is only required if you want to be unloadable. */ #define module_exit(exitfn) \ static inline exitcall_t __maybe_unused __exittest(void) \ { return exitfn; } \ - void cleanup_module(void) __attribute__((alias(#exitfn))); + void cleanup_module(void) __copy(exitfn) __attribute__((alias(#exitfn))); #endif -- 2.7.4 From 0d67e5e24aced6ce734368aeb6e9a18d133ea44f Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 1 May 2019 11:05:41 -0700 Subject: [PATCH 09/16] gcc-9: silence 'address-of-packed-member' warning commit 6f303d60534c46aa1a239f29c321f95c83dda748 upstream. We already did this for clang, but now gcc has that warning too. Yes, yes, the address may be unaligned. And that's kind of the point. Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman [sw0312.kim: cherry-pick from stable linux-4.14.y commit 8e69458509d2 for gcc 9 build] Signed-off-by: Seung-Woo Kim Change-Id: Iec954dfa4fd8bf3ea7e1db3da2e421b8f58bbb32 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3b10c8b..5bc7ede 100644 --- a/Makefile +++ b/Makefile @@ -650,6 +650,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,) KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation) KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow) KBUILD_CFLAGS += $(call cc-disable-warning, int-in-bool-context) +KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) KBUILD_CFLAGS += $(call cc-disable-warning, attribute-alias) ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE @@ -717,7 +718,6 @@ ifeq ($(cc-name),clang) KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,) KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier) KBUILD_CFLAGS += $(call cc-disable-warning, gnu) -KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) # Quiet clang warning: comparison of unsigned expression < 0 is always false KBUILD_CFLAGS += $(call cc-disable-warning, tautological-compare) # CLANG uses a _MergedGlobals as optimization, but this breaks modpost, as the -- 2.7.4 From da0a9eb6165017ebe95499cf3d96be6be16066cb Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 29 Mar 2018 00:06:10 +0200 Subject: [PATCH 10/16] ath10k: avoid possible string overflow commit 6707ba0105a2d350710bc0a537a98f49eb4b895d upstream. The way that 'strncat' is used here raised a warning in gcc-8: drivers/net/wireless/ath/ath10k/wmi.c: In function 'ath10k_wmi_tpc_stats_final_disp_tables': drivers/net/wireless/ath/ath10k/wmi.c:4649:4: error: 'strncat' output truncated before terminating nul copying as many bytes from a string as its length [-Werror=stringop-truncation] Effectively, this is simply a strcat() but the use of strncat() suggests some form of overflow check. Regardless of whether this might actually overflow, using strlcat() instead of strncat() avoids the warning and makes the code more robust. Fixes: bc64d05220f3 ("ath10k: debugfs support to get final TPC stats for 10.4 variants") Signed-off-by: Arnd Bergmann Signed-off-by: Kalle Valo Signed-off-by: Greg Kroah-Hartman [sw0312.kim: cherry-pick from stable linux-4.14.y commit 0cc17a7a3203 for gcc 9 build] Signed-off-by: Seung-Woo Kim Change-Id: I9e104bff8046c7ffa7f50b047dc4cd2e9fdb83e6 --- drivers/net/wireless/ath/ath10k/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 8cb4785..ab8eb9c 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -4309,7 +4309,7 @@ static void ath10k_tpc_config_disp_tables(struct ath10k *ar, rate_code[i], type); snprintf(buff, sizeof(buff), "%8d ", tpc[j]); - strncat(tpc_value, buff, strlen(buff)); + strlcat(tpc_value, buff, sizeof(tpc_value)); } tpc_stats->tpc_table[type].pream_idx[i] = pream_idx; tpc_stats->tpc_table[type].rate_code[i] = rate_code[i]; -- 2.7.4 From b7b6d124af81ef1a5bd49fee80264108be9c4e71 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Thu, 23 May 2019 14:45:35 +0200 Subject: [PATCH 11/16] tracing: Silence GCC 9 array bounds warning commit 0c97bf863efce63d6ab7971dad811601e6171d2f upstream. Starting with GCC 9, -Warray-bounds detects cases when memset is called starting on a member of a struct but the size to be cleared ends up writing over further members. Such a call happens in the trace code to clear, at once, all members after and including `seq` on struct trace_iterator: In function 'memset', inlined from 'ftrace_dump' at kernel/trace/trace.c:8914:3: ./include/linux/string.h:344:9: warning: '__builtin_memset' offset [8505, 8560] from the object at 'iter' is out of the bounds of referenced subobject 'seq' with type 'struct trace_seq' at offset 4368 [-Warray-bounds] 344 | return __builtin_memset(p, c, size); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ In order to avoid GCC complaining about it, we compute the address ourselves by adding the offsetof distance instead of referring directly to the member. Since there are two places doing this clear (trace.c and trace_kdb.c), take the chance to move the workaround into a single place in the internal header. Link: http://lkml.kernel.org/r/20190523124535.GA12931@gmail.com Signed-off-by: Miguel Ojeda [ Removed unnecessary parenthesis around "iter" ] Signed-off-by: Steven Rostedt (VMware) Signed-off-by: Greg Kroah-Hartman [sw0312.kim: cherry-pick from stable linux-4.14.y commit 50bbae7dad92 for gcc 9 build] Signed-off-by: Seung-Woo Kim Change-Id: I9f9b22003b8d13267b0f0b1d2b00f66bdd9af5f6 --- kernel/trace/trace.c | 6 +----- kernel/trace/trace.h | 18 ++++++++++++++++++ kernel/trace/trace_kdb.c | 6 +----- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index e9cbb96..a3e1828 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -8239,12 +8239,8 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) cnt++; - /* reset all but tr, trace, and overruns */ - memset(&iter.seq, 0, - sizeof(struct trace_iterator) - - offsetof(struct trace_iterator, seq)); + trace_iterator_reset(&iter); iter.iter_flags |= TRACE_FILE_LAT_FMT; - iter.pos = -1; if (trace_find_next_entry_inc(&iter) != NULL) { int ret; diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 851cd16..53a917d 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -1820,4 +1820,22 @@ static inline int tracing_alloc_snapshot_instance(struct trace_array *tr) extern struct trace_iterator *tracepoint_print_iter; +/* + * Reset the state of the trace_iterator so that it can read consumed data. + * Normally, the trace_iterator is used for reading the data when it is not + * consumed, and must retain state. + */ +static __always_inline void trace_iterator_reset(struct trace_iterator *iter) +{ + const size_t offset = offsetof(struct trace_iterator, seq); + + /* + * Keep gcc from complaining about overwriting more than just one + * member in the structure. + */ + memset((char *)iter + offset, 0, sizeof(struct trace_iterator) - offset); + + iter->pos = -1; +} + #endif /* _LINUX_KERNEL_TRACE_H */ diff --git a/kernel/trace/trace_kdb.c b/kernel/trace/trace_kdb.c index d953c16..9f2b85b 100644 --- a/kernel/trace/trace_kdb.c +++ b/kernel/trace/trace_kdb.c @@ -41,12 +41,8 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file) kdb_printf("Dumping ftrace buffer:\n"); - /* reset all but tr, trace, and overruns */ - memset(&iter.seq, 0, - sizeof(struct trace_iterator) - - offsetof(struct trace_iterator, seq)); + trace_iterator_reset(&iter); iter.iter_flags |= TRACE_FILE_LAT_FMT; - iter.pos = -1; if (cpu_file == RING_BUFFER_ALL_CPUS) { for_each_tracing_cpu(cpu) { -- 2.7.4 From ab6f052c691a40cd8facc21467a8ecd1f4d1b986 Mon Sep 17 00:00:00 2001 From: Dave Martin Date: Thu, 6 Jun 2019 11:33:43 +0100 Subject: [PATCH 12/16] arm64: Silence gcc warnings about arch ABI drift Since GCC 9, the compiler warns about evolution of the platform-specific ABI, in particular relating for the marshaling of certain structures involving bitfields. The kernel is a standalone binary, and of course nobody would be so stupid as to expose structs containing bitfields as function arguments in ABI. (Passing a pointer to such a struct, however inadvisable, should be unaffected by this change. perf and various drivers rely on that.) So these warnings do more harm than good: turn them off. We may miss warnings about future ABI drift, but that's too bad. Future ABI breaks of this class will have to be debugged and fixed the traditional way unless the compiler evolves finer-grained diagnostics. Signed-off-by: Dave Martin Signed-off-by: Will Deacon [sw0312.kim: backport mainline commit ebcc5928c5d9 for gcc 9 build] Signed-off-by: Seung-Woo Kim Change-Id: I42f221ba946ed70fe770eb3d501a48e837f0377d --- arch/arm64/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 0c5f70e..80b8f0b 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -52,6 +52,7 @@ endif KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr) $(brokengasinst) KBUILD_CFLAGS += -fno-asynchronous-unwind-tables KBUILD_CFLAGS += $(call cc-option, -mpc-relative-literal-loads) +KBUILD_CFLAGS += -Wno-psabi KBUILD_AFLAGS += $(lseinstr) $(brokengasinst) KBUILD_CFLAGS += $(call cc-option,-mabi=lp64) -- 2.7.4 From 91e410bc7be1e5458ac5c68e3ae6294f7a80f2eb Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Tue, 11 Jun 2019 10:19:32 -0700 Subject: [PATCH 13/16] arm64: Don't unconditionally add -Wno-psabi to KBUILD_CFLAGS MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit This is a GCC only option, which warns about ABI changes within GCC, so unconditionally adding it breaks Clang with tons of: warning: unknown warning option '-Wno-psabi' [-Wunknown-warning-option] and link time failures: ld.lld: error: undefined symbol: __efistub___stack_chk_guard >>> referenced by arm-stub.c:73 (/home/nathan/cbl/linux/drivers/firmware/efi/libstub/arm-stub.c:73) >>> arm-stub.stub.o:(__efistub_install_memreserve_table) in archive ./drivers/firmware/efi/libstub/lib.a These failures come from the lack of -fno-stack-protector, which is added via cc-option in drivers/firmware/efi/libstub/Makefile. When an unknown flag is added to KBUILD_CFLAGS, clang will noisily warn that it is ignoring the option like above, unlike gcc, who will just error. $ echo "int main() { return 0; }" > tmp.c $ clang -Wno-psabi tmp.c; echo $? warning: unknown warning option '-Wno-psabi' [-Wunknown-warning-option] 1 warning generated. 0 $ gcc -Wsometimes-uninitialized tmp.c; echo $? gcc: error: unrecognized command line option ‘-Wsometimes-uninitialized’; did you mean ‘-Wmaybe-uninitialized’? 1 For cc-option to work properly with clang and behave like gcc, -Werror is needed, which was done in commit c3f0d0bc5b01 ("kbuild, LLVMLinux: Add -Werror to cc-option to support clang"). $ clang -Werror -Wno-psabi tmp.c; echo $? error: unknown warning option '-Wno-psabi' [-Werror,-Wunknown-warning-option] 1 As a consequence of this, when an unknown flag is unconditionally added to KBUILD_CFLAGS, it will cause cc-option to always fail and those flags will never get added: $ clang -Werror -Wno-psabi -fno-stack-protector tmp.c; echo $? error: unknown warning option '-Wno-psabi' [-Werror,-Wunknown-warning-option] 1 This can be seen when compiling the whole kernel as some warnings that are normally disabled (see below) show up. The full list of flags missing from drivers/firmware/efi/libstub are the following (gathered from diffing .arm64-stub.o.cmd): -fno-delete-null-pointer-checks -Wno-address-of-packed-member -Wframe-larger-than=2048 -Wno-unused-const-variable -fno-strict-overflow -fno-merge-all-constants -fno-stack-check -Werror=date-time -Werror=incompatible-pointer-types -ffreestanding -fno-stack-protector Use cc-disable-warning so that it gets disabled for GCC and does nothing for Clang. Fixes: ebcc5928c5d9 ("arm64: Silence gcc warnings about arch ABI drift") Link: https://github.com/ClangBuiltLinux/linux/issues/511 Reported-by: Qian Cai Acked-by: Dave Martin Reviewed-by: Nick Desaulniers Signed-off-by: Nathan Chancellor Signed-off-by: Will Deacon [sw0312.kim: backport mainline commit fa63da2ab046 for gcc 9 build] Signed-off-by: Seung-Woo Kim Change-Id: I0fb6fb81abe69ba8c1d4228608f361a3a6ce3800 --- arch/arm64/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile index 80b8f0b..56a6199 100644 --- a/arch/arm64/Makefile +++ b/arch/arm64/Makefile @@ -52,7 +52,7 @@ endif KBUILD_CFLAGS += -mgeneral-regs-only $(lseinstr) $(brokengasinst) KBUILD_CFLAGS += -fno-asynchronous-unwind-tables KBUILD_CFLAGS += $(call cc-option, -mpc-relative-literal-loads) -KBUILD_CFLAGS += -Wno-psabi +KBUILD_CFLAGS += $(call cc-disable-warning, psabi) KBUILD_AFLAGS += $(lseinstr) $(brokengasinst) KBUILD_CFLAGS += $(call cc-option,-mabi=lp64) -- 2.7.4 From db92f438ea5fcdb580c0190a624cd833208a7eae Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Mon, 25 May 2020 17:21:13 +0900 Subject: [PATCH 14/16] packaging: Add _wrong_version_format_terminate_build macro Newer version of rpmbuild rejects double dash, "-", in version. To support the style, add _worng_version_format_terminate_build as 0 for docker gbs build. Change-Id: If15c81cea640ff63d3443207a8963b76412201a5 Reference: https://github.com/rpm-software-management/rpm/commit/5e94633660d0e2b97 Signed-off-by: Seung-Woo Kim --- packaging/linux-exynos-tm2.spec | 3 +++ packaging/odroid-linux-kernel.spec | 3 +++ 2 files changed, 6 insertions(+) diff --git a/packaging/linux-exynos-tm2.spec b/packaging/linux-exynos-tm2.spec index a6d33bf..b5d07e6 100644 --- a/packaging/linux-exynos-tm2.spec +++ b/packaging/linux-exynos-tm2.spec @@ -1,3 +1,6 @@ +# Ignore double dash in version for rpmbuild +%define _wrong_version_format_terminate_build 0 + %define config_name tizen_tm2_defconfig %define buildarch arm64 %define target_board tm2 diff --git a/packaging/odroid-linux-kernel.spec b/packaging/odroid-linux-kernel.spec index bc5dc74..07a2cd0 100644 --- a/packaging/odroid-linux-kernel.spec +++ b/packaging/odroid-linux-kernel.spec @@ -1,3 +1,6 @@ +# Ignore double dash in version for rpmbuild +%define _wrong_version_format_terminate_build 0 + %define config_name tizen_odroid_defconfig %define buildarch arm %define target_board odroidxu3 -- 2.7.4 From 7d599670f9864fc54e953f1a9ac3a0767968bfca Mon Sep 17 00:00:00 2001 From: Roman Gushchin Date: Fri, 17 Nov 2017 15:26:45 -0800 Subject: [PATCH 15/16] proc, coredump: add CoreDumping flag to /proc/pid/status Right now there is no convenient way to check if a process is being coredumped at the moment. It might be necessary to recognize such state to prevent killing the process and getting a broken coredump. Writing a large core might take significant time, and the process is unresponsive during it, so it might be killed by timeout, if another process is monitoring and killing/restarting hanging tasks. We're getting a significant number of corrupted coredump files on machines in our fleet, just because processes are being killed by timeout in the middle of the core writing process. We do have a process health check, and some agent is responsible for restarting processes which are not responding for health check requests. Writing a large coredump to the disk can easily exceed the reasonable timeout (especially on an overloaded machine). This flag will allow the agent to distinguish processes which are being coredumped, extend the timeout for them, and let them produce a full coredump file. To provide an ability to detect if a process is in the state of being coredumped, we can expose a boolean CoreDumping flag in /proc/pid/status. Example: $ cat core.sh #!/bin/sh echo "|/usr/bin/sleep 10" > /proc/sys/kernel/core_pattern sleep 1000 & PID=$! cat /proc/$PID/status | grep CoreDumping kill -ABRT $PID sleep 1 cat /proc/$PID/status | grep CoreDumping $ ./core.sh CoreDumping: 0 CoreDumping: 1 [guro@fb.com: document CoreDumping flag in /proc//status] Link: http://lkml.kernel.org/r/20170928135357.GA8470@castle.DHCP.thefacebook.com Link: http://lkml.kernel.org/r/20170920230634.31572-1-guro@fb.com Signed-off-by: Roman Gushchin Cc: Alexander Viro Cc: Ingo Molnar Cc: Konstantin Khlebnikov Cc: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds [k.lewandowsk: backport mainline commit c643401218 for userspace process managers (eg. resourced) to be able to avoid killing dead processes, breaking crash reports] Signed-off-by: Karol Lewandowski Change-Id: I7a7588752a24392d16963a7b3f78764d9bce1e2b --- Documentation/filesystems/proc.txt | 3 +++ fs/proc/array.c | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 4cee34c..41caceb 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -181,6 +181,7 @@ read the file /proc/PID/status: VmPTE: 20 kb VmSwap: 0 kB HugetlbPages: 0 kB + CoreDumping: 0 Threads: 1 SigQ: 0/28578 SigPnd: 0000000000000000 @@ -254,6 +255,8 @@ Table 1-2: Contents of the status files (as of 4.8) VmSwap amount of swap used by anonymous private data (shmem swap usage is not included) HugetlbPages size of hugetlb memory portions + CoreDumping process's memory is currently being dumped + (killing the process may lead to a corrupted core) Threads number of threads SigQ number of signals queued/max. number for queue SigPnd bitmap of pending signals for the thread diff --git a/fs/proc/array.c b/fs/proc/array.c index 4ac811e..95691ad 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -391,6 +391,11 @@ static void task_cpus_allowed(struct seq_file *m, struct task_struct *task) cpumask_pr_args(&task->cpus_allowed)); } +static inline void task_core_dumping(struct seq_file *m, struct mm_struct *mm) +{ + seq_printf(m, "CoreDumping:\t%d\n", !!mm->core_state); +} + int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, struct pid *pid, struct task_struct *task) { @@ -401,6 +406,7 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, if (mm) { task_mem(m, mm); + task_core_dumping(m, mm); mmput(mm); } task_sig(m, task); -- 2.7.4 From 865f7cc8cdb26f1572d36058a5a00e1a6e253389 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 11 Jun 2020 11:39:01 +0900 Subject: [PATCH 16/16] leds: add support for MAX77843 led control driver Maxim max77843 has 4-channel led controller on max77843 multi function device. Add max77843 led driver for the device. Note: this ports below commits in 4.1 kernel in tizen_5.0 branch: commit dd11bc28be60 ("mfd: max77843: Add led of_compatible in mfd_cell") commit ab013630b285 ("leds: add support for MAX77843 led control driver") Change-Id: I48c778addba06d1070284e4fc6b8e3ca500c089a Signed-off-by: Jaewon Kim Signed-off-by: Seung-Woo Kim --- drivers/leds/Kconfig | 7 + drivers/leds/Makefile | 1 + drivers/leds/leds-max77843.c | 254 +++++++++++++++++++++++++++++++++++ drivers/mfd/max77843.c | 3 + include/linux/mfd/max77843-private.h | 33 +++++ 5 files changed, 298 insertions(+) create mode 100644 drivers/leds/leds-max77843.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 52ea34e..2e08f83 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -569,6 +569,13 @@ config LEDS_MAX77693 multifunction device. It has build in control for two leds in flash and torch mode. +config LEDS_MAX77843 + tristate "LED support for MAX77843 PMIC" + depends on LEDS_CLASS && MFD_MAX77843 + help + This option enables support for on-chip 4-channel LED driver + on MAXIM MAX77843 PMIC. + config LEDS_MAX8997 tristate "LED support for MAX8997 PMIC" depends on LEDS_CLASS && MFD_MAX8997 diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 3598045..a13ef06 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_LEDS_NS2) += leds-ns2.o obj-$(CONFIG_LEDS_NETXBIG) += leds-netxbig.o obj-$(CONFIG_LEDS_ASIC3) += leds-asic3.o obj-$(CONFIG_LEDS_MAX77693) += leds-max77693.o +obj-$(CONFIG_LEDS_MAX77843) += leds-max77843.o obj-$(CONFIG_LEDS_MAX8997) += leds-max8997.o obj-$(CONFIG_LEDS_LM355x) += leds-lm355x.o obj-$(CONFIG_LEDS_BLINKM) += leds-blinkm.o diff --git a/drivers/leds/leds-max77843.c b/drivers/leds/leds-max77843.c new file mode 100644 index 0000000..4637cd4 --- /dev/null +++ b/drivers/leds/leds-max77843.c @@ -0,0 +1,254 @@ +/* + * max77843.c - LED class driver for Maxim MAX77843 + * + * Copyright (C) 2015 Samsung Electronics + * Author: Jaewon Kim + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX77843_MAX_BRIGHTNESS 0xFF + +enum max77843_leds { + MAX77843_LED0 = 0, + MAX77843_LED1, + MAX77843_LED2, + MAX77843_LED3, + + MAX77843_LED_NUM, +}; + +struct max77843_led_info { + struct led_classdev cdev; + const char *color; + u8 channel; + bool active; +}; + +struct max77843_led { + struct max77693_dev *max77843; + struct regmap *regmap_led; + struct device *dev; + struct max77843_led_info led_info[4]; +}; + +static struct max77843_led *cdev_to_led(struct led_classdev *cdev) +{ + struct max77843_led_info *led_info = container_of(cdev, + struct max77843_led_info, cdev); + + return container_of(led_info, struct max77843_led, + led_info[led_info->channel]); +} + +static void max77843_led_brightness_set(struct led_classdev *led_cdev, + enum led_brightness value) +{ + + struct max77843_led *led = cdev_to_led(led_cdev); + struct max77843_led_info *led_info = container_of(led_cdev, + struct max77843_led_info, cdev); + u8 channel = led_info->channel; + + switch (channel) { + case MAX77843_LED0: + regmap_write(led->regmap_led, + MAX77843_LED_REG_LED0BRT, value); + if (value == 0) + regmap_update_bits(led->regmap_led, + MAX77843_LED_REG_LEDEN, + MAX77843_LED_LED0EN_MASK, + OFF << LED0EN_SHIFT); + else + regmap_update_bits(led->regmap_led, + MAX77843_LED_REG_LEDEN, + MAX77843_LED_LED0EN_MASK, + CONSTANT << LED0EN_SHIFT); + + break; + case MAX77843_LED1: + regmap_write(led->regmap_led, + MAX77843_LED_REG_LED1BRT, value); + if (value == 0) + regmap_update_bits(led->regmap_led, + MAX77843_LED_REG_LEDEN, + MAX77843_LED_LED1EN_MASK, + OFF << LED1EN_SHIFT); + else + regmap_update_bits(led->regmap_led, + MAX77843_LED_REG_LEDEN, + MAX77843_LED_LED1EN_MASK, + CONSTANT << LED1EN_SHIFT); + break; + case MAX77843_LED2: + regmap_write(led->regmap_led, + MAX77843_LED_REG_LED2BRT, value); + if (value == 0) + regmap_update_bits(led->regmap_led, + MAX77843_LED_REG_LEDEN, + MAX77843_LED_LED2EN_MASK, + OFF << LED2EN_SHIFT); + else + regmap_update_bits(led->regmap_led, + MAX77843_LED_REG_LEDEN, + MAX77843_LED_LED2EN_MASK, + CONSTANT << LED2EN_SHIFT); + break; + case MAX77843_LED3: + regmap_write(led->regmap_led, + MAX77843_LED_REG_LED3BRT, value); + if (value == 0) + regmap_update_bits(led->regmap_led, + MAX77843_LED_REG_LEDEN, + MAX77843_LED_LED3EN_MASK, + OFF << LED3EN_SHIFT); + else + regmap_update_bits(led->regmap_led, + MAX77843_LED_REG_LEDEN, + MAX77843_LED_LED3EN_MASK, + CONSTANT << LED3EN_SHIFT); + break; + } +} + +static ssize_t max77843_led_show_color(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *cdev = dev_get_drvdata(dev); + struct max77843_led_info *led_info = container_of(cdev, + struct max77843_led_info, cdev); + + return sprintf(buf, "%s\n", led_info->color); +} + +static DEVICE_ATTR(color, 0644, max77843_led_show_color, NULL); + +static struct attribute *max77843_attrs[] = { + &dev_attr_color.attr, + NULL +}; +ATTRIBUTE_GROUPS(max77843); + +static int max77843_led_initialize(struct max77843_led_info *led_info, + const char *name, const char *color, enum max77843_leds id) +{ + struct led_classdev *cdev = &led_info->cdev; + struct max77843_led *led; + int ret; + + led_info->channel = id; + led_info->active = true; + led_info->color = color; + led = cdev_to_led(cdev); + + cdev->name = name; + cdev->brightness = 0; + cdev->max_brightness = MAX77843_MAX_BRIGHTNESS; + cdev->brightness_set = max77843_led_brightness_set; + cdev->groups = max77843_groups; + + ret = led_classdev_register(led->dev, cdev); + if (ret < 0) + return ret; + + return 0; +} + +static int max77843_led_probe(struct platform_device *pdev) +{ + struct max77693_dev *max77843 = dev_get_drvdata(pdev->dev.parent); + struct max77843_led *led; + struct device_node *child; + int i, ret; + + led = devm_kzalloc(&pdev->dev, sizeof(*led), GFP_KERNEL); + if (!led) + return -ENOMEM; + + led->max77843 = max77843; + led->regmap_led = max77843->regmap; + led->dev = &pdev->dev; + + for_each_available_child_of_node(pdev->dev.of_node, child) { + int channel; + const char *label; + const char *color; + + ret = of_property_read_u32(child, "channel", &channel); + if (ret) { + dev_err(&pdev->dev, "failed to parse channel\n"); + of_node_put(child); + goto err_init; + } + + ret = of_property_read_string(child, "label", &label); + if (ret) { + dev_err(&pdev->dev, "failed to parse lable\n"); + of_node_put(child); + goto err_init; + } + + ret = of_property_read_string(child, "color", &color); + if (ret) { + dev_err(&pdev->dev, "failed to parse color\n"); + of_node_put(child); + goto err_init; + } + + ret = max77843_led_initialize(&led->led_info[channel], + label, color, channel); + if (ret < 0) { + dev_err(&pdev->dev, "failed to initialize leds\n"); + goto err_init; + } + } + + platform_set_drvdata(pdev, led); + + return 0; + +err_init: + for (i = 0; i < MAX77843_LED_NUM; i++) + if (led->led_info[i].active) + led_classdev_unregister(&led->led_info[i].cdev); + + return ret; +} + +static int max77843_led_remove(struct platform_device *pdev) +{ + struct max77843_led *led = platform_get_drvdata(pdev); + int i; + + for (i = 0; i < MAX77843_LED_NUM; i++) + if (led->led_info[i].active) + led_classdev_unregister(&led->led_info[i].cdev); + + return 0; +} + +static struct platform_driver max77843_led_driver = { + .driver = { + .name = "max77843-led", + }, + .probe = max77843_led_probe, + .remove = max77843_led_remove, +}; + +module_platform_driver(max77843_led_driver); + +MODULE_AUTHOR("Jaewon Kim "); +MODULE_DESCRIPTION("Maxim MAX77843 LED driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/mfd/max77843.c b/drivers/mfd/max77843.c index dc5caea..21c61d8 100644 --- a/drivers/mfd/max77843.c +++ b/drivers/mfd/max77843.c @@ -38,6 +38,9 @@ static const struct mfd_cell max77843_devs[] = { }, { .name = "max77843-haptic", .of_compatible = "maxim,max77843-haptic", + }, { + .name = "max77843-led", + .of_compatible = "maxim,max77843-led", }, }; diff --git a/include/linux/mfd/max77843-private.h b/include/linux/mfd/max77843-private.h index b8908bf..4f7934d 100644 --- a/include/linux/mfd/max77843-private.h +++ b/include/linux/mfd/max77843-private.h @@ -202,6 +202,39 @@ enum max77843_irq_muic { #define MAX77843_MCONFIG_MEN_MASK BIT(MCONFIG_MEN_SHIFT) #define MAX77843_MCONFIG_PDIV_MASK (0x3 << MCONFIG_PDIV_SHIFT) +#define LED0EN_SHIFT 0 +#define LED1EN_SHIFT 2 +#define LED2EN_SHIFT 4 +#define LED3EN_SHIFT 6 + +#define MAX77843_LED_LED0EN_MASK (0x3 << LED0EN_SHIFT) +#define MAX77843_LED_LED1EN_MASK (0x3 << LED1EN_SHIFT) +#define MAX77843_LED_LED2EN_MASK (0x3 << LED2EN_SHIFT) +#define MAX77843_LED_LED3EN_MASK (0x3 << LED3EN_SHIFT) + +#define OFF 0x0 +#define CONSTANT 0x1 +#define BLINK 0x2 + +#define MAX77843_LED_LED0EN_CONSTANT (CONSTANT << LED0EN_SHIFT) +#define MAX77843_LED_LED1EN_CONSTANT (CONSTANT << LED1EN_SHIFT) +#define MAX77843_LED_LED2EN_CONSTANT (CONSTANT << LED2EN_SHIFT) +#define MAX77843_LED_LED3EN_CONSTANT (CONSTANT << LED3EN_SHIFT) + +/* MAX77843 LEDBLNK register */ +#define LEDTON1_SHIFT 4 +#define LEDTOFF1_SHIFT 0 + +#define MAX77843_LEDBLNK_LEDTON1_MASK (0xF << LEDTON1_SHIFT) +#define MAX77843_LEDBLNK_LEDTOFF1_MASK (0xF << LEDTOFF1_SHIFT) + +/* MAX77843 LEDRAMP register */ +#define RMPUP1_SHIFT 4 +#define RMPDN1_SHIFT 0 + +#define MAX77843_LEDRAMP_RAMPUP1_MASK (0xF << RMPUP1_SHIFT) +#define MAX77843_LEDRAMP_RAMPDN1_MASK (0xF << RMPDN1_SHIFT) + /* Max77843 charger insterrupts */ #define MAX77843_CHG_BYP_I BIT(0) #define MAX77843_CHG_BATP_I BIT(2) -- 2.7.4