Merge fa02fcd94b ("Merge tag 'media/v5.10-2' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media") into android-mainline
Steps on the way to 5.10-rc6 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com> Change-Id: I46dce0f7b71f0c6667e4d5fa7a693dc5dff9ec70
This commit is contained in:
@@ -243,10 +243,8 @@ static inline int constant_fls(unsigned int x)
|
|||||||
x <<= 2;
|
x <<= 2;
|
||||||
r -= 2;
|
r -= 2;
|
||||||
}
|
}
|
||||||
if (!(x & 0x80000000u)) {
|
if (!(x & 0x80000000u))
|
||||||
x <<= 1;
|
|
||||||
r -= 1;
|
r -= 1;
|
||||||
}
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,15 +38,27 @@
|
|||||||
|
|
||||||
#ifdef CONFIG_ARC_DW2_UNWIND
|
#ifdef CONFIG_ARC_DW2_UNWIND
|
||||||
|
|
||||||
static void seed_unwind_frame_info(struct task_struct *tsk,
|
static int
|
||||||
struct pt_regs *regs,
|
seed_unwind_frame_info(struct task_struct *tsk, struct pt_regs *regs,
|
||||||
struct unwind_frame_info *frame_info)
|
struct unwind_frame_info *frame_info)
|
||||||
{
|
{
|
||||||
/*
|
if (regs) {
|
||||||
* synchronous unwinding (e.g. dump_stack)
|
/*
|
||||||
* - uses current values of SP and friends
|
* Asynchronous unwinding of intr/exception
|
||||||
*/
|
* - Just uses the pt_regs passed
|
||||||
if (tsk == NULL && regs == NULL) {
|
*/
|
||||||
|
frame_info->task = tsk;
|
||||||
|
|
||||||
|
frame_info->regs.r27 = regs->fp;
|
||||||
|
frame_info->regs.r28 = regs->sp;
|
||||||
|
frame_info->regs.r31 = regs->blink;
|
||||||
|
frame_info->regs.r63 = regs->ret;
|
||||||
|
frame_info->call_frame = 0;
|
||||||
|
} else if (tsk == NULL || tsk == current) {
|
||||||
|
/*
|
||||||
|
* synchronous unwinding (e.g. dump_stack)
|
||||||
|
* - uses current values of SP and friends
|
||||||
|
*/
|
||||||
unsigned long fp, sp, blink, ret;
|
unsigned long fp, sp, blink, ret;
|
||||||
frame_info->task = current;
|
frame_info->task = current;
|
||||||
|
|
||||||
@@ -63,13 +75,17 @@ static void seed_unwind_frame_info(struct task_struct *tsk,
|
|||||||
frame_info->regs.r31 = blink;
|
frame_info->regs.r31 = blink;
|
||||||
frame_info->regs.r63 = ret;
|
frame_info->regs.r63 = ret;
|
||||||
frame_info->call_frame = 0;
|
frame_info->call_frame = 0;
|
||||||
} else if (regs == NULL) {
|
} else {
|
||||||
/*
|
/*
|
||||||
* Asynchronous unwinding of sleeping task
|
* Asynchronous unwinding of a likely sleeping task
|
||||||
* - Gets SP etc from task's pt_regs (saved bottom of kernel
|
* - first ensure it is actually sleeping
|
||||||
* mode stack of task)
|
* - if so, it will be in __switch_to, kernel mode SP of task
|
||||||
|
* is safe-kept and BLINK at a well known location in there
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (tsk->state == TASK_RUNNING)
|
||||||
|
return -1;
|
||||||
|
|
||||||
frame_info->task = tsk;
|
frame_info->task = tsk;
|
||||||
|
|
||||||
frame_info->regs.r27 = TSK_K_FP(tsk);
|
frame_info->regs.r27 = TSK_K_FP(tsk);
|
||||||
@@ -90,19 +106,8 @@ static void seed_unwind_frame_info(struct task_struct *tsk,
|
|||||||
frame_info->regs.r28 += 60;
|
frame_info->regs.r28 += 60;
|
||||||
frame_info->call_frame = 0;
|
frame_info->call_frame = 0;
|
||||||
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* Asynchronous unwinding of intr/exception
|
|
||||||
* - Just uses the pt_regs passed
|
|
||||||
*/
|
|
||||||
frame_info->task = tsk;
|
|
||||||
|
|
||||||
frame_info->regs.r27 = regs->fp;
|
|
||||||
frame_info->regs.r28 = regs->sp;
|
|
||||||
frame_info->regs.r31 = regs->blink;
|
|
||||||
frame_info->regs.r63 = regs->ret;
|
|
||||||
frame_info->call_frame = 0;
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -116,7 +121,8 @@ arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs,
|
|||||||
unsigned int address;
|
unsigned int address;
|
||||||
struct unwind_frame_info frame_info;
|
struct unwind_frame_info frame_info;
|
||||||
|
|
||||||
seed_unwind_frame_info(tsk, regs, &frame_info);
|
if (seed_unwind_frame_info(tsk, regs, &frame_info))
|
||||||
|
return 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
address = UNW_PC(&frame_info);
|
address = UNW_PC(&frame_info);
|
||||||
|
|||||||
@@ -30,14 +30,14 @@
|
|||||||
* -Changes related to MMU v2 (Rel 4.8)
|
* -Changes related to MMU v2 (Rel 4.8)
|
||||||
*
|
*
|
||||||
* Vineetg: Aug 29th 2008
|
* Vineetg: Aug 29th 2008
|
||||||
* -In TLB Flush operations (Metal Fix MMU) there is a explict command to
|
* -In TLB Flush operations (Metal Fix MMU) there is a explicit command to
|
||||||
* flush Micro-TLBS. If TLB Index Reg is invalid prior to TLBIVUTLB cmd,
|
* flush Micro-TLBS. If TLB Index Reg is invalid prior to TLBIVUTLB cmd,
|
||||||
* it fails. Thus need to load it with ANY valid value before invoking
|
* it fails. Thus need to load it with ANY valid value before invoking
|
||||||
* TLBIVUTLB cmd
|
* TLBIVUTLB cmd
|
||||||
*
|
*
|
||||||
* Vineetg: Aug 21th 2008:
|
* Vineetg: Aug 21th 2008:
|
||||||
* -Reduced the duration of IRQ lockouts in TLB Flush routines
|
* -Reduced the duration of IRQ lockouts in TLB Flush routines
|
||||||
* -Multiple copies of TLB erase code seperated into a "single" function
|
* -Multiple copies of TLB erase code separated into a "single" function
|
||||||
* -In TLB Flush routines, interrupt disabling moved UP to retrieve ASID
|
* -In TLB Flush routines, interrupt disabling moved UP to retrieve ASID
|
||||||
* in interrupt-safe region.
|
* in interrupt-safe region.
|
||||||
*
|
*
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
*
|
*
|
||||||
* Although J-TLB is 2 way set assoc, ARC700 caches J-TLB into uTLBS which has
|
* Although J-TLB is 2 way set assoc, ARC700 caches J-TLB into uTLBS which has
|
||||||
* much higher associativity. u-D-TLB is 8 ways, u-I-TLB is 4 ways.
|
* much higher associativity. u-D-TLB is 8 ways, u-I-TLB is 4 ways.
|
||||||
* Given this, the thrasing problem should never happen because once the 3
|
* Given this, the thrashing problem should never happen because once the 3
|
||||||
* J-TLB entries are created (even though 3rd will knock out one of the prev
|
* J-TLB entries are created (even though 3rd will knock out one of the prev
|
||||||
* two), the u-D-TLB and u-I-TLB will have what is required to accomplish memcpy
|
* two), the u-D-TLB and u-I-TLB will have what is required to accomplish memcpy
|
||||||
*
|
*
|
||||||
@@ -127,7 +127,7 @@ static void utlb_invalidate(void)
|
|||||||
* There was however an obscure hardware bug, where uTLB flush would
|
* There was however an obscure hardware bug, where uTLB flush would
|
||||||
* fail when a prior probe for J-TLB (both totally unrelated) would
|
* fail when a prior probe for J-TLB (both totally unrelated) would
|
||||||
* return lkup err - because the entry didn't exist in MMU.
|
* return lkup err - because the entry didn't exist in MMU.
|
||||||
* The Workround was to set Index reg with some valid value, prior to
|
* The Workaround was to set Index reg with some valid value, prior to
|
||||||
* flush. This was fixed in MMU v3
|
* flush. This was fixed in MMU v3
|
||||||
*/
|
*/
|
||||||
unsigned int idx;
|
unsigned int idx;
|
||||||
@@ -272,7 +272,7 @@ noinline void local_flush_tlb_all(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Flush the entrie MM for userland. The fastest way is to move to Next ASID
|
* Flush the entire MM for userland. The fastest way is to move to Next ASID
|
||||||
*/
|
*/
|
||||||
noinline void local_flush_tlb_mm(struct mm_struct *mm)
|
noinline void local_flush_tlb_mm(struct mm_struct *mm)
|
||||||
{
|
{
|
||||||
@@ -303,7 +303,7 @@ noinline void local_flush_tlb_mm(struct mm_struct *mm)
|
|||||||
* Difference between this and Kernel Range Flush is
|
* Difference between this and Kernel Range Flush is
|
||||||
* -Here the fastest way (if range is too large) is to move to next ASID
|
* -Here the fastest way (if range is too large) is to move to next ASID
|
||||||
* without doing any explicit Shootdown
|
* without doing any explicit Shootdown
|
||||||
* -In case of kernel Flush, entry has to be shot down explictly
|
* -In case of kernel Flush, entry has to be shot down explicitly
|
||||||
*/
|
*/
|
||||||
void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
||||||
unsigned long end)
|
unsigned long end)
|
||||||
@@ -620,7 +620,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
|
|||||||
* Super Page size is configurable in hardware (4K to 16M), but fixed once
|
* Super Page size is configurable in hardware (4K to 16M), but fixed once
|
||||||
* RTL builds.
|
* RTL builds.
|
||||||
*
|
*
|
||||||
* The exact THP size a Linx configuration will support is a function of:
|
* The exact THP size a Linux configuration will support is a function of:
|
||||||
* - MMU page size (typical 8K, RTL fixed)
|
* - MMU page size (typical 8K, RTL fixed)
|
||||||
* - software page walker address split between PGD:PTE:PFN (typical
|
* - software page walker address split between PGD:PTE:PFN (typical
|
||||||
* 11:8:13, but can be changed with 1 line)
|
* 11:8:13, but can be changed with 1 line)
|
||||||
@@ -698,7 +698,7 @@ void local_flush_pmd_tlb_range(struct vm_area_struct *vma, unsigned long start,
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Read the Cache Build Confuration Registers, Decode them and save into
|
/* Read the Cache Build Configuration Registers, Decode them and save into
|
||||||
* the cpuinfo structure for later use.
|
* the cpuinfo structure for later use.
|
||||||
* No Validation is done here, simply read/convert the BCRs
|
* No Validation is done here, simply read/convert the BCRs
|
||||||
*/
|
*/
|
||||||
@@ -803,13 +803,13 @@ void arc_mmu_init(void)
|
|||||||
pr_info("%s", arc_mmu_mumbojumbo(0, str, sizeof(str)));
|
pr_info("%s", arc_mmu_mumbojumbo(0, str, sizeof(str)));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Can't be done in processor.h due to header include depenedencies
|
* Can't be done in processor.h due to header include dependencies
|
||||||
*/
|
*/
|
||||||
BUILD_BUG_ON(!IS_ALIGNED((CONFIG_ARC_KVADDR_SIZE << 20), PMD_SIZE));
|
BUILD_BUG_ON(!IS_ALIGNED((CONFIG_ARC_KVADDR_SIZE << 20), PMD_SIZE));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* stack top size sanity check,
|
* stack top size sanity check,
|
||||||
* Can't be done in processor.h due to header include depenedencies
|
* Can't be done in processor.h due to header include dependencies
|
||||||
*/
|
*/
|
||||||
BUILD_BUG_ON(!IS_ALIGNED(STACK_TOP, PMD_SIZE));
|
BUILD_BUG_ON(!IS_ALIGNED(STACK_TOP, PMD_SIZE));
|
||||||
|
|
||||||
@@ -881,7 +881,7 @@ void arc_mmu_init(void)
|
|||||||
* the duplicate one.
|
* the duplicate one.
|
||||||
* -Knob to be verbose abt it.(TODO: hook them up to debugfs)
|
* -Knob to be verbose abt it.(TODO: hook them up to debugfs)
|
||||||
*/
|
*/
|
||||||
volatile int dup_pd_silent; /* Be slient abt it or complain (default) */
|
volatile int dup_pd_silent; /* Be silent abt it or complain (default) */
|
||||||
|
|
||||||
void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
|
void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
@@ -948,7 +948,7 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address,
|
|||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Diagnostic Routines
|
* Diagnostic Routines
|
||||||
* -Called from Low Level TLB Hanlders if things don;t look good
|
* -Called from Low Level TLB Handlers if things don;t look good
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
|
|
||||||
#ifdef CONFIG_ARC_DBG_TLB_PARANOIA
|
#ifdef CONFIG_ARC_DBG_TLB_PARANOIA
|
||||||
|
|||||||
@@ -53,11 +53,11 @@ int main(void)
|
|||||||
/* stack_frame offsets */
|
/* stack_frame offsets */
|
||||||
OFFSET(__SF_BACKCHAIN, stack_frame, back_chain);
|
OFFSET(__SF_BACKCHAIN, stack_frame, back_chain);
|
||||||
OFFSET(__SF_GPRS, stack_frame, gprs);
|
OFFSET(__SF_GPRS, stack_frame, gprs);
|
||||||
OFFSET(__SF_EMPTY, stack_frame, empty1);
|
OFFSET(__SF_EMPTY, stack_frame, empty1[0]);
|
||||||
OFFSET(__SF_SIE_CONTROL, stack_frame, empty1[0]);
|
OFFSET(__SF_SIE_CONTROL, stack_frame, empty1[1]);
|
||||||
OFFSET(__SF_SIE_SAVEAREA, stack_frame, empty1[1]);
|
OFFSET(__SF_SIE_SAVEAREA, stack_frame, empty1[2]);
|
||||||
OFFSET(__SF_SIE_REASON, stack_frame, empty1[2]);
|
OFFSET(__SF_SIE_REASON, stack_frame, empty1[3]);
|
||||||
OFFSET(__SF_SIE_FLAGS, stack_frame, empty1[3]);
|
OFFSET(__SF_SIE_FLAGS, stack_frame, empty1[4]);
|
||||||
BLANK();
|
BLANK();
|
||||||
OFFSET(__VDSO_GETCPU_VAL, vdso_per_cpu_data, getcpu_val);
|
OFFSET(__VDSO_GETCPU_VAL, vdso_per_cpu_data, getcpu_val);
|
||||||
BLANK();
|
BLANK();
|
||||||
|
|||||||
@@ -1068,6 +1068,7 @@ EXPORT_SYMBOL(save_fpu_regs)
|
|||||||
* %r4
|
* %r4
|
||||||
*/
|
*/
|
||||||
load_fpu_regs:
|
load_fpu_regs:
|
||||||
|
stnsm __SF_EMPTY(%r15),0xfc
|
||||||
lg %r4,__LC_CURRENT
|
lg %r4,__LC_CURRENT
|
||||||
aghi %r4,__TASK_thread
|
aghi %r4,__TASK_thread
|
||||||
TSTMSK __LC_CPU_FLAGS,_CIF_FPU
|
TSTMSK __LC_CPU_FLAGS,_CIF_FPU
|
||||||
@@ -1099,6 +1100,7 @@ load_fpu_regs:
|
|||||||
.Lload_fpu_regs_done:
|
.Lload_fpu_regs_done:
|
||||||
ni __LC_CPU_FLAGS+7,255-_CIF_FPU
|
ni __LC_CPU_FLAGS+7,255-_CIF_FPU
|
||||||
.Lload_fpu_regs_exit:
|
.Lload_fpu_regs_exit:
|
||||||
|
ssm __SF_EMPTY(%r15)
|
||||||
BR_EX %r14
|
BR_EX %r14
|
||||||
.Lload_fpu_regs_end:
|
.Lload_fpu_regs_end:
|
||||||
ENDPROC(load_fpu_regs)
|
ENDPROC(load_fpu_regs)
|
||||||
|
|||||||
@@ -253,17 +253,31 @@ config VIDEO_MEDIATEK_VCODEC
|
|||||||
depends on MTK_IOMMU || COMPILE_TEST
|
depends on MTK_IOMMU || COMPILE_TEST
|
||||||
depends on VIDEO_DEV && VIDEO_V4L2
|
depends on VIDEO_DEV && VIDEO_V4L2
|
||||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||||
|
depends on VIDEO_MEDIATEK_VPU || MTK_SCP
|
||||||
|
# The two following lines ensure we have the same state ("m" or "y") as
|
||||||
|
# our dependencies, to avoid missing symbols during link.
|
||||||
|
depends on VIDEO_MEDIATEK_VPU || !VIDEO_MEDIATEK_VPU
|
||||||
|
depends on MTK_SCP || !MTK_SCP
|
||||||
select VIDEOBUF2_DMA_CONTIG
|
select VIDEOBUF2_DMA_CONTIG
|
||||||
select V4L2_MEM2MEM_DEV
|
select V4L2_MEM2MEM_DEV
|
||||||
select VIDEO_MEDIATEK_VPU
|
select VIDEO_MEDIATEK_VCODEC_VPU if VIDEO_MEDIATEK_VPU
|
||||||
select MTK_SCP
|
select VIDEO_MEDIATEK_VCODEC_SCP if MTK_SCP
|
||||||
help
|
help
|
||||||
Mediatek video codec driver provides HW capability to
|
Mediatek video codec driver provides HW capability to
|
||||||
encode and decode in a range of video formats
|
encode and decode in a range of video formats on MT8173
|
||||||
This driver rely on VPU driver to communicate with VPU.
|
and MT8183.
|
||||||
|
|
||||||
To compile this driver as modules, choose M here: the
|
Note that support for MT8173 requires VIDEO_MEDIATEK_VPU to
|
||||||
modules will be called mtk-vcodec-dec and mtk-vcodec-enc.
|
also be selected. Support for MT8183 depends on MTK_SCP.
|
||||||
|
|
||||||
|
To compile this driver as modules, choose M here: the
|
||||||
|
modules will be called mtk-vcodec-dec and mtk-vcodec-enc.
|
||||||
|
|
||||||
|
config VIDEO_MEDIATEK_VCODEC_VPU
|
||||||
|
bool
|
||||||
|
|
||||||
|
config VIDEO_MEDIATEK_VCODEC_SCP
|
||||||
|
bool
|
||||||
|
|
||||||
config VIDEO_MEM2MEM_DEINTERLACE
|
config VIDEO_MEM2MEM_DEINTERLACE
|
||||||
tristate "Deinterlace support"
|
tristate "Deinterlace support"
|
||||||
|
|||||||
@@ -307,6 +307,7 @@ static int mmpcam_platform_remove(struct platform_device *pdev)
|
|||||||
* Suspend/resume support.
|
* Suspend/resume support.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef CONFIG_PM
|
||||||
static int mmpcam_runtime_resume(struct device *dev)
|
static int mmpcam_runtime_resume(struct device *dev)
|
||||||
{
|
{
|
||||||
struct mmp_camera *cam = dev_get_drvdata(dev);
|
struct mmp_camera *cam = dev_get_drvdata(dev);
|
||||||
@@ -352,6 +353,7 @@ static int __maybe_unused mmpcam_resume(struct device *dev)
|
|||||||
return mccic_resume(&cam->mcam);
|
return mccic_resume(&cam->mcam);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static const struct dev_pm_ops mmpcam_pm_ops = {
|
static const struct dev_pm_ops mmpcam_pm_ops = {
|
||||||
SET_RUNTIME_PM_OPS(mmpcam_runtime_suspend, mmpcam_runtime_resume, NULL)
|
SET_RUNTIME_PM_OPS(mmpcam_runtime_suspend, mmpcam_runtime_resume, NULL)
|
||||||
|
|||||||
@@ -24,4 +24,12 @@ mtk-vcodec-enc-y := venc/venc_vp8_if.o \
|
|||||||
|
|
||||||
mtk-vcodec-common-y := mtk_vcodec_intr.o \
|
mtk-vcodec-common-y := mtk_vcodec_intr.o \
|
||||||
mtk_vcodec_util.o \
|
mtk_vcodec_util.o \
|
||||||
mtk_vcodec_fw.o
|
mtk_vcodec_fw.o \
|
||||||
|
|
||||||
|
ifneq ($(CONFIG_VIDEO_MEDIATEK_VCODEC_VPU),)
|
||||||
|
mtk-vcodec-common-y += mtk_vcodec_fw_vpu.o
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(CONFIG_VIDEO_MEDIATEK_VCODEC_SCP),)
|
||||||
|
mtk-vcodec-common-y += mtk_vcodec_fw_scp.o
|
||||||
|
endif
|
||||||
|
|||||||
@@ -241,7 +241,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
|
dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
|
||||||
|
|
||||||
dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, VPU_RST_DEC);
|
dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, DECODER);
|
||||||
if (IS_ERR(dev->fw_handler))
|
if (IS_ERR(dev->fw_handler))
|
||||||
return PTR_ERR(dev->fw_handler);
|
return PTR_ERR(dev->fw_handler);
|
||||||
|
|
||||||
|
|||||||
@@ -293,7 +293,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
|
|||||||
}
|
}
|
||||||
dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
|
dma_set_max_seg_size(&pdev->dev, DMA_BIT_MASK(32));
|
||||||
|
|
||||||
dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, VPU_RST_ENC);
|
dev->fw_handler = mtk_vcodec_fw_select(dev, fw_type, ENCODER);
|
||||||
if (IS_ERR(dev->fw_handler))
|
if (IS_ERR(dev->fw_handler))
|
||||||
return PTR_ERR(dev->fw_handler);
|
return PTR_ERR(dev->fw_handler);
|
||||||
|
|
||||||
|
|||||||
@@ -1,193 +1,29 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
#include "mtk_vcodec_fw.h"
|
#include "mtk_vcodec_fw.h"
|
||||||
|
#include "mtk_vcodec_fw_priv.h"
|
||||||
#include "mtk_vcodec_util.h"
|
#include "mtk_vcodec_util.h"
|
||||||
#include "mtk_vcodec_drv.h"
|
#include "mtk_vcodec_drv.h"
|
||||||
|
|
||||||
struct mtk_vcodec_fw_ops {
|
|
||||||
int (*load_firmware)(struct mtk_vcodec_fw *fw);
|
|
||||||
unsigned int (*get_vdec_capa)(struct mtk_vcodec_fw *fw);
|
|
||||||
unsigned int (*get_venc_capa)(struct mtk_vcodec_fw *fw);
|
|
||||||
void * (*map_dm_addr)(struct mtk_vcodec_fw *fw, u32 dtcm_dmem_addr);
|
|
||||||
int (*ipi_register)(struct mtk_vcodec_fw *fw, int id,
|
|
||||||
mtk_vcodec_ipi_handler handler, const char *name, void *priv);
|
|
||||||
int (*ipi_send)(struct mtk_vcodec_fw *fw, int id, void *buf,
|
|
||||||
unsigned int len, unsigned int wait);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mtk_vcodec_fw {
|
|
||||||
enum mtk_vcodec_fw_type type;
|
|
||||||
const struct mtk_vcodec_fw_ops *ops;
|
|
||||||
struct platform_device *pdev;
|
|
||||||
struct mtk_scp *scp;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int mtk_vcodec_vpu_load_firmware(struct mtk_vcodec_fw *fw)
|
|
||||||
{
|
|
||||||
return vpu_load_firmware(fw->pdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int mtk_vcodec_vpu_get_vdec_capa(struct mtk_vcodec_fw *fw)
|
|
||||||
{
|
|
||||||
return vpu_get_vdec_hw_capa(fw->pdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int mtk_vcodec_vpu_get_venc_capa(struct mtk_vcodec_fw *fw)
|
|
||||||
{
|
|
||||||
return vpu_get_venc_hw_capa(fw->pdev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *mtk_vcodec_vpu_map_dm_addr(struct mtk_vcodec_fw *fw,
|
|
||||||
u32 dtcm_dmem_addr)
|
|
||||||
{
|
|
||||||
return vpu_mapping_dm_addr(fw->pdev, dtcm_dmem_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mtk_vcodec_vpu_set_ipi_register(struct mtk_vcodec_fw *fw, int id,
|
|
||||||
mtk_vcodec_ipi_handler handler,
|
|
||||||
const char *name, void *priv)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* The handler we receive takes a void * as its first argument. We
|
|
||||||
* cannot change this because it needs to be passed down to the rproc
|
|
||||||
* subsystem when SCP is used. VPU takes a const argument, which is
|
|
||||||
* more constrained, so the conversion below is safe.
|
|
||||||
*/
|
|
||||||
ipi_handler_t handler_const = (ipi_handler_t)handler;
|
|
||||||
|
|
||||||
return vpu_ipi_register(fw->pdev, id, handler_const, name, priv);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mtk_vcodec_vpu_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf,
|
|
||||||
unsigned int len, unsigned int wait)
|
|
||||||
{
|
|
||||||
return vpu_ipi_send(fw->pdev, id, buf, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct mtk_vcodec_fw_ops mtk_vcodec_vpu_msg = {
|
|
||||||
.load_firmware = mtk_vcodec_vpu_load_firmware,
|
|
||||||
.get_vdec_capa = mtk_vcodec_vpu_get_vdec_capa,
|
|
||||||
.get_venc_capa = mtk_vcodec_vpu_get_venc_capa,
|
|
||||||
.map_dm_addr = mtk_vcodec_vpu_map_dm_addr,
|
|
||||||
.ipi_register = mtk_vcodec_vpu_set_ipi_register,
|
|
||||||
.ipi_send = mtk_vcodec_vpu_ipi_send,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int mtk_vcodec_scp_load_firmware(struct mtk_vcodec_fw *fw)
|
|
||||||
{
|
|
||||||
return rproc_boot(scp_get_rproc(fw->scp));
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int mtk_vcodec_scp_get_vdec_capa(struct mtk_vcodec_fw *fw)
|
|
||||||
{
|
|
||||||
return scp_get_vdec_hw_capa(fw->scp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned int mtk_vcodec_scp_get_venc_capa(struct mtk_vcodec_fw *fw)
|
|
||||||
{
|
|
||||||
return scp_get_venc_hw_capa(fw->scp);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void *mtk_vcodec_vpu_scp_dm_addr(struct mtk_vcodec_fw *fw,
|
|
||||||
u32 dtcm_dmem_addr)
|
|
||||||
{
|
|
||||||
return scp_mapping_dm_addr(fw->scp, dtcm_dmem_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mtk_vcodec_scp_set_ipi_register(struct mtk_vcodec_fw *fw, int id,
|
|
||||||
mtk_vcodec_ipi_handler handler,
|
|
||||||
const char *name, void *priv)
|
|
||||||
{
|
|
||||||
return scp_ipi_register(fw->scp, id, handler, priv);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mtk_vcodec_scp_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf,
|
|
||||||
unsigned int len, unsigned int wait)
|
|
||||||
{
|
|
||||||
return scp_ipi_send(fw->scp, id, buf, len, wait);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct mtk_vcodec_fw_ops mtk_vcodec_rproc_msg = {
|
|
||||||
.load_firmware = mtk_vcodec_scp_load_firmware,
|
|
||||||
.get_vdec_capa = mtk_vcodec_scp_get_vdec_capa,
|
|
||||||
.get_venc_capa = mtk_vcodec_scp_get_venc_capa,
|
|
||||||
.map_dm_addr = mtk_vcodec_vpu_scp_dm_addr,
|
|
||||||
.ipi_register = mtk_vcodec_scp_set_ipi_register,
|
|
||||||
.ipi_send = mtk_vcodec_scp_ipi_send,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void mtk_vcodec_reset_handler(void *priv)
|
|
||||||
{
|
|
||||||
struct mtk_vcodec_dev *dev = priv;
|
|
||||||
struct mtk_vcodec_ctx *ctx;
|
|
||||||
|
|
||||||
mtk_v4l2_err("Watchdog timeout!!");
|
|
||||||
|
|
||||||
mutex_lock(&dev->dev_mutex);
|
|
||||||
list_for_each_entry(ctx, &dev->ctx_list, list) {
|
|
||||||
ctx->state = MTK_STATE_ABORT;
|
|
||||||
mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ABORT",
|
|
||||||
ctx->id);
|
|
||||||
}
|
|
||||||
mutex_unlock(&dev->dev_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct mtk_vcodec_fw *mtk_vcodec_fw_select(struct mtk_vcodec_dev *dev,
|
struct mtk_vcodec_fw *mtk_vcodec_fw_select(struct mtk_vcodec_dev *dev,
|
||||||
enum mtk_vcodec_fw_type type,
|
enum mtk_vcodec_fw_type type,
|
||||||
enum rst_id rst_id)
|
enum mtk_vcodec_fw_use fw_use)
|
||||||
{
|
{
|
||||||
const struct mtk_vcodec_fw_ops *ops;
|
|
||||||
struct mtk_vcodec_fw *fw;
|
|
||||||
struct platform_device *fw_pdev = NULL;
|
|
||||||
struct mtk_scp *scp = NULL;
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case VPU:
|
case VPU:
|
||||||
ops = &mtk_vcodec_vpu_msg;
|
return mtk_vcodec_fw_vpu_init(dev, fw_use);
|
||||||
fw_pdev = vpu_get_plat_device(dev->plat_dev);
|
|
||||||
if (!fw_pdev) {
|
|
||||||
mtk_v4l2_err("firmware device is not ready");
|
|
||||||
return ERR_PTR(-EINVAL);
|
|
||||||
}
|
|
||||||
vpu_wdt_reg_handler(fw_pdev, mtk_vcodec_reset_handler,
|
|
||||||
dev, rst_id);
|
|
||||||
break;
|
|
||||||
case SCP:
|
case SCP:
|
||||||
ops = &mtk_vcodec_rproc_msg;
|
return mtk_vcodec_fw_scp_init(dev);
|
||||||
scp = scp_get(dev->plat_dev);
|
|
||||||
if (!scp) {
|
|
||||||
mtk_v4l2_err("could not get vdec scp handle");
|
|
||||||
return ERR_PTR(-EPROBE_DEFER);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
mtk_v4l2_err("invalid vcodec fw type");
|
mtk_v4l2_err("invalid vcodec fw type");
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL);
|
|
||||||
if (!fw)
|
|
||||||
return ERR_PTR(-EINVAL);
|
|
||||||
|
|
||||||
fw->type = type;
|
|
||||||
fw->ops = ops;
|
|
||||||
fw->pdev = fw_pdev;
|
|
||||||
fw->scp = scp;
|
|
||||||
|
|
||||||
return fw;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mtk_vcodec_fw_select);
|
EXPORT_SYMBOL_GPL(mtk_vcodec_fw_select);
|
||||||
|
|
||||||
void mtk_vcodec_fw_release(struct mtk_vcodec_fw *fw)
|
void mtk_vcodec_fw_release(struct mtk_vcodec_fw *fw)
|
||||||
{
|
{
|
||||||
switch (fw->type) {
|
fw->ops->release(fw);
|
||||||
case VPU:
|
|
||||||
put_device(&fw->pdev->dev);
|
|
||||||
break;
|
|
||||||
case SCP:
|
|
||||||
scp_put(fw->scp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mtk_vcodec_fw_release);
|
EXPORT_SYMBOL_GPL(mtk_vcodec_fw_release);
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,11 @@ enum mtk_vcodec_fw_type {
|
|||||||
SCP,
|
SCP,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum mtk_vcodec_fw_use {
|
||||||
|
DECODER,
|
||||||
|
ENCODER,
|
||||||
|
};
|
||||||
|
|
||||||
struct mtk_vcodec_fw;
|
struct mtk_vcodec_fw;
|
||||||
|
|
||||||
typedef void (*mtk_vcodec_ipi_handler) (void *data,
|
typedef void (*mtk_vcodec_ipi_handler) (void *data,
|
||||||
@@ -22,7 +27,7 @@ typedef void (*mtk_vcodec_ipi_handler) (void *data,
|
|||||||
|
|
||||||
struct mtk_vcodec_fw *mtk_vcodec_fw_select(struct mtk_vcodec_dev *dev,
|
struct mtk_vcodec_fw *mtk_vcodec_fw_select(struct mtk_vcodec_dev *dev,
|
||||||
enum mtk_vcodec_fw_type type,
|
enum mtk_vcodec_fw_type type,
|
||||||
enum rst_id rst_id);
|
enum mtk_vcodec_fw_use fw_use);
|
||||||
void mtk_vcodec_fw_release(struct mtk_vcodec_fw *fw);
|
void mtk_vcodec_fw_release(struct mtk_vcodec_fw *fw);
|
||||||
|
|
||||||
int mtk_vcodec_fw_load_firmware(struct mtk_vcodec_fw *fw);
|
int mtk_vcodec_fw_load_firmware(struct mtk_vcodec_fw *fw);
|
||||||
|
|||||||
52
drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_priv.h
Normal file
52
drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_priv.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/* SPDX-License-Identifier: GPL-2.0 */
|
||||||
|
|
||||||
|
#ifndef _MTK_VCODEC_FW_PRIV_H_
|
||||||
|
#define _MTK_VCODEC_FW_PRIV_H_
|
||||||
|
|
||||||
|
#include "mtk_vcodec_fw.h"
|
||||||
|
|
||||||
|
struct mtk_vcodec_dev;
|
||||||
|
|
||||||
|
struct mtk_vcodec_fw {
|
||||||
|
enum mtk_vcodec_fw_type type;
|
||||||
|
const struct mtk_vcodec_fw_ops *ops;
|
||||||
|
struct platform_device *pdev;
|
||||||
|
struct mtk_scp *scp;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mtk_vcodec_fw_ops {
|
||||||
|
int (*load_firmware)(struct mtk_vcodec_fw *fw);
|
||||||
|
unsigned int (*get_vdec_capa)(struct mtk_vcodec_fw *fw);
|
||||||
|
unsigned int (*get_venc_capa)(struct mtk_vcodec_fw *fw);
|
||||||
|
void *(*map_dm_addr)(struct mtk_vcodec_fw *fw, u32 dtcm_dmem_addr);
|
||||||
|
int (*ipi_register)(struct mtk_vcodec_fw *fw, int id,
|
||||||
|
mtk_vcodec_ipi_handler handler, const char *name,
|
||||||
|
void *priv);
|
||||||
|
int (*ipi_send)(struct mtk_vcodec_fw *fw, int id, void *buf,
|
||||||
|
unsigned int len, unsigned int wait);
|
||||||
|
void (*release)(struct mtk_vcodec_fw *fw);
|
||||||
|
};
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCODEC_VPU)
|
||||||
|
struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev,
|
||||||
|
enum mtk_vcodec_fw_use fw_use);
|
||||||
|
#else
|
||||||
|
static inline struct mtk_vcodec_fw *
|
||||||
|
mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev,
|
||||||
|
enum mtk_vcodec_fw_use fw_use)
|
||||||
|
{
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_VIDEO_MEDIATEK_VCODEC_VPU */
|
||||||
|
|
||||||
|
#if IS_ENABLED(CONFIG_VIDEO_MEDIATEK_VCODEC_SCP)
|
||||||
|
struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev);
|
||||||
|
#else
|
||||||
|
static inline struct mtk_vcodec_fw *
|
||||||
|
mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev)
|
||||||
|
{
|
||||||
|
return ERR_PTR(-ENODEV);
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_VIDEO_MEDIATEK_VCODEC_SCP */
|
||||||
|
|
||||||
|
#endif /* _MTK_VCODEC_FW_PRIV_H_ */
|
||||||
73
drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c
Normal file
73
drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_scp.c
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
#include "mtk_vcodec_fw_priv.h"
|
||||||
|
#include "mtk_vcodec_util.h"
|
||||||
|
#include "mtk_vcodec_drv.h"
|
||||||
|
|
||||||
|
static int mtk_vcodec_scp_load_firmware(struct mtk_vcodec_fw *fw)
|
||||||
|
{
|
||||||
|
return rproc_boot(scp_get_rproc(fw->scp));
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int mtk_vcodec_scp_get_vdec_capa(struct mtk_vcodec_fw *fw)
|
||||||
|
{
|
||||||
|
return scp_get_vdec_hw_capa(fw->scp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int mtk_vcodec_scp_get_venc_capa(struct mtk_vcodec_fw *fw)
|
||||||
|
{
|
||||||
|
return scp_get_venc_hw_capa(fw->scp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *mtk_vcodec_vpu_scp_dm_addr(struct mtk_vcodec_fw *fw,
|
||||||
|
u32 dtcm_dmem_addr)
|
||||||
|
{
|
||||||
|
return scp_mapping_dm_addr(fw->scp, dtcm_dmem_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mtk_vcodec_scp_set_ipi_register(struct mtk_vcodec_fw *fw, int id,
|
||||||
|
mtk_vcodec_ipi_handler handler,
|
||||||
|
const char *name, void *priv)
|
||||||
|
{
|
||||||
|
return scp_ipi_register(fw->scp, id, handler, priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mtk_vcodec_scp_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf,
|
||||||
|
unsigned int len, unsigned int wait)
|
||||||
|
{
|
||||||
|
return scp_ipi_send(fw->scp, id, buf, len, wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mtk_vcodec_scp_release(struct mtk_vcodec_fw *fw)
|
||||||
|
{
|
||||||
|
scp_put(fw->scp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mtk_vcodec_fw_ops mtk_vcodec_rproc_msg = {
|
||||||
|
.load_firmware = mtk_vcodec_scp_load_firmware,
|
||||||
|
.get_vdec_capa = mtk_vcodec_scp_get_vdec_capa,
|
||||||
|
.get_venc_capa = mtk_vcodec_scp_get_venc_capa,
|
||||||
|
.map_dm_addr = mtk_vcodec_vpu_scp_dm_addr,
|
||||||
|
.ipi_register = mtk_vcodec_scp_set_ipi_register,
|
||||||
|
.ipi_send = mtk_vcodec_scp_ipi_send,
|
||||||
|
.release = mtk_vcodec_scp_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mtk_vcodec_fw *mtk_vcodec_fw_scp_init(struct mtk_vcodec_dev *dev)
|
||||||
|
{
|
||||||
|
struct mtk_vcodec_fw *fw;
|
||||||
|
struct mtk_scp *scp;
|
||||||
|
|
||||||
|
scp = scp_get(dev->plat_dev);
|
||||||
|
if (!scp) {
|
||||||
|
mtk_v4l2_err("could not get vdec scp handle");
|
||||||
|
return ERR_PTR(-EPROBE_DEFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL);
|
||||||
|
fw->type = SCP;
|
||||||
|
fw->ops = &mtk_vcodec_rproc_msg;
|
||||||
|
fw->scp = scp;
|
||||||
|
|
||||||
|
return fw;
|
||||||
|
}
|
||||||
110
drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c
Normal file
110
drivers/media/platform/mtk-vcodec/mtk_vcodec_fw_vpu.c
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
#include "mtk_vcodec_fw_priv.h"
|
||||||
|
#include "mtk_vcodec_util.h"
|
||||||
|
#include "mtk_vcodec_drv.h"
|
||||||
|
|
||||||
|
static int mtk_vcodec_vpu_load_firmware(struct mtk_vcodec_fw *fw)
|
||||||
|
{
|
||||||
|
return vpu_load_firmware(fw->pdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int mtk_vcodec_vpu_get_vdec_capa(struct mtk_vcodec_fw *fw)
|
||||||
|
{
|
||||||
|
return vpu_get_vdec_hw_capa(fw->pdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int mtk_vcodec_vpu_get_venc_capa(struct mtk_vcodec_fw *fw)
|
||||||
|
{
|
||||||
|
return vpu_get_venc_hw_capa(fw->pdev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *mtk_vcodec_vpu_map_dm_addr(struct mtk_vcodec_fw *fw,
|
||||||
|
u32 dtcm_dmem_addr)
|
||||||
|
{
|
||||||
|
return vpu_mapping_dm_addr(fw->pdev, dtcm_dmem_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mtk_vcodec_vpu_set_ipi_register(struct mtk_vcodec_fw *fw, int id,
|
||||||
|
mtk_vcodec_ipi_handler handler,
|
||||||
|
const char *name, void *priv)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The handler we receive takes a void * as its first argument. We
|
||||||
|
* cannot change this because it needs to be passed down to the rproc
|
||||||
|
* subsystem when SCP is used. VPU takes a const argument, which is
|
||||||
|
* more constrained, so the conversion below is safe.
|
||||||
|
*/
|
||||||
|
ipi_handler_t handler_const = (ipi_handler_t)handler;
|
||||||
|
|
||||||
|
return vpu_ipi_register(fw->pdev, id, handler_const, name, priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mtk_vcodec_vpu_ipi_send(struct mtk_vcodec_fw *fw, int id, void *buf,
|
||||||
|
unsigned int len, unsigned int wait)
|
||||||
|
{
|
||||||
|
return vpu_ipi_send(fw->pdev, id, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mtk_vcodec_vpu_release(struct mtk_vcodec_fw *fw)
|
||||||
|
{
|
||||||
|
put_device(&fw->pdev->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mtk_vcodec_vpu_reset_handler(void *priv)
|
||||||
|
{
|
||||||
|
struct mtk_vcodec_dev *dev = priv;
|
||||||
|
struct mtk_vcodec_ctx *ctx;
|
||||||
|
|
||||||
|
mtk_v4l2_err("Watchdog timeout!!");
|
||||||
|
|
||||||
|
mutex_lock(&dev->dev_mutex);
|
||||||
|
list_for_each_entry(ctx, &dev->ctx_list, list) {
|
||||||
|
ctx->state = MTK_STATE_ABORT;
|
||||||
|
mtk_v4l2_debug(0, "[%d] Change to state MTK_STATE_ABORT",
|
||||||
|
ctx->id);
|
||||||
|
}
|
||||||
|
mutex_unlock(&dev->dev_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mtk_vcodec_fw_ops mtk_vcodec_vpu_msg = {
|
||||||
|
.load_firmware = mtk_vcodec_vpu_load_firmware,
|
||||||
|
.get_vdec_capa = mtk_vcodec_vpu_get_vdec_capa,
|
||||||
|
.get_venc_capa = mtk_vcodec_vpu_get_venc_capa,
|
||||||
|
.map_dm_addr = mtk_vcodec_vpu_map_dm_addr,
|
||||||
|
.ipi_register = mtk_vcodec_vpu_set_ipi_register,
|
||||||
|
.ipi_send = mtk_vcodec_vpu_ipi_send,
|
||||||
|
.release = mtk_vcodec_vpu_release,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mtk_vcodec_fw *mtk_vcodec_fw_vpu_init(struct mtk_vcodec_dev *dev,
|
||||||
|
enum mtk_vcodec_fw_use fw_use)
|
||||||
|
{
|
||||||
|
struct platform_device *fw_pdev;
|
||||||
|
struct mtk_vcodec_fw *fw;
|
||||||
|
enum rst_id rst_id;
|
||||||
|
|
||||||
|
switch (fw_use) {
|
||||||
|
case ENCODER:
|
||||||
|
rst_id = VPU_RST_ENC;
|
||||||
|
break;
|
||||||
|
case DECODER:
|
||||||
|
default:
|
||||||
|
rst_id = VPU_RST_DEC;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fw_pdev = vpu_get_plat_device(dev->plat_dev);
|
||||||
|
if (!fw_pdev) {
|
||||||
|
mtk_v4l2_err("firmware device is not ready");
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
vpu_wdt_reg_handler(fw_pdev, mtk_vcodec_vpu_reset_handler, dev, rst_id);
|
||||||
|
|
||||||
|
fw = devm_kzalloc(&dev->plat_dev->dev, sizeof(*fw), GFP_KERNEL);
|
||||||
|
fw->type = VPU;
|
||||||
|
fw->ops = &mtk_vcodec_vpu_msg;
|
||||||
|
fw->pdev = fw_pdev;
|
||||||
|
|
||||||
|
return fw;
|
||||||
|
}
|
||||||
@@ -243,8 +243,19 @@ struct venc_controls {
|
|||||||
|
|
||||||
u32 header_mode;
|
u32 header_mode;
|
||||||
|
|
||||||
u32 profile;
|
struct {
|
||||||
u32 level;
|
u32 h264;
|
||||||
|
u32 mpeg4;
|
||||||
|
u32 hevc;
|
||||||
|
u32 vp8;
|
||||||
|
u32 vp9;
|
||||||
|
} profile;
|
||||||
|
struct {
|
||||||
|
u32 h264;
|
||||||
|
u32 mpeg4;
|
||||||
|
u32 hevc;
|
||||||
|
u32 vp9;
|
||||||
|
} level;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct venus_buffer {
|
struct venus_buffer {
|
||||||
|
|||||||
@@ -794,7 +794,7 @@ skip_pmdomains:
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
opp_dl_add_err:
|
opp_dl_add_err:
|
||||||
dev_pm_domain_detach(core->opp_pmdomain, true);
|
dev_pm_opp_detach_genpd(core->opp_table);
|
||||||
opp_attach_err:
|
opp_attach_err:
|
||||||
if (core->pd_dl_venus) {
|
if (core->pd_dl_venus) {
|
||||||
device_link_del(core->pd_dl_venus);
|
device_link_del(core->pd_dl_venus);
|
||||||
@@ -832,7 +832,7 @@ skip_pmdomains:
|
|||||||
if (core->opp_dl_venus)
|
if (core->opp_dl_venus)
|
||||||
device_link_del(core->opp_dl_venus);
|
device_link_del(core->opp_dl_venus);
|
||||||
|
|
||||||
dev_pm_domain_detach(core->opp_pmdomain, true);
|
dev_pm_opp_detach_genpd(core->opp_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int core_get_v4(struct device *dev)
|
static int core_get_v4(struct device *dev)
|
||||||
|
|||||||
@@ -537,6 +537,7 @@ static int venc_set_properties(struct venus_inst *inst)
|
|||||||
struct hfi_quantization quant;
|
struct hfi_quantization quant;
|
||||||
struct hfi_quantization_range quant_range;
|
struct hfi_quantization_range quant_range;
|
||||||
u32 ptype, rate_control, bitrate;
|
u32 ptype, rate_control, bitrate;
|
||||||
|
u32 profile, level;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2);
|
ret = venus_helper_set_work_mode(inst, VIDC_WORK_MODE_2);
|
||||||
@@ -684,7 +685,35 @@ static int venc_set_properties(struct venus_inst *inst)
|
|||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = venus_helper_set_profile_level(inst, ctr->profile, ctr->level);
|
switch (inst->hfi_codec) {
|
||||||
|
case HFI_VIDEO_CODEC_H264:
|
||||||
|
profile = ctr->profile.h264;
|
||||||
|
level = ctr->level.h264;
|
||||||
|
break;
|
||||||
|
case HFI_VIDEO_CODEC_MPEG4:
|
||||||
|
profile = ctr->profile.mpeg4;
|
||||||
|
level = ctr->level.mpeg4;
|
||||||
|
break;
|
||||||
|
case HFI_VIDEO_CODEC_VP8:
|
||||||
|
profile = ctr->profile.vp8;
|
||||||
|
level = 0;
|
||||||
|
break;
|
||||||
|
case HFI_VIDEO_CODEC_VP9:
|
||||||
|
profile = ctr->profile.vp9;
|
||||||
|
level = ctr->level.vp9;
|
||||||
|
break;
|
||||||
|
case HFI_VIDEO_CODEC_HEVC:
|
||||||
|
profile = ctr->profile.hevc;
|
||||||
|
level = ctr->level.hevc;
|
||||||
|
break;
|
||||||
|
case HFI_VIDEO_CODEC_MPEG2:
|
||||||
|
default:
|
||||||
|
profile = 0;
|
||||||
|
level = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = venus_helper_set_profile_level(inst, profile, level);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|||||||
@@ -103,15 +103,25 @@ static int venc_op_s_ctrl(struct v4l2_ctrl *ctrl)
|
|||||||
ctr->h264_entropy_mode = ctrl->val;
|
ctr->h264_entropy_mode = ctrl->val;
|
||||||
break;
|
break;
|
||||||
case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
|
case V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE:
|
||||||
|
ctr->profile.mpeg4 = ctrl->val;
|
||||||
|
break;
|
||||||
case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
|
case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
|
||||||
|
ctr->profile.h264 = ctrl->val;
|
||||||
|
break;
|
||||||
case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
|
case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
|
||||||
|
ctr->profile.hevc = ctrl->val;
|
||||||
|
break;
|
||||||
case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
|
case V4L2_CID_MPEG_VIDEO_VP8_PROFILE:
|
||||||
ctr->profile = ctrl->val;
|
ctr->profile.vp8 = ctrl->val;
|
||||||
break;
|
break;
|
||||||
case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
|
case V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL:
|
||||||
|
ctr->level.mpeg4 = ctrl->val;
|
||||||
|
break;
|
||||||
case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
|
case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
|
||||||
|
ctr->level.h264 = ctrl->val;
|
||||||
|
break;
|
||||||
case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
|
case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
|
||||||
ctr->level = ctrl->val;
|
ctr->level.hevc = ctrl->val;
|
||||||
break;
|
break;
|
||||||
case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
|
case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
|
||||||
ctr->h264_i_qp = ctrl->val;
|
ctr->h264_i_qp = ctrl->val;
|
||||||
|
|||||||
@@ -446,7 +446,7 @@ static void cedrus_set_params(struct cedrus_ctx *ctx,
|
|||||||
reg |= (pps->second_chroma_qp_index_offset & 0x3f) << 16;
|
reg |= (pps->second_chroma_qp_index_offset & 0x3f) << 16;
|
||||||
reg |= (pps->chroma_qp_index_offset & 0x3f) << 8;
|
reg |= (pps->chroma_qp_index_offset & 0x3f) << 8;
|
||||||
reg |= (pps->pic_init_qp_minus26 + 26 + slice->slice_qp_delta) & 0x3f;
|
reg |= (pps->pic_init_qp_minus26 + 26 + slice->slice_qp_delta) & 0x3f;
|
||||||
if (pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT)
|
if (!(pps->flags & V4L2_H264_PPS_FLAG_SCALING_MATRIX_PRESENT))
|
||||||
reg |= VE_H264_SHS_QP_SCALING_MATRIX_DEFAULT;
|
reg |= VE_H264_SHS_QP_SCALING_MATRIX_DEFAULT;
|
||||||
cedrus_write(dev, VE_H264_SHS_QP, reg);
|
cedrus_write(dev, VE_H264_SHS_QP, reg);
|
||||||
|
|
||||||
|
|||||||
@@ -1093,7 +1093,12 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info)
|
|||||||
goto err1;
|
goto err1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fb_virt = ioremap(par->mem->start, screen_fb_size);
|
/*
|
||||||
|
* Map the VRAM cacheable for performance. This is also required for
|
||||||
|
* VM Connect to display properly for ARM64 Linux VM, as the host also
|
||||||
|
* maps the VRAM cacheable.
|
||||||
|
*/
|
||||||
|
fb_virt = ioremap_cache(par->mem->start, screen_fb_size);
|
||||||
if (!fb_virt)
|
if (!fb_virt)
|
||||||
goto err2;
|
goto err2;
|
||||||
|
|
||||||
|
|||||||
@@ -1266,6 +1266,7 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
|
|||||||
cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
|
cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
|
||||||
} else if (mode_from_special_sid) {
|
} else if (mode_from_special_sid) {
|
||||||
rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
|
rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, true);
|
||||||
|
kfree(pntsd);
|
||||||
} else {
|
} else {
|
||||||
/* get approximated mode from ACL */
|
/* get approximated mode from ACL */
|
||||||
rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
|
rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr, false);
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ smb2_revert_current_mid(struct TCP_Server_Info *server, const unsigned int val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct mid_q_entry *
|
static struct mid_q_entry *
|
||||||
smb2_find_mid(struct TCP_Server_Info *server, char *buf)
|
__smb2_find_mid(struct TCP_Server_Info *server, char *buf, bool dequeue)
|
||||||
{
|
{
|
||||||
struct mid_q_entry *mid;
|
struct mid_q_entry *mid;
|
||||||
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
|
struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)buf;
|
||||||
@@ -281,6 +281,10 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf)
|
|||||||
(mid->mid_state == MID_REQUEST_SUBMITTED) &&
|
(mid->mid_state == MID_REQUEST_SUBMITTED) &&
|
||||||
(mid->command == shdr->Command)) {
|
(mid->command == shdr->Command)) {
|
||||||
kref_get(&mid->refcount);
|
kref_get(&mid->refcount);
|
||||||
|
if (dequeue) {
|
||||||
|
list_del_init(&mid->qhead);
|
||||||
|
mid->mid_flags |= MID_DELETED;
|
||||||
|
}
|
||||||
spin_unlock(&GlobalMid_Lock);
|
spin_unlock(&GlobalMid_Lock);
|
||||||
return mid;
|
return mid;
|
||||||
}
|
}
|
||||||
@@ -289,6 +293,18 @@ smb2_find_mid(struct TCP_Server_Info *server, char *buf)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct mid_q_entry *
|
||||||
|
smb2_find_mid(struct TCP_Server_Info *server, char *buf)
|
||||||
|
{
|
||||||
|
return __smb2_find_mid(server, buf, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct mid_q_entry *
|
||||||
|
smb2_find_dequeue_mid(struct TCP_Server_Info *server, char *buf)
|
||||||
|
{
|
||||||
|
return __smb2_find_mid(server, buf, true);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
|
smb2_dump_detail(void *buf, struct TCP_Server_Info *server)
|
||||||
{
|
{
|
||||||
@@ -4356,7 +4372,8 @@ init_read_bvec(struct page **pages, unsigned int npages, unsigned int data_size,
|
|||||||
static int
|
static int
|
||||||
handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
||||||
char *buf, unsigned int buf_len, struct page **pages,
|
char *buf, unsigned int buf_len, struct page **pages,
|
||||||
unsigned int npages, unsigned int page_data_size)
|
unsigned int npages, unsigned int page_data_size,
|
||||||
|
bool is_offloaded)
|
||||||
{
|
{
|
||||||
unsigned int data_offset;
|
unsigned int data_offset;
|
||||||
unsigned int data_len;
|
unsigned int data_len;
|
||||||
@@ -4378,7 +4395,8 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
|||||||
|
|
||||||
if (server->ops->is_session_expired &&
|
if (server->ops->is_session_expired &&
|
||||||
server->ops->is_session_expired(buf)) {
|
server->ops->is_session_expired(buf)) {
|
||||||
cifs_reconnect(server);
|
if (!is_offloaded)
|
||||||
|
cifs_reconnect(server);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4402,7 +4420,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
|||||||
cifs_dbg(FYI, "%s: server returned error %d\n",
|
cifs_dbg(FYI, "%s: server returned error %d\n",
|
||||||
__func__, rdata->result);
|
__func__, rdata->result);
|
||||||
/* normal error on read response */
|
/* normal error on read response */
|
||||||
dequeue_mid(mid, false);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_RECEIVED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4426,7 +4447,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
|||||||
cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
|
cifs_dbg(FYI, "%s: data offset (%u) beyond end of smallbuf\n",
|
||||||
__func__, data_offset);
|
__func__, data_offset);
|
||||||
rdata->result = -EIO;
|
rdata->result = -EIO;
|
||||||
dequeue_mid(mid, rdata->result);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_MALFORMED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, rdata->result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4442,21 +4466,30 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
|||||||
cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n",
|
cifs_dbg(FYI, "%s: data offset (%u) beyond 1st page of response\n",
|
||||||
__func__, data_offset);
|
__func__, data_offset);
|
||||||
rdata->result = -EIO;
|
rdata->result = -EIO;
|
||||||
dequeue_mid(mid, rdata->result);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_MALFORMED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, rdata->result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_len > page_data_size - pad_len) {
|
if (data_len > page_data_size - pad_len) {
|
||||||
/* data_len is corrupt -- discard frame */
|
/* data_len is corrupt -- discard frame */
|
||||||
rdata->result = -EIO;
|
rdata->result = -EIO;
|
||||||
dequeue_mid(mid, rdata->result);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_MALFORMED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, rdata->result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rdata->result = init_read_bvec(pages, npages, page_data_size,
|
rdata->result = init_read_bvec(pages, npages, page_data_size,
|
||||||
cur_off, &bvec);
|
cur_off, &bvec);
|
||||||
if (rdata->result != 0) {
|
if (rdata->result != 0) {
|
||||||
dequeue_mid(mid, rdata->result);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_MALFORMED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, rdata->result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4471,7 +4504,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
|||||||
/* read response payload cannot be in both buf and pages */
|
/* read response payload cannot be in both buf and pages */
|
||||||
WARN_ONCE(1, "buf can not contain only a part of read data");
|
WARN_ONCE(1, "buf can not contain only a part of read data");
|
||||||
rdata->result = -EIO;
|
rdata->result = -EIO;
|
||||||
dequeue_mid(mid, rdata->result);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_MALFORMED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, rdata->result);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4482,7 +4518,10 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
|
|||||||
if (length < 0)
|
if (length < 0)
|
||||||
return length;
|
return length;
|
||||||
|
|
||||||
dequeue_mid(mid, false);
|
if (is_offloaded)
|
||||||
|
mid->mid_state = MID_RESPONSE_RECEIVED;
|
||||||
|
else
|
||||||
|
dequeue_mid(mid, false);
|
||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4511,15 +4550,34 @@ static void smb2_decrypt_offload(struct work_struct *work)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dw->server->lstrp = jiffies;
|
dw->server->lstrp = jiffies;
|
||||||
mid = smb2_find_mid(dw->server, dw->buf);
|
mid = smb2_find_dequeue_mid(dw->server, dw->buf);
|
||||||
if (mid == NULL)
|
if (mid == NULL)
|
||||||
cifs_dbg(FYI, "mid not found\n");
|
cifs_dbg(FYI, "mid not found\n");
|
||||||
else {
|
else {
|
||||||
mid->decrypted = true;
|
mid->decrypted = true;
|
||||||
rc = handle_read_data(dw->server, mid, dw->buf,
|
rc = handle_read_data(dw->server, mid, dw->buf,
|
||||||
dw->server->vals->read_rsp_size,
|
dw->server->vals->read_rsp_size,
|
||||||
dw->ppages, dw->npages, dw->len);
|
dw->ppages, dw->npages, dw->len,
|
||||||
mid->callback(mid);
|
true);
|
||||||
|
if (rc >= 0) {
|
||||||
|
#ifdef CONFIG_CIFS_STATS2
|
||||||
|
mid->when_received = jiffies;
|
||||||
|
#endif
|
||||||
|
mid->callback(mid);
|
||||||
|
} else {
|
||||||
|
spin_lock(&GlobalMid_Lock);
|
||||||
|
if (dw->server->tcpStatus == CifsNeedReconnect) {
|
||||||
|
mid->mid_state = MID_RETRY_NEEDED;
|
||||||
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
mid->callback(mid);
|
||||||
|
} else {
|
||||||
|
mid->mid_state = MID_REQUEST_SUBMITTED;
|
||||||
|
mid->mid_flags &= ~(MID_DELETED);
|
||||||
|
list_add_tail(&mid->qhead,
|
||||||
|
&dw->server->pending_mid_q);
|
||||||
|
spin_unlock(&GlobalMid_Lock);
|
||||||
|
}
|
||||||
|
}
|
||||||
cifs_mid_q_entry_release(mid);
|
cifs_mid_q_entry_release(mid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4622,7 +4680,7 @@ non_offloaded_decrypt:
|
|||||||
(*mid)->decrypted = true;
|
(*mid)->decrypted = true;
|
||||||
rc = handle_read_data(server, *mid, buf,
|
rc = handle_read_data(server, *mid, buf,
|
||||||
server->vals->read_rsp_size,
|
server->vals->read_rsp_size,
|
||||||
pages, npages, len);
|
pages, npages, len, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
free_pages:
|
free_pages:
|
||||||
@@ -4765,7 +4823,7 @@ smb3_handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid)
|
|||||||
char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
|
char *buf = server->large_buf ? server->bigbuf : server->smallbuf;
|
||||||
|
|
||||||
return handle_read_data(server, mid, buf, server->pdu_size,
|
return handle_read_data(server, mid, buf, server->pdu_size,
|
||||||
NULL, 0, 0);
|
NULL, 0, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
@@ -1484,11 +1484,19 @@ void end_page_writeback(struct page *page)
|
|||||||
rotate_reclaimable_page(page);
|
rotate_reclaimable_page(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Writeback does not hold a page reference of its own, relying
|
||||||
|
* on truncation to wait for the clearing of PG_writeback.
|
||||||
|
* But here we must make sure that the page is not freed and
|
||||||
|
* reused before the wake_up_page().
|
||||||
|
*/
|
||||||
|
get_page(page);
|
||||||
if (!test_clear_page_writeback(page))
|
if (!test_clear_page_writeback(page))
|
||||||
BUG();
|
BUG();
|
||||||
|
|
||||||
smp_mb__after_atomic();
|
smp_mb__after_atomic();
|
||||||
wake_up_page(page, PG_writeback);
|
wake_up_page(page, PG_writeback);
|
||||||
|
put_page(page);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(end_page_writeback);
|
EXPORT_SYMBOL(end_page_writeback);
|
||||||
|
|
||||||
|
|||||||
@@ -2754,12 +2754,6 @@ int test_clear_page_writeback(struct page *page)
|
|||||||
} else {
|
} else {
|
||||||
ret = TestClearPageWriteback(page);
|
ret = TestClearPageWriteback(page);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
* NOTE: Page might be free now! Writeback doesn't hold a page
|
|
||||||
* reference on its own, it relies on truncation to wait for
|
|
||||||
* the clearing of PG_writeback. The below can only access
|
|
||||||
* page state that is static across allocation cycles.
|
|
||||||
*/
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dec_lruvec_state(lruvec, NR_WRITEBACK);
|
dec_lruvec_state(lruvec, NR_WRITEBACK);
|
||||||
dec_zone_page_state(page, NR_ZONE_WRITE_PENDING);
|
dec_zone_page_state(page, NR_ZONE_WRITE_PENDING);
|
||||||
|
|||||||
Reference in New Issue
Block a user