From d29f5c328c92a8ff2c4f146348b8035e484f83c5 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Tue, 27 Oct 2020 19:23:56 +0900 Subject: [PATCH 01/16] brcmfmac: Fix memory leak for unpaired brcmf_{alloc/free} There are missig brcmf_free() for brcmf_alloc(). Fix memory leak by adding missed brcmf_free(). Change-Id: I050398a7b828b0fb2aadbe491f353b3d3c47bdd6 Reported-by: Jaehoon Chung Signed-off-by: Seung-Woo Kim --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c | 6 ++++-- drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c index 3be60ae..cb68f54 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c @@ -1936,16 +1936,18 @@ brcmf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) fwreq = brcmf_pcie_prepare_fw_request(devinfo); if (!fwreq) { ret = -ENOMEM; - goto fail_bus; + goto fail_brcmf; } ret = brcmf_fw_get_firmwares(bus->dev, fwreq, brcmf_pcie_setup); if (ret < 0) { kfree(fwreq); - goto fail_bus; + goto fail_brcmf; } return 0; +fail_brcmf: + brcmf_free(&devinfo->pdev->dev); fail_bus: kfree(bus->msgbuf); kfree(bus); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index a3595b1..e6f4d4e 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -4432,6 +4432,7 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) brcmf_sdiod_intr_unregister(bus->sdiodev); brcmf_detach(bus->sdiodev->dev); + brcmf_free(bus->sdiodev->dev); cancel_work_sync(&bus->datawork); if (bus->brcmf_wq) -- 2.7.4 From e256997d9da3c74449ed05bd2fbbc649a903c8b6 Mon Sep 17 00:00:00 2001 From: Sung-hun Kim Date: Tue, 27 Oct 2020 20:48:36 +0900 Subject: [PATCH 02/16] mm: LKSM: bug fix for kernel memory leak For efficiency, LKSM cleans exited processes in a batched manner when it finishes a scanning iteration. When it finds exited process while it is in the scanning iteration, it just pends the mm_slot of the exited process to the internal list. On the other hend, when KSM daemon cleans mm_slots of exited processes, it should care regions of exited processes to remove unreferenced lksm_region objects. Previously, most regions are maintained properly but only regions in "head" of the exited process list does not be cleaned due to the buggy implementation. At last, uncleaned objects are remained as unreferenced garbages. Follow message is detected by kmemleak (reported by Suengwoo Kim): ========================================================================= unreferenced object 0xffffff80c7083600 (size 128): comm "ksm_crawld", pid 41, jiffies 4294918362 (age 95.632s) hex dump (first 32 bytes): 00 37 08 c7 80 ff ff ff 60 82 19 bd 80 ff ff ff .7......`....... 00 35 08 c7 80 ff ff ff 00 00 00 00 00 00 00 00 .5.............. backtrace: [<0000000048313958>] kmem_cache_alloc_trace+0x1e0/0x348 [<00000000fd246822>] lksm_region_ref_append+0x48/0xf8 [<00000000c5a818a0>] ksm_join+0x3a0/0x498 [<00000000b2c3f36a>] lksm_prepare_full_scan+0xe8/0x390 [<00000000013943b5>] lksm_crawl_thread+0x214/0xbf8 [<00000000b4ce0593>] kthread+0x1b0/0x1b8 [<000000002a3f7216>] ret_from_fork+0x10/0x18 unreferenced object 0xffffff80c7083700 (size 128): comm "ksm_crawld", pid 41, jiffies 4294918362 (age 95.632s) hex dump (first 32 bytes): 00 39 08 c7 80 ff ff ff 00 36 08 c7 80 ff ff ff .9.......6...... 00 35 08 c7 80 ff ff ff 00 00 00 00 00 00 00 00 .5.............. backtrace: [<0000000048313958>] kmem_cache_alloc_trace+0x1e0/0x348 [<00000000fd246822>] lksm_region_ref_append+0x48/0xf8 [<00000000c5a818a0>] ksm_join+0x3a0/0x498 [<00000000b2c3f36a>] lksm_prepare_full_scan+0xe8/0x390 [<00000000013943b5>] lksm_crawl_thread+0x214/0xbf8 [<00000000b4ce0593>] kthread+0x1b0/0x1b8 [<000000002a3f7216>] ret_from_fork+0x10/0x18 ... ========================================================================= This patch takes care of such possible kernel memory leak problem. Change-Id: Ifb4963773b8803da239a1d3108c5b2690d22d531 Signed-off-by: Sung-hun Kim --- mm/lksm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mm/lksm.c b/mm/lksm.c index e6a1533..6081f4b 100644 --- a/mm/lksm.c +++ b/mm/lksm.c @@ -2836,6 +2836,9 @@ static void lksm_flush_removed_mm_list(void) cond_resched(); remove_trailing_rmap_items(head, &head->rmap_list); +#ifdef CONFIG_LKSM_FILTER + lksm_region_ref_list_release(head); +#endif clear_bit(MMF_VM_MERGEABLE, &head->mm->flags); mmdrop(head->mm); free_mm_slot(head); -- 2.7.4 From acea88dbb780d2415aa08108f5b9f87ee7db7a08 Mon Sep 17 00:00:00 2001 From: Sung-hun Kim Date: Wed, 28 Oct 2020 19:26:31 +0900 Subject: [PATCH 03/16] mm: LKSM: bug fix for KASAN out-of-bound access error on accessing a filter KASAN reports out-of-bound accesses (reported by Jaehoon Chung) on slab which is performed for obtaining a next filtered address to find a sharable page. LKSM exploits bitmap-based filters to find sharable pages in an efficient way. A buggy code is a kind of miscalculation for boundary of the allocated bitmap. This patch takes care of it. Change-Id: If45c5ce175db067523b60f11e69e12d2bc798659 Signed-off-by: Sung-hun Kim --- mm/lksm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mm/lksm.c b/mm/lksm.c index 6081f4b..3dcaacf 100644 --- a/mm/lksm.c +++ b/mm/lksm.c @@ -2917,7 +2917,7 @@ static void lksm_insert_mm_slot_ordered(struct mm_slot *slot) static inline void __lksm_copy_filter (unsigned long *orig, unsigned long *newer, int size) { - while (size-- >= 0) + while (--size >= 0) *(newer++) = *(orig++); } @@ -3012,8 +3012,8 @@ static inline unsigned long lksm_get_next_filtered_address unsigned long next_offset, curr_offset, nbits; curr_offset = (addr - base) >> PAGE_SHIFT; - nbits = (region->len == 0) ? BITS_PER_LONG : - (region->len << (6 + PAGE_SHIFT)); + nbits = region->len * BITS_PER_LONG; + if (region->len > SINGLE_FILTER_LEN) next_offset = find_next_bit(region->filter, nbits, curr_offset); else -- 2.7.4 From 36d582530bcbba2167da9c697adbda4047b3ffc6 Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Tue, 3 Nov 2020 17:08:54 +0900 Subject: [PATCH 04/16] Revert "drm/vc4: kms: Fix VBLANK reporting on a disabled CRTC" This reverts commit e805316d5d44b1f1f080fd8ae8a34b69329d940c. Revert this patch for apply patch version 2. Change-Id: If9525aaa3835ab80b8ca83271dc584f68254018a Signed-off-by: Hoegeun Kwon --- drivers/gpu/drm/vc4/vc4_kms.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index a552221..06b291f 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -651,14 +651,6 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = { * need to consider all the running CRTCs in the DRM device to assign * a FIFO, not just the one in the state. * - * - To fix the above, we can't use drm_atomic_get_crtc_state on all - * enabled CRTCs to pull their CRTC state into the global state, since - * a page flip would start considering their vblank to complete. Since - * we don't have a guarantee that they are actually active, that - * vblank might never happen, and shouldn't even be considered if we - * want to do a page flip on a single CRTC. That can be tested by - * doing a modetest -v first on HDMI1 and then on HDMI0. - * * - Since we need the pixelvalve to be disabled and enabled back when * the FIFO is changed, we should keep the FIFO assigned for as long * as the CRTC is enabled, only considering it free again once that @@ -669,8 +661,8 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0); + struct vc4_dev *vc4 = to_vc4_dev(state->dev); struct drm_crtc_state *old_crtc_state, *new_crtc_state; - struct drm_crtc_state *crtc_state; struct drm_crtc *crtc; unsigned int i; @@ -682,13 +674,14 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, * the same CRTCs, instead of evaluating only the CRTC being * modified. */ - for_each_new_or_current_crtc_state(state, crtc, crtc_state) { - struct vc4_crtc_state *vc4_crtc_state; - if (!crtc_state->enable) + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + struct drm_crtc_state *crtc_state; + if (!crtc->state->enable) continue; - vc4_crtc_state = to_vc4_crtc_state(crtc_state); - unassigned_channels &= ~BIT(vc4_crtc_state->assigned_channel); + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) + return PTR_ERR(crtc_state); } for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { @@ -704,8 +697,10 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, if (!new_crtc_state->enable) continue; - if (new_vc4_crtc_state->assigned_channel != VC4_HVS_CHANNEL_DISABLED) + if (new_vc4_crtc_state->assigned_channel != VC4_HVS_CHANNEL_DISABLED) { + unassigned_channels &= ~BIT(new_vc4_crtc_state->assigned_channel); continue; + } /* * The problem we have to solve here is that we have -- 2.7.4 From 2578979a9fe4c962bf782fe65997843f9acc2bcd Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Tue, 3 Nov 2020 17:08:57 +0900 Subject: [PATCH 05/16] Revert "drm/vc4: kms: Don't disable the muxing of an active CRTC" This reverts commit 5d2fec61a25bacc49ee8e84b3c19aee1522f7289. Revert this patch for apply patch version 2. Change-Id: Ib7ff9b242dc3f208cf58f7d8f0741321b725c657 Signed-off-by: Hoegeun Kwon --- drivers/gpu/drm/vc4/vc4_kms.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 06b291f..367cead 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -191,23 +191,6 @@ static void vc4_hvs_pv_muxing_commit(struct vc4_dev *vc4, } } -static struct drm_crtc_state * -drm_atomic_get_new_or_current_crtc_state(struct drm_atomic_state *state, - struct drm_crtc *crtc) -{ - struct drm_crtc_state *crtc_state; - - crtc_state = drm_atomic_get_new_crtc_state(state, crtc); - if (crtc_state) - return crtc_state; - - return crtc->state; -} - -#define for_each_new_or_current_crtc_state(__state, crtc, crtc_state) \ - list_for_each_entry(crtc, &__state->dev->mode_config.crtc_list, head) \ - for_each_if(crtc_state = drm_atomic_get_new_or_current_crtc_state(__state, crtc)) - static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4, struct drm_atomic_state *state) { @@ -217,16 +200,16 @@ static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4, unsigned char dsp3_mux = 3; unsigned char dsp4_mux = 3; unsigned char dsp5_mux = 3; + unsigned int i; u32 reg; - for_each_new_or_current_crtc_state(state, crtc, crtc_state) { + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); - struct vc4_crtc_state *vc4_state; if (!crtc_state->active) continue; - vc4_state = to_vc4_crtc_state(crtc_state); switch (vc4_crtc->data->hvs_output) { case 2: dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1; -- 2.7.4 From 75f8ae9a4394a202950001d7e6233e0a4cbb1b4d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 3 Nov 2020 17:08:59 +0900 Subject: [PATCH 06/16] drm/vc4: kms: Remove useless define NUM_OUTPUTS isn't used anymore, let's remove it. Signed-off-by: Maxime Ripard [hoegeun.kwon: Needed to fix page flip issue of dual hdmi and for enable force hotplug configure.] Signed-off-by: Hoegeun Kwon Change-Id: I20b47a2da045094a06cef9e9a924f46c4dd1d4a9 --- drivers/gpu/drm/vc4/vc4_kms.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 367cead..261ac79 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -615,7 +615,6 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = { .atomic_destroy_state = vc4_load_tracker_destroy_state, }; -#define NUM_OUTPUTS 6 #define NUM_CHANNELS 3 /* -- 2.7.4 From 18a12e7b42d9a732fa402b739ebffd7dbe92cb39 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 3 Nov 2020 17:09:01 +0900 Subject: [PATCH 07/16] drm/vc4: kms: Rename NUM_CHANNELS The NUM_CHANNELS define has a pretty generic name and was right before the function using it. Let's move to something that makes the hardware-specific nature more obvious, and to a more appropriate place. Signed-off-by: Maxime Ripard [hoegeun.kwon: Needed to fix page flip issue of dual hdmi and for enable force hotplug configure.] Signed-off-by: Hoegeun Kwon Change-Id: Ib94c2b3ffbc7e5c95f2c3a965919e523c68f8a12 --- drivers/gpu/drm/vc4/vc4_kms.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 261ac79..c87590d 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -27,6 +27,8 @@ #include "vc4_drv.h" #include "vc4_regs.h" +#define HVS_NUM_CHANNELS 3 + struct vc4_ctm_state { struct drm_private_state base; struct drm_color_ctm *ctm; @@ -615,8 +617,6 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = { .atomic_destroy_state = vc4_load_tracker_destroy_state, }; -#define NUM_CHANNELS 3 - /* * The BCM2711 HVS has up to 7 output connected to the pixelvalves and * the TXP (and therefore all the CRTCs found on that platform). @@ -642,7 +642,7 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = { static int vc4_pv_muxing_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { - unsigned long unassigned_channels = GENMASK(NUM_CHANNELS - 1, 0); + unsigned long unassigned_channels = GENMASK(HVS_NUM_CHANNELS - 1, 0); struct vc4_dev *vc4 = to_vc4_dev(state->dev); struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_crtc *crtc; -- 2.7.4 From 29f6ebcf83fb4d1f1f407a9da191ccffc927cfd3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 3 Nov 2020 17:09:12 +0900 Subject: [PATCH 08/16] drm/vc4: kms: Add functions to create the state objects We're going to add a new private state, so let's move the previous state function creation to some functions to make further additions easier. Signed-off-by: Maxime Ripard [hoegeun.kwon: Needed to fix page flip issue of dual hdmi and for enable force hotplug configure.] Signed-off-by: Hoegeun Kwon Change-Id: Ice57c56dfbdfbb81f486cba7626512cfbb12b905 --- drivers/gpu/drm/vc4/vc4_kms.c | 71 ++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index c87590d..7db8cd6 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -98,6 +98,27 @@ static const struct drm_private_state_funcs vc4_ctm_state_funcs = { .atomic_destroy_state = vc4_ctm_destroy_state, }; +static int vc4_ctm_obj_init(struct vc4_dev *vc4) +{ + struct vc4_ctm_state *ctm_state; + + drm_modeset_lock_init(&vc4->ctm_state_lock); + + ctm_state = kzalloc(sizeof(*ctm_state), GFP_KERNEL); + if (!ctm_state) + return -ENOMEM; + + drm_atomic_private_obj_init(vc4->dev, &vc4->ctm_manager, &ctm_state->base, + &vc4_ctm_state_funcs); + + return 0; +} + +static void vc4_ctm_obj_fini(struct vc4_dev *vc4) +{ + drm_atomic_private_obj_fini(&vc4->ctm_manager); +} + /* Converts a DRM S31.32 value to the HW S0.9 format. */ static u16 vc4_ctm_s31_32_to_s0_9(u64 in) { @@ -617,6 +638,24 @@ static const struct drm_private_state_funcs vc4_load_tracker_state_funcs = { .atomic_destroy_state = vc4_load_tracker_destroy_state, }; +static int vc4_load_tracker_obj_init(struct vc4_dev *vc4) +{ + struct vc4_load_tracker_state *load_state; + + if (!vc4->load_tracker_available) + return 0; + + load_state = kzalloc(sizeof(*load_state), GFP_KERNEL); + if (!load_state) + return -ENOMEM; + + drm_atomic_private_obj_init(vc4->dev, &vc4->load_tracker, + &load_state->base, + &vc4_load_tracker_state_funcs); + + return 0; +} + /* * The BCM2711 HVS has up to 7 output connected to the pixelvalves and * the TXP (and therefore all the CRTCs found on that platform). @@ -756,8 +795,6 @@ static const struct drm_mode_config_funcs vc4_mode_funcs = { int vc4_kms_load(struct drm_device *dev) { struct vc4_dev *vc4 = to_vc4_dev(dev); - struct vc4_ctm_state *ctm_state; - struct vc4_load_tracker_state *load_state; int ret; if (!of_device_is_compatible(dev->dev->of_node, "brcm,bcm2711-vc5")) { @@ -795,30 +832,22 @@ int vc4_kms_load(struct drm_device *dev) dev->mode_config.allow_fb_modifiers = true; dev->mode_config.normalize_zpos = true; - drm_modeset_lock_init(&vc4->ctm_state_lock); - - ctm_state = kzalloc(sizeof(*ctm_state), GFP_KERNEL); - if (!ctm_state) - return -ENOMEM; - - drm_atomic_private_obj_init(dev, &vc4->ctm_manager, &ctm_state->base, - &vc4_ctm_state_funcs); - - if (vc4->load_tracker_available) { - load_state = kzalloc(sizeof(*load_state), GFP_KERNEL); - if (!load_state) { - drm_atomic_private_obj_fini(&vc4->ctm_manager); - return -ENOMEM; - } + ret = vc4_ctm_obj_init(vc4); + if (ret) + return ret; - drm_atomic_private_obj_init(dev, &vc4->load_tracker, - &load_state->base, - &vc4_load_tracker_state_funcs); - } + ret = vc4_load_tracker_obj_init(vc4); + if (ret) + goto ctm_fini; drm_mode_config_reset(dev); drm_kms_helper_poll_init(dev); return 0; + +ctm_fini: + vc4_ctm_obj_fini(vc4); + + return ret; } -- 2.7.4 From 5a8a9828f9ee1fca4b545cb0eba095c7143da937 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 3 Nov 2020 17:09:14 +0900 Subject: [PATCH 09/16] drm/vc4: kms: Store the unassigned channel list in the state If a CRTC is enabled but not active, and that we're then doing a page flip on another CRTC, drm_atomic_get_crtc_state will bring the first CRTC state into the global state, and will make us wait for its vblank as well, even though that might never occur. Instead of creating the list of the free channels each time atomic_check is called, and calling drm_atomic_get_crtc_state to retrieve the allocated channels, let's create a private state object in the main atomic state, and use it to store the available channels. Fixes: 87ebcd42fb7b ("drm/vc4: crtc: Assign output to channel automatically") Signed-off-by: Maxime Ripard [hoegeun.kwon: Needed to fix page flip issue of dual hdmi and for enable force hotplug configure. fix to unsigned long unassigned_channels instead of integer to fix build errors.] Signed-off-by: Hoegeun Kwon Change-Id: Ic8bf07502f614595070e21ecc7912e671a193b09 --- drivers/gpu/drm/vc4/vc4_drv.h | 1 + drivers/gpu/drm/vc4/vc4_kms.c | 129 +++++++++++++++++++++++++++++++++--------- 2 files changed, 103 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 457fd68..d21b38a 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -222,6 +222,7 @@ struct vc4_dev { struct drm_modeset_lock ctm_state_lock; struct drm_private_obj ctm_manager; + struct drm_private_obj hvs_channels; struct drm_private_obj load_tracker; /* List of vc4_debugfs_info_entry for adding to debugfs once diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 7db8cd6..ba06a8b 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -40,6 +40,17 @@ static struct vc4_ctm_state *to_vc4_ctm_state(struct drm_private_state *priv) return container_of(priv, struct vc4_ctm_state, base); } +struct vc4_hvs_state { + struct drm_private_state base; + unsigned long unassigned_channels; +}; + + static struct vc4_hvs_state * +to_vc4_hvs_state(struct drm_private_state *priv) +{ + return container_of(priv, struct vc4_hvs_state, base); +} + struct vc4_load_tracker_state { struct drm_private_state base; u64 hvs_load; @@ -656,6 +667,71 @@ static int vc4_load_tracker_obj_init(struct vc4_dev *vc4) return 0; } +static void vc4_load_tracker_obj_fini(struct vc4_dev *vc4) +{ + if (!vc4->load_tracker_available) + return; + + drm_atomic_private_obj_fini(&vc4->load_tracker); +} + + static struct drm_private_state * +vc4_hvs_channels_duplicate_state(struct drm_private_obj *obj) +{ + struct vc4_hvs_state *state; + + state = kmemdup(obj->state, sizeof(*state), GFP_KERNEL); + if (!state) + return NULL; + + __drm_atomic_helper_private_obj_duplicate_state(obj, &state->base); + + return &state->base; +} + +static void vc4_hvs_channels_destroy_state(struct drm_private_obj *obj, + struct drm_private_state *state) +{ + struct vc4_hvs_state *hvs_state; + + hvs_state = to_vc4_hvs_state(state); + kfree(hvs_state); +} + +static const struct drm_private_state_funcs vc4_hvs_state_funcs = { + .atomic_duplicate_state = vc4_hvs_channels_duplicate_state, + .atomic_destroy_state = vc4_hvs_channels_destroy_state, +}; + +static int vc4_hvs_channels_obj_init(struct vc4_dev *vc4) +{ + struct vc4_hvs_state *state; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->unassigned_channels = GENMASK(HVS_NUM_CHANNELS - 1, 0); + drm_atomic_private_obj_init(vc4->dev, &vc4->hvs_channels, + &state->base, + &vc4_hvs_state_funcs); + + return 0; +} + + static struct vc4_hvs_state * +vc4_hvs_get_global_state(struct drm_atomic_state *state) +{ + struct vc4_dev *vc4 = to_vc4_dev(state->dev); + struct drm_private_state *priv_state; + + priv_state = drm_atomic_get_private_obj_state(state, &vc4->hvs_channels); + if (IS_ERR(priv_state)) + return ERR_CAST(priv_state); + + return to_vc4_hvs_state(priv_state); +} + /* * The BCM2711 HVS has up to 7 output connected to the pixelvalves and * the TXP (and therefore all the CRTCs found on that platform). @@ -672,6 +748,14 @@ static int vc4_load_tracker_obj_init(struct vc4_dev *vc4) * need to consider all the running CRTCs in the DRM device to assign * a FIFO, not just the one in the state. * + * - To fix the above, we can't use drm_atomic_get_crtc_state on all + * enabled CRTCs to pull their CRTC state into the global state, since + * a page flip would start considering their vblank to complete. Since + * we don't have a guarantee that they are actually active, that + * vblank might never happen, and shouldn't even be considered if we + * want to do a page flip on a single CRTC. That can be tested by + * doing a modetest -v first on HDMI1 and then on HDMI0. + * * - Since we need the pixelvalve to be disabled and enabled back when * the FIFO is changed, we should keep the FIFO assigned for as long * as the CRTC is enabled, only considering it free again once that @@ -681,29 +765,14 @@ static int vc4_load_tracker_obj_init(struct vc4_dev *vc4) static int vc4_pv_muxing_atomic_check(struct drm_device *dev, struct drm_atomic_state *state) { - unsigned long unassigned_channels = GENMASK(HVS_NUM_CHANNELS - 1, 0); - struct vc4_dev *vc4 = to_vc4_dev(state->dev); + struct vc4_hvs_state *hvs_state; struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_crtc *crtc; unsigned int i; - /* - * Since the HVS FIFOs are shared across all the pixelvalves and - * the TXP (and thus all the CRTCs), we need to pull the current - * state of all the enabled CRTCs so that an update to a single - * CRTC still keeps the previous FIFOs enabled and assigned to - * the same CRTCs, instead of evaluating only the CRTC being - * modified. - */ - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { - struct drm_crtc_state *crtc_state; - if (!crtc->state->enable) - continue; - - crtc_state = drm_atomic_get_crtc_state(state, crtc); - if (IS_ERR(crtc_state)) - return PTR_ERR(crtc_state); - } + hvs_state = vc4_hvs_get_global_state(state); + if (!hvs_state) + return -EINVAL; for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { struct vc4_crtc_state *new_vc4_crtc_state = @@ -712,16 +781,16 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, bool is_assigned = false; unsigned int channel; - if (old_crtc_state->enable && !new_crtc_state->enable) + if (old_crtc_state->enable && !new_crtc_state->enable) { + hvs_state->unassigned_channels |= BIT(old_vc4_crtc_state->assigned_channel); new_vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED; + } if (!new_crtc_state->enable) continue; - if (new_vc4_crtc_state->assigned_channel != VC4_HVS_CHANNEL_DISABLED) { - unassigned_channels &= ~BIT(new_vc4_crtc_state->assigned_channel); + if (new_vc4_crtc_state->assigned_channel != VC4_HVS_CHANNEL_DISABLED) continue; - } /* * The problem we have to solve here is that we have @@ -747,14 +816,13 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, * the future, we will need to have something smarter, * but it works so far. */ - for_each_set_bit(channel, &unassigned_channels, - sizeof(unassigned_channels)) { - + for_each_set_bit(channel, &hvs_state->unassigned_channels, + sizeof(hvs_state->unassigned_channels)) { if (!(BIT(channel) & vc4_crtc->data->hvs_available_channels)) continue; new_vc4_crtc_state->assigned_channel = channel; - unassigned_channels &= ~BIT(channel); + hvs_state->unassigned_channels &= ~BIT(channel); is_assigned = true; break; } @@ -840,12 +908,19 @@ int vc4_kms_load(struct drm_device *dev) if (ret) goto ctm_fini; + ret = vc4_hvs_channels_obj_init(vc4); + if (ret) + goto load_tracker_fini; + drm_mode_config_reset(dev); drm_kms_helper_poll_init(dev); return 0; +load_tracker_fini: + vc4_load_tracker_obj_fini(vc4); + ctm_fini: vc4_ctm_obj_fini(vc4); -- 2.7.4 From 27140845d2a14c4b3e94802fd6ff750fb30d48eb Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 3 Nov 2020 17:09:17 +0900 Subject: [PATCH 10/16] drm/vc4: kms: Don't disable the muxing of an active CRTC The current HVS muxing code will consider the CRTCs in a given state to setup their muxing in the HVS, and disable the other CRTCs muxes. However, it's valid to only update a single CRTC with a state, and in this situation we would mux out a CRTC that was enabled but left untouched by the new state. Fix this by setting a flag on the CRTC state when the muxing has been changed, and only change the muxing configuration when that flag is there. Fixes: 87ebcd42fb7b ("drm/vc4: crtc: Assign output to channel automatically") Signed-off-by: Maxime Ripard [hoegeun.kwon: Needed to fix page flip issue of dual hdmi and for enable force hotplug configure. ] Signed-off-by: Hoegeun Kwon Change-Id: I5c9fb79c9ad07caa8fe77ea724f35c955df6edcf --- drivers/gpu/drm/vc4/vc4_drv.h | 1 + drivers/gpu/drm/vc4/vc4_kms.c | 84 +++++++++++++++++++++++++------------------ 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index d21b38a..056d8cd 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -503,6 +503,7 @@ struct vc4_crtc_state { struct drm_mm_node mm; bool feed_txp; bool txp_armed; + bool needs_muxing; unsigned int assigned_channel; struct { diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index ba06a8b..5e8e2ee 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -230,10 +230,7 @@ static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4, { struct drm_crtc_state *crtc_state; struct drm_crtc *crtc; - unsigned char dsp2_mux = 0; - unsigned char dsp3_mux = 3; - unsigned char dsp4_mux = 3; - unsigned char dsp5_mux = 3; + unsigned char mux; unsigned int i; u32 reg; @@ -241,50 +238,58 @@ static void vc5_hvs_pv_muxing_commit(struct vc4_dev *vc4, struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc_state); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); - if (!crtc_state->active) + if (!vc4_state->needs_muxing) continue; switch (vc4_crtc->data->hvs_output) { case 2: - dsp2_mux = (vc4_state->assigned_channel == 2) ? 0 : 1; + mux = (vc4_state->assigned_channel == 2) ? 0 : 1; + reg = HVS_READ(SCALER_DISPECTRL); + HVS_WRITE(SCALER_DISPECTRL, + (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) | + VC4_SET_FIELD(mux, SCALER_DISPECTRL_DSP2_MUX)); break; case 3: - dsp3_mux = vc4_state->assigned_channel; + if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED) + mux = 3; + else + mux = vc4_state->assigned_channel; + + reg = HVS_READ(SCALER_DISPCTRL); + HVS_WRITE(SCALER_DISPCTRL, + (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) | + VC4_SET_FIELD(mux, SCALER_DISPCTRL_DSP3_MUX)); break; case 4: - dsp4_mux = vc4_state->assigned_channel; + if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED) + mux = 3; + else + mux = vc4_state->assigned_channel; + + reg = HVS_READ(SCALER_DISPEOLN); + HVS_WRITE(SCALER_DISPEOLN, + (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) | + VC4_SET_FIELD(mux, SCALER_DISPEOLN_DSP4_MUX)); break; case 5: - dsp5_mux = vc4_state->assigned_channel; + if (vc4_state->assigned_channel == VC4_HVS_CHANNEL_DISABLED) + mux = 3; + else + mux = vc4_state->assigned_channel; + + reg = HVS_READ(SCALER_DISPDITHER); + HVS_WRITE(SCALER_DISPDITHER, + (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) | + VC4_SET_FIELD(mux, SCALER_DISPDITHER_DSP5_MUX)); break; default: break; } } - - reg = HVS_READ(SCALER_DISPECTRL); - HVS_WRITE(SCALER_DISPECTRL, - (reg & ~SCALER_DISPECTRL_DSP2_MUX_MASK) | - VC4_SET_FIELD(dsp2_mux, SCALER_DISPECTRL_DSP2_MUX)); - - reg = HVS_READ(SCALER_DISPCTRL); - HVS_WRITE(SCALER_DISPCTRL, - (reg & ~SCALER_DISPCTRL_DSP3_MUX_MASK) | - VC4_SET_FIELD(dsp3_mux, SCALER_DISPCTRL_DSP3_MUX)); - - reg = HVS_READ(SCALER_DISPEOLN); - HVS_WRITE(SCALER_DISPEOLN, - (reg & ~SCALER_DISPEOLN_DSP4_MUX_MASK) | - VC4_SET_FIELD(dsp4_mux, SCALER_DISPEOLN_DSP4_MUX)); - - reg = HVS_READ(SCALER_DISPDITHER); - HVS_WRITE(SCALER_DISPDITHER, - (reg & ~SCALER_DISPDITHER_DSP5_MUX_MASK) | - VC4_SET_FIELD(dsp5_mux, SCALER_DISPDITHER_DSP5_MUX)); } @@ -775,22 +780,31 @@ static int vc4_pv_muxing_atomic_check(struct drm_device *dev, return -EINVAL; for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { + struct vc4_crtc_state *old_vc4_crtc_state = + to_vc4_crtc_state(old_crtc_state); struct vc4_crtc_state *new_vc4_crtc_state = to_vc4_crtc_state(new_crtc_state); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); bool is_assigned = false; unsigned int channel; - if (old_crtc_state->enable && !new_crtc_state->enable) { - hvs_state->unassigned_channels |= BIT(old_vc4_crtc_state->assigned_channel); - new_vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED; + /* Nothing to do here, let's skip it */ + if ((old_crtc_state->enable && new_crtc_state->enable) || + (!old_crtc_state->enable && !new_crtc_state->enable)) { + new_vc4_crtc_state->needs_muxing = false; + continue; } - if (!new_crtc_state->enable) - continue; + /* Muxing will need to be modified, mark it as such */ + new_vc4_crtc_state->needs_muxing = true; + - if (new_vc4_crtc_state->assigned_channel != VC4_HVS_CHANNEL_DISABLED) + /* If we're disabling our CRTC, we put back our channel */ + if (old_crtc_state->enable && !new_crtc_state->enable) { + hvs_state->unassigned_channels |= BIT(old_vc4_crtc_state->assigned_channel); + new_vc4_crtc_state->assigned_channel = VC4_HVS_CHANNEL_DISABLED; continue; + } /* * The problem we have to solve here is that we have -- 2.7.4 From 426af4a6f87e20039e905894c8f23ba9ab13c578 Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Tue, 3 Nov 2020 17:09:20 +0900 Subject: [PATCH 11/16] rpi4: boot: config: Enable hdmi_force_hotplug There is a problem that the booting stops when booting without connecting HDMI. To fix it we need to enable hdmi_force_hotplug. Change-Id: I44e960a04f75c999ab69a75ad72d67311f8b70c1 Signed-off-by: Hoegeun Kwon --- rpi4/boot/config.txt | 2 +- rpi4/boot/config_64bit.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rpi4/boot/config.txt b/rpi4/boot/config.txt index 2a4fb5b..27cc5ff 100644 --- a/rpi4/boot/config.txt +++ b/rpi4/boot/config.txt @@ -22,7 +22,7 @@ #framebuffer_height=720 # uncomment if hdmi display is not detected and composite is being output -#hdmi_force_hotplug=1 +hdmi_force_hotplug=1 # uncomment to force a specific HDMI mode (this will force VGA) #hdmi_group=1 diff --git a/rpi4/boot/config_64bit.txt b/rpi4/boot/config_64bit.txt index d071525..6075f04 100644 --- a/rpi4/boot/config_64bit.txt +++ b/rpi4/boot/config_64bit.txt @@ -22,7 +22,7 @@ #framebuffer_height=720 # uncomment if hdmi display is not detected and composite is being output -#hdmi_force_hotplug=1 +hdmi_force_hotplug=1 # uncomment to force a specific HDMI mode (this will force VGA) #hdmi_group=1 -- 2.7.4 From 0616a8487a626559a2b6974d890c884831b3df0c Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Mon, 9 Nov 2020 16:03:59 +0900 Subject: [PATCH 12/16] arm64: tizen_bcm2711_defconfig: Fix console loglevel for logo display Modifiy CONSOLE_LOGLEVEL_QUIET defconfig to 3 for logo display. Change-Id: I5112d85dedd1e116a75af0d07c09d77182ff4f5a Signed-off-by: Hoegeun Kwon --- 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 de8a7cf..b1bccf9 100644 --- a/arch/arm64/configs/tizen_bcm2711_defconfig +++ b/arch/arm64/configs/tizen_bcm2711_defconfig @@ -462,6 +462,7 @@ CONFIG_CRC_ITU_T=y CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=256 CONFIG_PRINTK_TIME=y +CONFIG_CONSOLE_LOGLEVEL_QUIET=3 CONFIG_BOOT_PRINTK_DELAY=y CONFIG_DEBUG_MEMORY_INIT=y CONFIG_DETECT_HUNG_TASK=y -- 2.7.4 From d681d0bc4f6623300182e2e4425b8870e7269705 Mon Sep 17 00:00:00 2001 From: Hoegeun Kwon Date: Mon, 9 Nov 2020 16:44:46 +0900 Subject: [PATCH 13/16] ARM: tizen_bcm2711_defconfig: Fix console loglevel for logo display Modifiy CONSOLE_LOGLEVEL_QUIET defconfig to 3 for logo display. Change-Id: Idae234c40304fbe8fd5f02941e53505a6bd189fa Signed-off-by: Hoegeun Kwon --- 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 167c914..0157e8d 100644 --- a/arch/arm/configs/tizen_bcm2711_defconfig +++ b/arch/arm/configs/tizen_bcm2711_defconfig @@ -485,6 +485,7 @@ CONFIG_CRC7=m CONFIG_DMA_CMA=y CONFIG_CMA_SIZE_MBYTES=256 CONFIG_PRINTK_TIME=y +CONFIG_CONSOLE_LOGLEVEL_QUIET=3 CONFIG_BOOT_PRINTK_DELAY=y CONFIG_DEBUG_MEMORY_INIT=y CONFIG_DETECT_HUNG_TASK=y -- 2.7.4 From 30dcbc16255df980f9834534dad52281a7926f74 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 13 Aug 2020 16:58:18 +0100 Subject: [PATCH 14/16] staging: vc04_services: codec: Fix incorrect buffer cleanup The allocated input and output buffers are initialised in buf_init and should only be cleared up in buf_cleanup. stop_streaming was (incorrectly) cleaning up the buffers to avoid an issue in videobuf2 that had been fixed by the orphaned buffer support. Remove the erroneous cleanup. Signed-off-by: Dave Stevenson [sw0312.kim: cherry-pick rpi-5.4.y commit to fix video decoding seek issue] Ref: https://github.com/raspberrypi/linux/pull/3790 Signed-off-by: Seung-Woo Kim Change-Id: I38e3a257a941753b02e448d6d5dd1c8486b648f1 --- .../vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c index 3fe8197..b6c5a66 100644 --- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c +++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c @@ -2320,10 +2320,7 @@ static void bcm2835_codec_stop_streaming(struct vb2_queue *q) struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type); struct vchiq_mmal_port *port = get_port_data(ctx, q->type); struct vb2_v4l2_buffer *vbuf; - struct vb2_v4l2_buffer *vb2; - struct v4l2_m2m_buffer *m2m; - struct m2m_mmal_buffer *buf; - int ret, i; + int ret; v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d - return buffers\n", __func__, q->type); @@ -2363,18 +2360,6 @@ static void bcm2835_codec_stop_streaming(struct vb2_queue *q) } } - /* - * Release the VCSM handle here as otherwise REQBUFS(0) aborts because - * someone is using the dmabuf before giving the driver a chance to do - * anything about it. - */ - for (i = 0; i < q->num_buffers; i++) { - vb2 = to_vb2_v4l2_buffer(q->bufs[i]); - m2m = container_of(vb2, struct v4l2_m2m_buffer, vb); - buf = container_of(m2m, struct m2m_mmal_buffer, m2m); - - bcm2835_codec_mmal_buf_cleanup(&buf->mmal); - } /* If both ports disabled, then disable the component */ if (!ctx->component->input[0].enabled && -- 2.7.4 From 8da40a4662a49961088d79c56d739ce25f32e733 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 13 Aug 2020 17:01:27 +0100 Subject: [PATCH 15/16] staging: vc04_service: codec: Allow start_streaming to update the buffernum start_streaming passes a count of how many buffers have been queued to videobuf2. Allow this value to update the number of buffers the VPU allocates on a port to avoid buffer recycling issues. Signed-off-by: Dave Stevenson [sw0312.kim: cherry-pick rpi-5.4.y commit to fix video decoding seek issue] Ref: https://github.com/raspberrypi/linux/pull/3790 Signed-off-by: Seung-Woo Kim Change-Id: Iaf37f57df95789cc8987b268feab1f0fa7377849 --- .../bcm2835-codec/bcm2835-v4l2-codec.c | 23 ++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c index b6c5a66..427048c 100644 --- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c +++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c @@ -2268,6 +2268,7 @@ static int bcm2835_codec_start_streaming(struct vb2_queue *q, struct bcm2835_codec_ctx *ctx = vb2_get_drv_priv(q); struct bcm2835_codec_dev *dev = ctx->dev; struct bcm2835_codec_q_data *q_data = get_q_data(ctx, q->type); + struct vchiq_mmal_port *port = get_port_data(ctx, q->type); int ret; v4l2_dbg(1, debug, &ctx->dev->v4l2_dev, "%s: type: %d count %d\n", @@ -2283,6 +2284,20 @@ static int bcm2835_codec_start_streaming(struct vb2_queue *q, ctx->component_enabled = true; } + if (count < port->minimum_buffer.num) + count = port->minimum_buffer.num; + + if (port->current_buffer.num != count + 1) { + v4l2_dbg(2, debug, &ctx->dev->v4l2_dev, "%s: ctx:%p, buffer count changed %u to %u\n", + __func__, ctx, port->current_buffer.num, count + 1); + + port->current_buffer.num = count + 1; + ret = vchiq_mmal_port_set_format(dev->instance, port); + if (ret) + v4l2_err(&ctx->dev->v4l2_dev, "%s: Error updating buffer count, ret %d\n", + __func__, ret); + } + if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { /* * Create the EOS buffer. @@ -2294,17 +2309,17 @@ static int bcm2835_codec_start_streaming(struct vb2_queue *q, &q_data->eos_buffer.mmal); q_data->eos_buffer_in_use = false; - ctx->component->input[0].cb_ctx = ctx; + port->cb_ctx = ctx; ret = vchiq_mmal_port_enable(dev->instance, - &ctx->component->input[0], + port, ip_buffer_cb); if (ret) v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling i/p port, ret %d\n", __func__, ret); } else { - ctx->component->output[0].cb_ctx = ctx; + port->cb_ctx = ctx; ret = vchiq_mmal_port_enable(dev->instance, - &ctx->component->output[0], + port, op_buffer_cb); if (ret) v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling o/p port, ret %d\n", -- 2.7.4 From cb24cc8409d2eb4a23a94c2a7403ea6376bd7fa7 Mon Sep 17 00:00:00 2001 From: Dave Stevenson Date: Thu, 13 Aug 2020 17:04:53 +0100 Subject: [PATCH 16/16] staging: vc04_services: codec: Fix component enable/disable start_streaming enabled the VPU component if ctx->component_enabled was not set. stop_streaming disabled the VPU component if both ports were disabled. It didn't clear ctx->component_enabled. If seeking, this meant that the component never got re-enabled, and buffers never got processed afterwards. Signed-off-by: Dave Stevenson [sw0312.kim: cherry-pick rpi-5.4.y commit to fix video decoding seek issue] Ref: https://github.com/raspberrypi/linux/pull/3790 Signed-off-by: Seung-Woo Kim Change-Id: Ibf27e3ed2dc3d98d64a78b10878d6339d77f8a33 --- drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c index 427048c..14c47e2 100644 --- a/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c +++ b/drivers/staging/vc04_services/bcm2835-codec/bcm2835-v4l2-codec.c @@ -2377,13 +2377,15 @@ static void bcm2835_codec_stop_streaming(struct vb2_queue *q) /* If both ports disabled, then disable the component */ - if (!ctx->component->input[0].enabled && + if (ctx->component_enabled && + !ctx->component->input[0].enabled && !ctx->component->output[0].enabled) { ret = vchiq_mmal_component_disable(dev->instance, ctx->component); if (ret) v4l2_err(&ctx->dev->v4l2_dev, "%s: Failed enabling component, ret %d\n", __func__, ret); + ctx->component_enabled = false; } if (V4L2_TYPE_IS_OUTPUT(q->type)) -- 2.7.4