From f6e61709ceb1ca9770f2120d9045089456a50b4d Mon Sep 17 00:00:00 2001 From: Sung-hun Kim Date: Thu, 13 Aug 2020 15:46:36 +0900 Subject: [PATCH 01/16] mm: LKSM: remove unnecessary debug messages In order to get scanning candidates, LKSM hooks fork and exit calls even though LKSM does not run. Previous patches include debugging messages when LKSM hooks exit calls, and it can flush old kernel logs. To handle this, this patch removes unnecessary debugging messages. Change-Id: If475a880ee931668b6bebf53322622ba2a042c89 Signed-off-by: Sung-hun Kim --- mm/lksm.c | 29 +++-------------------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/mm/lksm.c b/mm/lksm.c index e65cf12..e6a1533 100644 --- a/mm/lksm.c +++ b/mm/lksm.c @@ -1034,7 +1034,6 @@ static void lksm_region_free(struct lksm_region *region) { unsigned long flags; - ksm_debug("lets free region(%p) prev(%p)", region, region->prev); spin_lock_irqsave(&lksm_region_lock, flags); if (!region->next) { if (region->prev) { @@ -1043,12 +1042,8 @@ static void lksm_region_free(struct lksm_region *region) if (region->prev->len > SINGLE_FILTER_LEN) kfree(region->prev->filter); kfree(region->prev); - } else { - ksm_debug("prev region(%p) has ref count(%d)", - region->prev, - atomic_read(®ion->prev->refcount)); + } else region->prev->next = NULL; - } } hash_del(®ion->hnode); if (region->len > SINGLE_FILTER_LEN) @@ -1070,7 +1065,6 @@ static void lksm_region_ref_list_release(struct mm_slot *slot) { struct lksm_region_ref *ref, *next; - ksm_debug("release %p ref list", slot); list_for_each_entry_safe(ref, next, &slot->ref_list, list) { lksm_region_ref_remove(ref); } @@ -2826,7 +2820,6 @@ static void lksm_flush_removed_mm_list(void) if (!list_empty(&head->mm_list)) { list_for_each_entry_safe(slot, next, &head->mm_list, mm_list) { - ksm_debug("slot(%p) will be freed", slot); list_del(&slot->mm_list); cond_resched(); @@ -2841,8 +2834,6 @@ static void lksm_flush_removed_mm_list(void) } } - ksm_debug("slot(%p) will be freed", head); - cond_resched(); remove_trailing_rmap_items(head, &head->rmap_list); clear_bit(MMF_VM_MERGEABLE, &head->mm->flags); @@ -2873,7 +2864,6 @@ static struct mm_slot *lksm_get_unscanned_mm_slot(struct mm_slot *slot) list_for_each_entry_safe_continue(slot, next, &ksm_scan_head.scan_list, scan_list) { if (ksm_test_exit(slot->mm)) { - ksm_debug("slot:%p %p is moved to remove list", slot, slot->mm); if (lksm_test_mm_state(slot, KSM_MM_FROZEN)) atomic_dec(&ksm_scan.nr_frozen); else @@ -2985,14 +2975,12 @@ static struct vm_area_struct *lksm_find_next_vma region->len = SINGLE_FILTER_LEN; /* conflicted regions will be unfiltered */ region = &unknown_region; - ksm_debug("the region is frequently conflicted. break."); break; } if (region->len < len) { unsigned long *filter; ksm_debug("size of region(%p) is changed: %d -> %d (size: %d)", region, region->len, len, size); - ksm_debug("region-%d type: %d vma:%p", region->ino, region->type, vma); filter = kcalloc(len, sizeof(long), GFP_KERNEL); if (!filter) { ksm_err("fail to allocate memory for filter"); @@ -4072,13 +4060,10 @@ void __ksm_exit(struct mm_struct *mm) easy_to_free = 1; } else lksm_remove_mm_slot(mm_slot); - if (lksm_test_mm_state(mm_slot, KSM_MM_FROZEN)) { + if (lksm_test_mm_state(mm_slot, KSM_MM_FROZEN)) atomic_dec(&ksm_scan.nr_frozen); - ksm_debug("nr_frozen: %d", atomic_read(&ksm_scan.nr_frozen)); - } else if (!lksm_test_mm_state(mm_slot, KSM_MM_SCANNED)) { + else if (!lksm_test_mm_state(mm_slot, KSM_MM_SCANNED)) atomic_dec(&ksm_scan.nr_scannable); - ksm_debug("nr_scannable: %d", atomic_read(&ksm_scan.nr_scannable)); - } } #ifdef CONFIG_LKSM_FILTER deferring_free: @@ -5028,8 +5013,6 @@ static struct lksm_region *lksm_find_region(struct vm_area_struct *vma) if (region && type == LKSM_REGION_FILE2) { if (!region->next) { - ksm_debug("region(%p:%lu:%s)-vma(%p) doesn't have next area (file: %p)", - region, ino, region_type_str[region->type], vma, file); lksm_insert_region(®ion, ino, vma, type); BUG_ON(!region->next); } @@ -5069,17 +5052,11 @@ void lksm_remove_candidate(struct mm_struct *mm) atomic_dec(&ksm_scan.nr_frozen); else if (!lksm_test_mm_state(mm_slot, KSM_MM_SCANNED)) atomic_dec(&ksm_scan.nr_scannable); - ksm_debug("mm_slot: %p will be exited", mm_slot); } spin_unlock(&ksm_mmlist_lock); return; } - if (!ksm_test_exit(mm)) - ksm_debug("proc-%d(%s) will be removed", - task_pid_nr(mm->owner), mm->owner->comm); - - ksm_debug("proc-%d(%s) is exited", task_pid_nr(mm->owner), mm->owner->comm); spin_lock(&frozen_task_lock); ret = __lksm_remove_candidate(mm->owner); spin_unlock(&frozen_task_lock); -- 2.7.4 From 68c42ea532ace4039263246fa6d0105d85291bfa Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 13 Aug 2020 18:57:09 +0900 Subject: [PATCH 02/16] ARM64: configs: tizen_bcm2711_defconfig: enable I2C_STUB as module Tizen peripheral-io tct requires i2c_stub module to test i2c functionality. Enable I2C_STUB as module. Change-Id: I93ea159349dd5bcfea7ceabd04af239c7f2a1b96 Signed-off-by: Seung-Woo Kim --- arch/arm64/configs/tizen_bcm2711_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/tizen_bcm2711_defconfig b/arch/arm64/configs/tizen_bcm2711_defconfig index a53c912..5a03773 100644 --- a/arch/arm64/configs/tizen_bcm2711_defconfig +++ b/arch/arm64/configs/tizen_bcm2711_defconfig @@ -284,6 +284,7 @@ CONFIG_I2C_CHARDEV=y CONFIG_I2C_BCM2708=m CONFIG_I2C_BCM2835=y CONFIG_I2C_GPIO=y +CONFIG_I2C_STUB=m CONFIG_SPI=y CONFIG_SPI_BCM2835=y CONFIG_SPI_BCM2835AUX=m -- 2.7.4 From ce1a2ebfe25d50af27b32d77512d042f991dbeb7 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Fri, 14 Aug 2020 16:24:24 +0900 Subject: [PATCH 03/16] rpi4: boot: config: disable eeprom i2c hat auto detect From raspberry pi gpio pins, ID_SC and ID_SD are reserved by firmware to detect HAT with i2c, but in Tizen, auto-detection and dynamical setting dt with overlay is not supported. To use the pins for uart2, explictly disable eeprom i2c hat auto detect. Ref: https://www.raspberrypi.org/documentation/configuration/config-txt/boot.md Change-Id: Id5cf016b09e7661317529e1174842915165955bc Signed-off-by: Seung-Woo Kim --- rpi4/boot/config.txt | 4 ++++ rpi4/boot/config_64bit.txt | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/rpi4/boot/config.txt b/rpi4/boot/config.txt index 6bdc59b..2a4fb5b 100644 --- a/rpi4/boot/config.txt +++ b/rpi4/boot/config.txt @@ -59,6 +59,10 @@ dtparam=audio=on # Enable DRM VC4 V3D driver on top of the dispmanx display stack dtoverlay=vc4-fkms-v3d max_framebuffers=2 + +# Disable ID_SC and ID_SD pins to use UART2 +force_eeprom_read=0 + kernel=u-boot.bin [all] diff --git a/rpi4/boot/config_64bit.txt b/rpi4/boot/config_64bit.txt index ee241b1..d071525 100644 --- a/rpi4/boot/config_64bit.txt +++ b/rpi4/boot/config_64bit.txt @@ -59,6 +59,10 @@ dtparam=audio=on # Enable DRM VC4 V3D driver on top of the dispmanx display stack dtoverlay=vc4-fkms-v3d max_framebuffers=2 + +# Disable ID_SC and ID_SD pins to use UART2 +force_eeprom_read=0 + kernel=u-boot.bin [all] -- 2.7.4 From 14f18f90fbab197f6c1264fd42ccfa8fcea10faa Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Fri, 14 Aug 2020 16:47:15 +0900 Subject: [PATCH 04/16] ARM: dts: bcm2711-rpi-4-b: Enable uart2 node Enable uart2 to support '/dev/ttyAMA1'. The node setting is from arch/arm/boot/dts/overlays/uart2-overlay.dts, without cts, rts. Tx pin is gpio 0, pin 27, and Rx pin is gpio 1, pin 28. Ref: https://www.raspberrypi.org/forums/viewtopic.php?t=244827 Change-Id: Ib6c460f6c8e46f3ef7d2d40ab23b3524e438c6c9 Signed-off-by: Seung-Woo Kim --- arch/arm/boot/dts/bcm2711-rpi-4-b.dts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts index 3edc927..d0fab24e 100644 --- a/arch/arm/boot/dts/bcm2711-rpi-4-b.dts +++ b/arch/arm/boot/dts/bcm2711-rpi-4-b.dts @@ -310,6 +310,12 @@ pinctrl-0 = <&uart1_pins>; }; +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&uart2_pins>; + status = "okay"; +}; + &spi0 { pinctrl-names = "default"; pinctrl-0 = <&spi0_pins &spi0_cs_pins>; -- 2.7.4 From 61c0e800c27d2b767072b078d098ce565cbe8bd4 Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Thu, 20 Aug 2020 14:24:51 +0900 Subject: [PATCH 05/16] scripts: mkbootimg_rpi4.sh: Fix module image size to 32MB The partition module size has been modified to 32MB. Change-Id: I467fd7618d345a25d87af62985a1c2f8f47ad0eb Signed-off-by: Hoegeun Kwon --- scripts/mkbootimg_rpi4.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/mkbootimg_rpi4.sh b/scripts/mkbootimg_rpi4.sh index f78575d..1127b94 100755 --- a/scripts/mkbootimg_rpi4.sh +++ b/scripts/mkbootimg_rpi4.sh @@ -58,7 +58,7 @@ mkdir -p tmp/lib/modules mkdir -p tmp_modules # Create modules.img -dd if=/dev/zero of=modules.img bs=1024 count=20480 +dd if=/dev/zero of=modules.img bs=1024 count=32768 mkfs.ext4 -q -F -t ext4 -b 1024 -L modules modules.img sudo mount -o loop modules.img ./tmp/lib/modules if [ -n "$IS_64BIT" ]; then -- 2.7.4 From a51d13fed28dc28eb69c575c660c9f1667a0a57f Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Fri, 21 Aug 2020 10:08:34 +0900 Subject: [PATCH 06/16] Revert "WORKAROUND: security: smack: Allow ptracing even processes in onlycap set" This reverts commit 38b1ae4b960c310b02d7d6935b97d289f0326800. Now crash-worker has System::Privileged privilege, so not anymore ptrace related workaround is necessary. So revert the workaround. Change-Id: I42b535e4152eb742df011a5a08324764b49f989a Signed-off-by: Seung-Woo Kim --- security/smack/smack_lsm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 7c5adf2..12c0fa8 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -442,8 +442,6 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, rc = 0; else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) rc = -EACCES; - else if (smack_ptrace_rule == SMACK_PTRACE_EXACT) - rc = capable(CAP_SYS_PTRACE) != 0 ? 0 : -EACCES; else if (smack_privileged_cred(CAP_SYS_PTRACE, tracercred)) rc = 0; else -- 2.7.4 From cad4c208fb4555786244483ce0f917847677e6ef Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Mon, 3 Aug 2020 14:44:43 +0900 Subject: [PATCH 07/16] mm: memcontrol: Add force_reclaim to reclaim tasks' memory in memcg These days, platforms tend to manage memory on low memory state like andloid's lowmemory killer. These platforms might want to reclaim memory from background tasks as well as kill victims to guarantee free memory at use space level. This patch provides an interface to reclaim a given memcg. After platform's low memory handler moves tasks that the platform wants to reclaim to a memcg and decides how many pages should be reclaimed, it can reclaim the pages from the tasks by writing the number of pages at memory.force_reclaim. Signed-off-by: Hyunhee Kim Signed-off-by: Kyungmin Park [dwoo08.lee: ported from mailing list https://www.spinics.net/lists/cgroups/msg07874.html] Change-Id: I40b1322dfe2628ca306690a15958881b3026606f Signed-off-by: Dongwoo Lee --- mm/memcontrol.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index a3f4c35..704e812 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3367,6 +3367,36 @@ static ssize_t mem_cgroup_force_empty_write(struct kernfs_open_file *of, return mem_cgroup_force_empty(memcg) ?: nbytes; } +#ifdef CONFIG_MEMCG_SWAP +static int mem_cgroup_force_reclaim(struct cgroup_subsys_state *css, + struct cftype *cft, u64 val) +{ + struct mem_cgroup *memcg = mem_cgroup_from_css(css); + unsigned long nr_to_reclaim = val; + unsigned long total = 0; + int loop; + + for (loop = 0; loop < MEM_CGROUP_MAX_RECLAIM_LOOPS; loop++) { + total += try_to_free_mem_cgroup_pages(memcg, nr_to_reclaim, + GFP_KERNEL, true); + + /* + * If nothing was reclaimed after two attempts, there + * may be no reclaimable pages in this hierarchy. + * If more than nr_to_reclaim pages were already reclaimed, + * finish force reclaim. + */ + if (loop && (!total || total > nr_to_reclaim)) + break; + } + + pr_info("%s: [Mem_reclaim] Loop: %d - Total_reclaimed: %lu - nr_to_reclaim: %lu\n", + __func__, loop, total, nr_to_reclaim); + + return total; +} +#endif + static u64 mem_cgroup_hierarchy_read(struct cgroup_subsys_state *css, struct cftype *cft) { @@ -7309,6 +7339,10 @@ static struct cftype memsw_cgroup_files[] = { .write = mem_cgroup_reset, .read_u64 = mem_cgroup_read_u64, }, + { + .name = "force_reclaim", + .write_u64 = mem_cgroup_force_reclaim, + }, { }, /* terminate */ }; -- 2.7.4 From 84c7edd09cdad19c99ceec4a85ea80c51b146403 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Mon, 24 Aug 2020 11:33:04 +0900 Subject: [PATCH 08/16] ARM: tizen_bcm2711_defconfig: Enable RTL8192CU config as module Enable RTL8192CU configuration as module. Change-Id: Ibe38cc889d5e2973028b28615a2210f87056763f Signed-off-by: Jaehoon Chung --- arch/arm/configs/tizen_bcm2711_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/tizen_bcm2711_defconfig b/arch/arm/configs/tizen_bcm2711_defconfig index 7557de2..565611b 100644 --- a/arch/arm/configs/tizen_bcm2711_defconfig +++ b/arch/arm/configs/tizen_bcm2711_defconfig @@ -256,6 +256,7 @@ CONFIG_RT2800USB=y CONFIG_RT2800USB_RT3573=y CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_RT55XX=y +CONFIG_RTL8192CU=m CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_EVDEV=y -- 2.7.4 From 3145de08493ffd1f1a0dd84645b69163c359c0e9 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Mon, 24 Aug 2020 11:34:08 +0900 Subject: [PATCH 09/16] ARM64: tizen_bcm2711_defconfig: Enable RTL8192CU config as module Enable RTL8192CU configuration as module. Change-Id: I4597976b08b9e1e98d61f42da674c28c5e476f10 Signed-off-by: Jaehoon Chung --- arch/arm64/configs/tizen_bcm2711_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/tizen_bcm2711_defconfig b/arch/arm64/configs/tizen_bcm2711_defconfig index 5a03773..3928257 100644 --- a/arch/arm64/configs/tizen_bcm2711_defconfig +++ b/arch/arm64/configs/tizen_bcm2711_defconfig @@ -249,6 +249,7 @@ CONFIG_BRCMFMAC=m CONFIG_BRCMDBG=y CONFIG_RT2X00=y CONFIG_RT2500USB=y +CONFIG_RTL8192CU=m CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_EVDEV=y -- 2.7.4 From c574d1c74096eeab487296ed3afed630f2ae1a05 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Fri, 21 Aug 2020 20:53:46 +0900 Subject: [PATCH 10/16] Revert "block: zram: Add support for dynamic compressor switch" Since dynamic compress switch increases memory usage of meta data along with the size of zram, in order to saving memory, this reverts commit '2aab8469d74f ("block: zram Add support for dynamic compressor switch")' Change-Id: Idd6e1f6f938ca2ebb24ba3e8c65a838bf8fc84d4 Signed-off-by: Dongwoo Lee --- drivers/block/zram/zcomp.c | 84 +++++++++++++------------------------------ drivers/block/zram/zcomp.h | 6 ++-- drivers/block/zram/zram_drv.c | 54 +++++++++++----------------- drivers/block/zram/zram_drv.h | 2 -- 4 files changed, 48 insertions(+), 98 deletions(-) diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c index a02f08d..1a8564a 100644 --- a/drivers/block/zram/zcomp.c +++ b/drivers/block/zram/zcomp.c @@ -63,6 +63,24 @@ static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp) return zstrm; } +bool zcomp_available_algorithm(const char *comp) +{ + int i; + + i = __sysfs_match_string(backends, -1, comp); + if (i >= 0) + return true; + + /* + * Crypto does not ignore a trailing new line symbol, + * so make sure you don't supply a string containing + * one. + * This also means that we permit zcomp initialisation + * with any compressing algorithm known to crypto api. + */ + return crypto_has_comp(comp, 0, 0) == 1; +} + /* show available compressors */ ssize_t zcomp_available_show(const char *comp, char *buf) { @@ -184,43 +202,29 @@ cleanup: return ret; } -static void zcomp_destroy(struct zcomp *comp) +void zcomp_destroy(struct zcomp *comp) { cpuhp_state_remove_instance(CPUHP_ZCOMP_PREPARE, &comp->node); free_percpu(comp->stream); kfree(comp); } -void zcomp_reset(struct list_head *blist) -{ - struct list_head *curr, *next; - struct zcomp *comp; - int i; - - list_for_each_safe(curr, next, blist) { - comp = list_entry(curr, struct zcomp, list); - list_del(&comp->list); - - i = __sysfs_match_string(backends, -1, comp->name); - if (i < 0) - kfree(comp->name); - - zcomp_destroy(comp); - } -} - /* + * search available compressors for requested algorithm. * allocate new zcomp and initialize it. return compressing * backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL) * if requested algorithm is not supported, ERR_PTR(-ENOMEM) in * case of allocation error, or any other error potentially * returned by zcomp_init(). */ -static struct zcomp *zcomp_create(const char *compress) +struct zcomp *zcomp_create(const char *compress) { struct zcomp *comp; int error; + if (!zcomp_available_algorithm(compress)) + return ERR_PTR(-EINVAL); + comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL); if (!comp) return ERR_PTR(-ENOMEM); @@ -233,43 +237,3 @@ static struct zcomp *zcomp_create(const char *compress) } return comp; } - -struct zcomp *zcomp_get_instance(struct list_head *blist, const char *name) -{ - struct zcomp *comp; - const char *comp_name = NULL; - int i; - - list_for_each_entry(comp, blist, list) - if (sysfs_streq(name, comp->name)) - return comp; - - i = __sysfs_match_string(backends, -1, name); - if (i >= 0) - comp_name = backends[i]; - else { - /* - * Crypto does not ignore a trailing new line symbol, - * so make sure you don't supply a string containing - * one. - * This also means that we permit zcomp initialisation - * with any compressing algorithm known to crypto api. - */ - if (crypto_has_comp(name, 0, 0) == 1) - comp_name = kstrdup(name, GFP_KERNEL); - else - return ERR_PTR(-ENOENT); - } - - comp = zcomp_create(comp_name); - if (IS_ERR(comp)) { - pr_err("Cannot initialise %s compressing backend\n", name); - if (i < 0) - kfree(comp_name); - return comp; - } - - list_add(&comp->list, blist); - - return comp; -} diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h index aff688d..1806475 100644 --- a/drivers/block/zram/zcomp.h +++ b/drivers/block/zram/zcomp.h @@ -17,15 +17,15 @@ struct zcomp { struct zcomp_strm * __percpu *stream; const char *name; struct hlist_node node; - struct list_head list; }; int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node); int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node); ssize_t zcomp_available_show(const char *comp, char *buf); +bool zcomp_available_algorithm(const char *comp); -struct zcomp *zcomp_get_instance(struct list_head *blist, const char *name); -void zcomp_reset(struct list_head *blist); +struct zcomp *zcomp_create(const char *comp); +void zcomp_destroy(struct zcomp *comp); struct zcomp_strm *zcomp_stream_get(struct zcomp *comp); void zcomp_stream_put(struct zcomp *comp); diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 6335e66..1bf4a90 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -121,17 +121,6 @@ static unsigned long zram_get_element(struct zram *zram, u32 index) return zram->table[index].element; } -static inline void zram_set_compressor(struct zram *zram, u32 index, - struct zcomp *comp) -{ - zram->table[index].compressor = comp; -} - -static struct zcomp *zram_get_compressor(struct zram *zram, u32 index) -{ - return zram->table[index].compressor; -} - static size_t zram_get_obj_size(struct zram *zram, u32 index) { return zram->table[index].flags & (BIT(ZRAM_FLAG_SHIFT) - 1); @@ -996,7 +985,6 @@ static ssize_t comp_algorithm_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct zram *zram = dev_to_zram(dev); - struct zcomp *comp; char compressor[ARRAY_SIZE(zram->compressor)]; size_t sz; @@ -1006,12 +994,16 @@ static ssize_t comp_algorithm_store(struct device *dev, if (sz > 0 && compressor[sz - 1] == '\n') compressor[sz - 1] = 0x00; - comp = zcomp_get_instance(&zram->backend_list, compressor); - if (IS_ERR_OR_NULL(comp)) + if (!zcomp_available_algorithm(compressor)) return -EINVAL; down_write(&zram->init_lock); - zram->comp = comp; + if (init_done(zram)) { + up_write(&zram->init_lock); + pr_info("Can't change algorithm for initialized device\n"); + return -EBUSY; + } + strcpy(zram->compressor, compressor); up_write(&zram->init_lock); return len; @@ -1206,7 +1198,6 @@ static void zram_free_page(struct zram *zram, size_t index) return; zs_free(zram->mem_pool, handle); - zram->table[index].compressor = NULL; atomic64_sub(zram_get_obj_size(zram, index), &zram->stats.compr_data_size); @@ -1262,13 +1253,12 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index, kunmap_atomic(dst); ret = 0; } else { - struct zcomp *comp = zram_get_compressor(zram, index); - struct zcomp_strm *zstrm = zcomp_stream_get(comp); + struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp); dst = kmap_atomic(page); ret = zcomp_decompress(zstrm, src, size, dst); kunmap_atomic(dst); - zcomp_stream_put(comp); + zcomp_stream_put(zram->comp); } zs_unmap_object(zram->mem_pool, handle); zram_slot_unlock(zram, index); @@ -1322,7 +1312,6 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, unsigned int comp_len = 0; void *src, *dst, *mem; struct zcomp_strm *zstrm; - struct zcomp *comp = NULL; struct page *page = bvec->bv_page; unsigned long element = 0; enum zram_pageflags flags = 0; @@ -1338,14 +1327,13 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, kunmap_atomic(mem); compress_again: - comp = zram->comp; - zstrm = zcomp_stream_get(comp); + zstrm = zcomp_stream_get(zram->comp); src = kmap_atomic(page); ret = zcomp_compress(zstrm, src, &comp_len); kunmap_atomic(src); if (unlikely(ret)) { - zcomp_stream_put(comp); + zcomp_stream_put(zram->comp); pr_err("Compression failed! err=%d\n", ret); zs_free(zram->mem_pool, handle); return ret; @@ -1373,7 +1361,7 @@ compress_again: __GFP_HIGHMEM | __GFP_MOVABLE); if (!handle) { - zcomp_stream_put(comp); + zcomp_stream_put(zram->comp); atomic64_inc(&zram->stats.writestall); handle = zs_malloc(zram->mem_pool, comp_len, GFP_NOIO | __GFP_HIGHMEM | @@ -1387,7 +1375,7 @@ compress_again: update_used_max(zram, alloced_pages); if (zram->limit_pages && alloced_pages > zram->limit_pages) { - zcomp_stream_put(comp); + zcomp_stream_put(zram->comp); zs_free(zram->mem_pool, handle); return -ENOMEM; } @@ -1401,7 +1389,7 @@ compress_again: if (comp_len == PAGE_SIZE) kunmap_atomic(src); - zcomp_stream_put(comp); + zcomp_stream_put(zram->comp); zs_unmap_object(zram->mem_pool, handle); atomic64_add(comp_len, &zram->stats.compr_data_size); out: @@ -1423,8 +1411,6 @@ out: } else { zram_set_handle(zram, index, handle); zram_set_obj_size(zram, index, comp_len); - if (comp_len < PAGE_SIZE) - zram_set_compressor(zram, index, comp); } zram_slot_unlock(zram, index); @@ -1689,6 +1675,7 @@ out: static void zram_reset_device(struct zram *zram) { + struct zcomp *comp; u64 disksize; down_write(&zram->init_lock); @@ -1700,6 +1687,7 @@ static void zram_reset_device(struct zram *zram) return; } + comp = zram->comp; disksize = zram->disksize; zram->disksize = 0; @@ -1710,8 +1698,7 @@ static void zram_reset_device(struct zram *zram) /* I/O operation under all of CPU are done so let's free */ zram_meta_free(zram, disksize); memset(&zram->stats, 0, sizeof(zram->stats)); - zram->comp = NULL; - zcomp_reset(&zram->backend_list); + zcomp_destroy(comp); reset_bdev(zram); } @@ -1740,8 +1727,10 @@ static ssize_t disksize_store(struct device *dev, goto out_unlock; } - comp = zcomp_get_instance(&zram->backend_list, zram->compressor); - if (IS_ERR_OR_NULL(comp)) { + comp = zcomp_create(zram->compressor); + if (IS_ERR(comp)) { + pr_err("Cannot initialise %s compressing backend\n", + zram->compressor); err = PTR_ERR(comp); goto out_free_meta; } @@ -1964,7 +1953,6 @@ static int zram_add(void) device_add_disk(NULL, zram->disk, zram_disk_attr_groups); strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor)); - INIT_LIST_HEAD(&zram->backend_list); zram_debugfs_register(zram); pr_info("Added device: %s\n", zram->disk->disk_name); diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h index 83b320f..f2fd46d 100644 --- a/drivers/block/zram/zram_drv.h +++ b/drivers/block/zram/zram_drv.h @@ -63,7 +63,6 @@ struct zram_table_entry { unsigned long element; }; unsigned long flags; - struct zcomp *compressor; #ifdef CONFIG_ZRAM_MEMORY_TRACKING ktime_t ac_time; #endif @@ -113,7 +112,6 @@ struct zram { * zram is claimed so open request will be failed */ bool claim; /* Protected by bdev->bd_mutex */ - struct list_head backend_list; struct file *backing_dev; #ifdef CONFIG_ZRAM_WRITEBACK spinlock_t wb_limit_lock; -- 2.7.4 From d9cbf6ebd428f00a5ca5655d6fdc03504bbceed0 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 10 Sep 2020 13:25:20 +0900 Subject: [PATCH 11/16] ARM: configs: tizen_bcm2711_defconfig: Enable VIDEO_CODEC_BCM2835 To support v4l2 codec device, enable VIDEO_CODEC_BCM2835. Change-Id: I7f7147901b77b3ff01afc1a7c3c7f0ab9cc20701 Signed-off-by: Seung-Woo Kim --- arch/arm/configs/tizen_bcm2711_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/tizen_bcm2711_defconfig b/arch/arm/configs/tizen_bcm2711_defconfig index 565611b..167c914 100644 --- a/arch/arm/configs/tizen_bcm2711_defconfig +++ b/arch/arm/configs/tizen_bcm2711_defconfig @@ -419,6 +419,7 @@ CONFIG_STAGING_MEDIA=y CONFIG_ANDROID_LOGGER=y CONFIG_SND_BCM2835=y CONFIG_VIDEO_BCM2835=y +CONFIG_VIDEO_CODEC_BCM2835=y CONFIG_CLK_RASPBERRYPI=y CONFIG_MAILBOX=y CONFIG_BCM2835_MBOX=y -- 2.7.4 From 1f214bbbe0819ae7bb4e9ba4384ede5c974c985d Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 10 Sep 2020 13:28:11 +0900 Subject: [PATCH 12/16] ARM64: tizen_bcm2711_defconfig: Enable VIDEO_CODEC_BCM2835 To support v4l2 codec device, enable VIDEO_CODEC_BCM2835 and to meet dependency, enable MEDIA_CONTROLLER. Change-Id: Id473825163c409ceaab5d4b618cf8bddd6af0f68 Signed-off-by: Seung-Woo Kim --- arch/arm64/configs/tizen_bcm2711_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/tizen_bcm2711_defconfig b/arch/arm64/configs/tizen_bcm2711_defconfig index 3928257..de8a7cf 100644 --- a/arch/arm64/configs/tizen_bcm2711_defconfig +++ b/arch/arm64/configs/tizen_bcm2711_defconfig @@ -322,6 +322,7 @@ CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_ANALOG_TV_SUPPORT=y CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y CONFIG_USB_GSPCA_ZC3XX=m @@ -406,6 +407,7 @@ CONFIG_STAGING_MEDIA=y CONFIG_ANDROID_LOGGER=y CONFIG_SND_BCM2835=y CONFIG_VIDEO_BCM2835=y +CONFIG_VIDEO_CODEC_BCM2835=y CONFIG_CLK_RASPBERRYPI=y CONFIG_MAILBOX=y CONFIG_BCM2835_MBOX=y -- 2.7.4 From d2ead75e526d98aa4a838f2e9b66f8114eaca3fa Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 24 Aug 2020 19:56:15 +0900 Subject: [PATCH 13/16] drm/vc4: encoder: Add finer-grained encoder callbacks In the BCM2711, the setup of the HVS, pixelvalve and HDMI controller requires very precise ordering and timing that the regular atomic callbacks don't provide. Let's add new callbacks on top of the regular ones to be able to split the configuration as needed. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/1dd78efe8f29add73c97d0148cfd4ec8e34aaf22.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: For use encoder callback, needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: I16a1a59ad753d7c4e211c24a3563a607faa03a5c --- drivers/gpu/drm/vc4/vc4_crtc.c | 19 +++++++++++++++++++ drivers/gpu/drm/vc4/vc4_drv.h | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 7925b7d..129cf90a 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -495,6 +495,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(old_state); u32 chan = vc4_crtc_state->assigned_channel; + struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); + struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); int ret; require_hvs_enabled(dev); @@ -506,6 +508,9 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1); WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n"); + if (vc4_encoder->post_crtc_disable) + vc4_encoder->post_crtc_disable(encoder); + CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN); if (HVS_READ(SCALER_DISPCTRLX(chan)) & @@ -531,6 +536,9 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) != SCALER_DISPSTATX_EMPTY); + if (vc4_encoder->post_crtc_powerdown) + vc4_encoder->post_crtc_powerdown(encoder); + /* * Make sure we issue a vblank event after disabling the CRTC if * someone was waiting it. @@ -592,6 +600,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); struct drm_display_mode *mode = &crtc->state->adjusted_mode; u32 dispctrl; + struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); + struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); require_hvs_enabled(dev); @@ -627,14 +637,23 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, (vc4_state->feed_txp ? SCALER5_DISPCTRLX_ONESHOT : 0); + if (vc4_encoder->pre_crtc_configure) + vc4_encoder->pre_crtc_configure(encoder); + HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl); + if (vc4_encoder->pre_crtc_enable) + vc4_encoder->pre_crtc_enable(encoder); + /* When feeding the transposer block the pixelvalve is unneeded and * should not be enabled. */ if (!vc4_state->feed_txp) CRTC_WRITE(PV_V_CONTROL, CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN); + + if (vc4_encoder->post_crtc_enable) + vc4_encoder->post_crtc_enable(encoder); } static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index afdf477..9273595 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -440,6 +440,13 @@ struct vc4_encoder { struct drm_encoder base; enum vc4_encoder_type type; u32 clock_select; + + void (*pre_crtc_configure)(struct drm_encoder *encoder); + void (*pre_crtc_enable)(struct drm_encoder *encoder); + void (*post_crtc_enable)(struct drm_encoder *encoder); + + void (*post_crtc_disable)(struct drm_encoder *encoder); + void (*post_crtc_powerdown)(struct drm_encoder *encoder); }; static inline struct vc4_encoder * -- 2.7.4 From fb91e38e8069c7b592767a33f436f0d4ea7a9d34 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 15:53:28 +0900 Subject: [PATCH 14/16] drm/vc4: hdmi: Add reset callback The BCM2711 and BCM283x HDMI controllers use a slightly different reset sequence, so let's add a callback to reset the controller. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/a34bcb493da07eae58ed704f65e72ce0748e8952.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Apply the missing code, needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: If0383cb9b5f8ba5d3f309bfeab3e3c74272d8723 --- drivers/gpu/drm/vc4/vc4_hdmi.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index da9fce5..77c05ae 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -97,6 +97,12 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi) { + HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST); + udelay(1); + HDMI_WRITE(HDMI_M_CTL, 0); + + HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE); + HDMI_WRITE(HDMI_SW_RESET_CONTROL, VC4_HDMI_SW_RESET_HDMI | VC4_HDMI_SW_RESET_FORMAT_DETECT); @@ -1757,14 +1763,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; } - /* HDMI core must be enabled. */ - if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) { - HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST); - udelay(1); - HDMI_WRITE(HDMI_M_CTL, 0); - - HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE); - } pm_runtime_enable(dev); drm_encoder_init(drm, encoder, &vc4_hdmi_encoder_funcs, -- 2.7.4 From 11b503d4d3c574fd920243a5f35d8de1974bd96b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 17:31:56 +0900 Subject: [PATCH 15/16] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate The HSM clock needs to be setup at around 101% of the pixel rate. This was done previously by setting the clock rate to 163.7MHz at probe time and only check in mode_valid whether the mode pixel clock was under the pixel clock +1% or not. However, with 4k we need to change that frequency to a higher frequency than 163.7MHz, and yet want to have the lowest clock as possible to have a decent power saving. Let's change that logic a bit by setting the clock rate of the HSM clock to the pixel rate at encoder_enable time. This would work for the BCM2711 that support 4k resolutions and has a clock that can provide it, but we still have to take care of a 4k panel plugged on a BCM283x SoCs that wouldn't be able to use those modes, so let's define the limit in the variant. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/7e692ddc231d33dd671e70ea04dd1dcf56c1ecb3.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Applied missing code, needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: I43328575d59a0bbccac8d4153ac5ed54f029550b --- drivers/gpu/drm/vc4/vc4_hdmi.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 77c05ae..1c20561 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -612,7 +612,23 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) return; } - hsm_rate = vc4_hdmi->variant->calc_hsm_clock(vc4_hdmi, pixel_rate); + /* + * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must + * be faster than pixel clock, infinitesimally faster, tested in + * simulation. Otherwise, exact value is unimportant for HDMI + * operation." This conflicts with bcm2835's vc4 documentation, which + * states HSM's clock has to be at least 108% of the pixel clock. + * + * Real life tests reveal that vc4's firmware statement holds up, and + * users are able to use pixel clocks closer to HSM's, namely for + * 1920x1200@60Hz. So it was decided to have leave a 1% margin between + * both clocks. Which, for RPi0-3 implies a maximum pixel clock of + * 162MHz. + * + * Additionally, the AXI clock needs to be at least 25% of + * pixel clock, but HSM ends up being the limiting factor. + */ + hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101); ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate); if (ret) { DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); @@ -757,22 +773,6 @@ static enum drm_mode_status vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display_mode *mode) { - /* - * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must - * be faster than pixel clock, infinitesimally faster, tested in - * simulation. Otherwise, exact value is unimportant for HDMI - * operation." This conflicts with bcm2835's vc4 documentation, which - * states HSM's clock has to be at least 108% of the pixel clock. - * - * Real life tests reveal that vc4's firmware statement holds up, and - * users are able to use pixel clocks closer to HSM's, namely for - * 1920x1200@60Hz. So it was decided to have leave a 1% margin between - * both clocks. Which, for RPi0-3 implies a maximum pixel clock of - * 162MHz. - * - * Additionally, the AXI clock needs to be at least 25% of - * pixel clock, but HSM ends up being the limiting factor. - */ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock) @@ -794,7 +794,7 @@ static u32 vc4_hdmi_get_hsm_clock(struct vc4_hdmi *vc4_hdmi) static u32 vc5_hdmi_get_hsm_clock(struct vc4_hdmi *vc4_hdmi) { - return 108000000; + return 120000000; } static u32 vc4_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixel_rate) @@ -815,7 +815,7 @@ static u32 vc5_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixe * Use 101% as this is what the firmware uses. */ - return max_t(unsigned long, 108000000, (pixel_rate / 100) * 101); + return max_t(unsigned long, 120000000, (pixel_rate / 100) * 101); } static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) -- 2.7.4 From d0a23476008384650b5d08111f456649bf425df3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:07:16 +0900 Subject: [PATCH 16/16] drm/vc4: hdmi: Use clk_set_min_rate instead The HSM clock needs to be running at 101% the pixel clock of the HDMI controller, however it's shared between the two HDMI controllers, which means that if the resolutions are different between the two HDMI controllers, and the lowest resolution is on the second (in enable order) controller, the first HDMI controller will end up with a smaller than expected clock rate. Since we don't really need an exact frequency there, we can simply change the minimum rate we expect instead. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/821992209cc0d7a83254bf26fe2bf507ef0994d2.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: I5666bf89beb6bada919b279846e5c204fabd0ffc --- drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 1c20561..61f6279 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -629,7 +629,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) * pixel clock, but HSM ends up being the limiting factor. */ hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101); - ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate); + ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); if (ret) { DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); return; -- 2.7.4