* [PATCH v3] KVM: arm/arm64: add WARN_ON if size is not PAGE_SIZE aligned in unmap_stage2_range
From: Jia He @ 2018-06-08 9:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1526871930-1231-1-git-send-email-hejianet@gmail.com>
Ping
Cheers,
Jia
On 5/21/2018 11:05 AM, Jia He Wrote:
> There is a panic in armv8a server(QDF2400) under memory pressure tests
> (start 20 guests and run memhog in the host).
>
> ---------------------------------begin--------------------------------
> [35380.800950] BUG: Bad page state in process qemu-kvm pfn:dd0b6
> [35380.805825] page:ffff7fe003742d80 count:-4871 mapcount:-2126053375
> mapping: (null) index:0x0
> [35380.815024] flags: 0x1fffc00000000000()
> [35380.818845] raw: 1fffc00000000000 0000000000000000 0000000000000000
> ffffecf981470000
> [35380.826569] raw: dead000000000100 dead000000000200 ffff8017c001c000
> 0000000000000000
> [35380.805825] page:ffff7fe003742d80 count:-4871 mapcount:-2126053375
> mapping: (null) index:0x0
> [35380.815024] flags: 0x1fffc00000000000()
> [35380.818845] raw: 1fffc00000000000 0000000000000000 0000000000000000
> ffffecf981470000
> [35380.826569] raw: dead000000000100 dead000000000200 ffff8017c001c000
> 0000000000000000
> [35380.834294] page dumped because: nonzero _refcount
> [35380.839069] Modules linked in: vhost_net vhost tap ebtable_filter
> ebtables ip6table_filter ip6_tables iptable_filter fcoe libfcoe libfc
> 8021q garp mrp stp llc scsi_transport_fc openvswitch nf_conntrack_ipv6
> nf_nat_ipv6 nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_defrag_ipv6
> nf_nat nf_conntrack vfat fat rpcrdma ib_isert iscsi_target_mod ib_iser
> libiscsi scsi_transport_iscsi ib_srpt target_core_mod ib_srp
> scsi_transport_srp ib_ipoib rdma_ucm ib_ucm ib_uverbs ib_umad rdma_cm
> ib_cm iw_cm mlx5_ib ib_core crc32_ce ipmi_ssif tpm_tis tpm_tis_core sg
> nfsd auth_rpcgss nfs_acl lockd grace sunrpc dm_multipath ip_tables xfs
> libcrc32c mlx5_core mlxfw devlink ahci_platform libahci_platform libahci
> qcom_emac sdhci_acpi sdhci hdma mmc_core hdma_mgmt i2c_qup dm_mirror
> dm_region_hash dm_log dm_mod
> [35380.908341] CPU: 29 PID: 18323 Comm: qemu-kvm Tainted: G W
> 4.14.15-5.hxt.aarch64 #1
> [35380.917107] Hardware name: <snip for confidential issues>
> [35380.930909] Call trace:
> [35380.933345] [<ffff000008088f00>] dump_backtrace+0x0/0x22c
> [35380.938723] [<ffff000008089150>] show_stack+0x24/0x2c
> [35380.943759] [<ffff00000893c078>] dump_stack+0x8c/0xb0
> [35380.948794] [<ffff00000820ab50>] bad_page+0xf4/0x154
> [35380.953740] [<ffff000008211ce8>] free_pages_check_bad+0x90/0x9c
> [35380.959642] [<ffff00000820c430>] free_pcppages_bulk+0x464/0x518
> [35380.965545] [<ffff00000820db98>] free_hot_cold_page+0x22c/0x300
> [35380.971448] [<ffff0000082176fc>] __put_page+0x54/0x60
> [35380.976484] [<ffff0000080b1164>] unmap_stage2_range+0x170/0x2b4
> [35380.982385] [<ffff0000080b12d8>] kvm_unmap_hva_handler+0x30/0x40
> [35380.988375] [<ffff0000080b0104>] handle_hva_to_gpa+0xb0/0xec
> [35380.994016] [<ffff0000080b2644>] kvm_unmap_hva_range+0x5c/0xd0
> [35380.999833] [<ffff0000080a8054>]
> kvm_mmu_notifier_invalidate_range_start+0x60/0xb0
> [35381.007387] [<ffff000008271f44>]
> __mmu_notifier_invalidate_range_start+0x64/0x8c
> [35381.014765] [<ffff0000082547c8>] try_to_unmap_one+0x78c/0x7a4
> [35381.020493] [<ffff000008276d04>] rmap_walk_ksm+0x124/0x1a0
> [35381.025961] [<ffff0000082551b4>] rmap_walk+0x94/0x98
> [35381.030909] [<ffff0000082555e4>] try_to_unmap+0x100/0x124
> [35381.036293] [<ffff00000828243c>] unmap_and_move+0x480/0x6fc
> [35381.041847] [<ffff000008282b6c>] migrate_pages+0x10c/0x288
> [35381.047318] [<ffff00000823c164>] compact_zone+0x238/0x954
> [35381.052697] [<ffff00000823c944>] compact_zone_order+0xc4/0xe8
> [35381.058427] [<ffff00000823d25c>] try_to_compact_pages+0x160/0x294
> [35381.064503] [<ffff00000820f074>]
> __alloc_pages_direct_compact+0x68/0x194
> [35381.071187] [<ffff000008210138>] __alloc_pages_nodemask+0xc20/0xf7c
> [35381.077437] [<ffff0000082709e4>] alloc_pages_vma+0x1a4/0x1c0
> [35381.083080] [<ffff000008285b68>]
> do_huge_pmd_anonymous_page+0x128/0x324
> [35381.089677] [<ffff000008248a24>] __handle_mm_fault+0x71c/0x7e8
> [35381.095492] [<ffff000008248be8>] handle_mm_fault+0xf8/0x194
> [35381.101049] [<ffff000008240dcc>] __get_user_pages+0x124/0x34c
> [35381.106777] [<ffff000008241870>] populate_vma_page_range+0x90/0x9c
> [35381.112941] [<ffff000008241940>] __mm_populate+0xc4/0x15c
> [35381.118322] [<ffff00000824b294>] SyS_mlockall+0x100/0x164
> [35381.123705] Exception stack(0xffff800dce5f3ec0 to 0xffff800dce5f4000)
> [35381.130128] 3ec0: 0000000000000003 d6e6024cc9b87e00 0000aaaabe94f000
> 0000000000000000
> [35381.137940] 3ee0: 0000000000000002 0000000000000000 0000000000000000
> 0000aaaacf6fc3c0
> [35381.145753] 3f00: 00000000000000e6 0000aaaacf6fc490 0000ffffeeeab0f0
> d6e6024cc9b87e00
> [35381.153565] 3f20: 0000000000000000 0000aaaabe81b3c0 0000000000000020
> 00009e53eff806b5
> [35381.161379] 3f40: 0000aaaabe94de48 0000ffffa7c269b0 0000000000000011
> 0000ffffeeeabf68
> [35381.169190] 3f60: 0000aaaaceacfe60 0000aaaabe94f000 0000aaaabe9ba358
> 0000aaaabe7ffb80
> [35381.177003] 3f80: 0000aaaabe9ba000 0000aaaabe959f64 0000000000000000
> 0000aaaabe94f000
> [35381.184815] 3fa0: 0000000000000000 0000ffffeeeabdb0 0000aaaabe5f3bf8
> 0000ffffeeeabdb0
> [35381.192628] 3fc0: 0000ffffa7c269b8 0000000060000000 0000000000000003
> 00000000000000e6
> [35381.200440] 3fe0: 0000000000000000 0000000000000000 0000000000000000
> 0000000000000000
> [35381.208254] [<ffff00000808339c>] __sys_trace_return+0x0/0x4
> [35381.213809] Disabling lock debugging due to kernel taint
> --------------------------------end--------------------------------------
>
> The root cause might be what I fixed at [1]. But from arm kvm points of
> view, it would be better we caught the exception earlier and clearer.
>
> If the size is not PAGE_SIZE aligned, unmap_stage2_range might unmap the
> wrong(more or less) page range. Hence it caused the "BUG: Bad page
> state"
>
> [1] https://lkml.org/lkml/2018/5/3/1042
>
> Signed-off-by: jia.he at hxt-semitech.com
> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
> v3: resend after dropping patch 2/2 of the series
>
> virt/kvm/arm/mmu.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
> index 7f6a944..8dac311 100644
> --- a/virt/kvm/arm/mmu.c
> +++ b/virt/kvm/arm/mmu.c
> @@ -297,6 +297,8 @@ static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
> phys_addr_t next;
>
> assert_spin_locked(&kvm->mmu_lock);
> + WARN_ON(size & ~PAGE_MASK);
> +
> pgd = kvm->arch.pgd + stage2_pgd_index(addr);
> do {
> /*
>
^ permalink raw reply
* [PATCH v2 2/2] media: mtk-vcodec: Support VP9 profile in decoder
From: Hans Verkuil @ 2018-06-08 9:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180530071613.125768-3-keiichiw@chromium.org>
On 05/30/2018 09:16 AM, Keiichi Watanabe wrote:
> Add V4L2_CID_MPEG_VIDEO_VP9_PROFILE control in MediaTek decoder's
> driver.
> MediaTek decoder only supports profile 0 for now.
>
> Signed-off-by: Keiichi Watanabe <keiichiw@chromium.org>
> ---
> drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
> index 86f0a7134365..f9393504356d 100644
> --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
> +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec.c
> @@ -1400,6 +1400,12 @@ int mtk_vcodec_dec_ctrls_setup(struct mtk_vcodec_ctx *ctx)
> V4L2_CID_MIN_BUFFERS_FOR_CAPTURE,
> 0, 32, 1, 1);
> ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
> + v4l2_ctrl_new_std_menu(&ctx->ctrl_hdl,
> + &mtk_vcodec_dec_ctrl_ops,
> + V4L2_CID_MPEG_VIDEO_VP9_PROFILE,
> + V4L2_MPEG_VIDEO_VP9_PROFILE_3,
It makes no sense to set max to PROFILE_3 if PROFILE_0 is the only choice.
Just set max to PROFILE_0 as well.
> + ~(1U << V4L2_MPEG_VIDEO_VP9_PROFILE_0),
> + V4L2_MPEG_VIDEO_VP9_PROFILE_0);
>
> if (ctx->ctrl_hdl.error) {
> mtk_v4l2_err("Adding control failed %d",
> --
> 2.17.0.921.gf22659ad46-goog
>
Regards,
Hans
^ permalink raw reply
* [PATCH v4 05/14] coresight: get/put module in coresight_build/release_path
From: Suzuki K Poulose @ 2018-06-08 9:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180607164747.7e4bb30f69a1fb4c160b6ef1@arm.com>
On 06/07/2018 10:47 PM, Kim Phillips wrote:
> On Thu, 7 Jun 2018 22:10:07 +0100
> Suzuki K Poulose <suzuki.poulose@arm.com> wrote:
>
>> On 06/07/2018 06:13 PM, Kim Phillips wrote:
>>> I'm going to assume the series is still valid after this discussion,
>>> since technically just this patch can get dropped, and the user is able
>>> to shoot themselves in the foot.
>>
>> That doesn't mean the kernel can panic() if the user decided to unload
>> the module while the trace session is in progress. It only means that
>> the trace session could be stopped in between in the worst case. But
>> nothing more harmful to the system.
Kim,
>
> FWIW, I didn't see the kernel panic in my basic tests; just some bad
> accesses: the new remove functions take care of cleaning up most items,
> and most drivers still depend on the links and sinks (funnel,
> replicator) drivers, so they can't be upset too bad.
Bad accesses are still bad. The bad access could trigger an Oops for
e.g, or could even corrupt the other parts of the kernel if we try
to access a memory that is free'd (and reallocated to somebody else).
So, the point is there are issues with the series which we know for
sure from code analysis. It may take different forms to show up at
runtime.
>
>>> This series is for development purposes, after all.
>>
>> Do you mean that this series is for internal development purposes and
>> not upstream ? Making the drivers modular are always helpful, especially
>
> no, I'm posting them for upstream review because I'd like them upstream.
>
>> for something related to tracing, that allows the module to be unloaded
>> after use. So, it would be good to have this series in, but in a manner
>> which is usable and doesn't cause harm to the overall system usage.
>>
>> I think the summary of the discussion is that we need more robust code
>> to handle the situation, which also allows unloading the modules without
>> any trouble.
>
> Trouble's relative. My point was since the series is going to be used
> mainly by developers testing their code, they already prepare for, and
> expect badness to occur anyway. Greg's point isn't lost here, and in
Making something modular is not really just for the use of developers.
There are and will be other users for a device driver as a module and
it is a fundamental feature people expect (especially in the enterprise
world, where there is one kernel which builds most of the stuff as
module to let the users pick the individual drivers as they need).
So, at the kernel driver you can't really be sure, if the user is
actually aware of the "developer" only mode and he knows that we can
crash the kernel.
> my interpretation, his review of this patch was that it was in the
> wrong direction of safety: it made things unnecessarily too safe, up
> front, and that items relative to the perf core should strive to adhere
One of the areas of improvement towards the "modern" behavior is failing
the activation of the trace schedule, when a component in the path has
been removed when we go through coresight_enable_path(). Right now, we
create a path and then we do enable_path() and disable_path() around the
trace schedules and the path is destroyed only at pmu->free_aux(). With
the current patch, we hold the reference to the device/driver throughout
the duration of the life time of the tracing, even when the tracing
may be disabled in between.
I think, if we get to that point, we should be at the best we can reach
towards the expected behavior. But having said that, it is indeed tricky
to get that. May be we could play a little bit with the refcounting on
csdev and check if the refcount is only held by the number of paths this
component is part of (needs more thought).
Suzuki
^ permalink raw reply
* [PATCH] net: thunderx: prevent concurrent data re-writing by nicvf_set_rx_mode
From: Vadim Lomovtsev @ 2018-06-08 9:27 UTC (permalink / raw)
To: linux-arm-kernel
From: Vadim Lomovtsev <Vadim.Lomovtsev@cavium.com>
For each network interface linux network stack issue ndo_set_rx_mode call
in order to configure MAC address filters (e.g. for multicast filtering).
Currently ThunderX NICVF driver has only one ordered workqueue to process
such requests for all VFs.
And because of that it is possible that subsequent call to
ndo_set_rx_mode would corrupt data which is currently in use
by nicvf_set_rx_mode_task. Which in turn could cause following issue:
[...]
[ 48.978341] Unable to handle kernel paging request at virtual address 1fffff0000000000
[ 48.986275] Mem abort info:
[ 48.989058] Exception class = DABT (current EL), IL = 32 bits
[ 48.994965] SET = 0, FnV = 0
[ 48.998020] EA = 0, S1PTW = 0
[ 49.001152] Data abort info:
[ 49.004022] ISV = 0, ISS = 0x00000004
[ 49.007869] CM = 0, WnR = 0
[ 49.010826] [1fffff0000000000] address between user and kernel address ranges
[ 49.017963] Internal error: Oops: 96000004 [#1] SMP
[...]
[ 49.072138] task: ffff800fdd675400 task.stack: ffff000026440000
[ 49.078051] PC is at prefetch_freepointer.isra.37+0x28/0x3c
[ 49.083613] LR is at kmem_cache_alloc_trace+0xc8/0x1fc
[...]
[ 49.272684] [<ffff0000082738f0>] prefetch_freepointer.isra.37+0x28/0x3c
[ 49.279286] [<ffff000008276bc8>] kmem_cache_alloc_trace+0xc8/0x1fc
[ 49.285455] [<ffff0000082c0c0c>] alloc_fdtable+0x78/0x134
[ 49.290841] [<ffff0000082c15c0>] dup_fd+0x254/0x2f4
[ 49.295709] [<ffff0000080d1954>] copy_process.isra.38.part.39+0x64c/0x1168
[ 49.302572] [<ffff0000080d264c>] _do_fork+0xfc/0x3b0
[ 49.307524] [<ffff0000080d29e8>] SyS_clone+0x44/0x50
[...]
This patch is to prevent such concurrent data write with spinlock.
Reported-by: Dean Nelson <dnelson@redhat.com>
Signed-off-by: Vadim Lomovtsev <Vadim.Lomovtsev@cavium.com>
---
drivers/net/ethernet/cavium/thunder/nic.h | 2 +
drivers/net/ethernet/cavium/thunder/nicvf_main.c | 50 +++++++++++++++++-------
2 files changed, 38 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h
index 448d1fafc827..f4d81765221e 100644
--- a/drivers/net/ethernet/cavium/thunder/nic.h
+++ b/drivers/net/ethernet/cavium/thunder/nic.h
@@ -325,6 +325,8 @@ struct nicvf {
struct tasklet_struct qs_err_task;
struct work_struct reset_task;
struct nicvf_work rx_mode_work;
+ /* spinlock to protect workqueue arguments from concurrent access */
+ spinlock_t rx_mode_wq_lock;
/* PTP timestamp */
struct cavium_ptp *ptp_clock;
diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
index 7135db45927e..135766c4296b 100644
--- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c
+++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c
@@ -1923,17 +1923,12 @@ static int nicvf_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
}
}
-static void nicvf_set_rx_mode_task(struct work_struct *work_arg)
+static void __nicvf_set_rx_mode_task(u8 mode, struct xcast_addr_list *mc_addrs,
+ struct nicvf *nic)
{
- struct nicvf_work *vf_work = container_of(work_arg, struct nicvf_work,
- work.work);
- struct nicvf *nic = container_of(vf_work, struct nicvf, rx_mode_work);
union nic_mbx mbx = {};
int idx;
- if (!vf_work)
- return;
-
/* From the inside of VM code flow we have only 128 bits memory
* available to send message to host's PF, so send all mc addrs
* one by one, starting from flush command in case if kernel
@@ -1944,7 +1939,7 @@ static void nicvf_set_rx_mode_task(struct work_struct *work_arg)
mbx.xcast.msg = NIC_MBOX_MSG_RESET_XCAST;
nicvf_send_msg_to_pf(nic, &mbx);
- if (vf_work->mode & BGX_XCAST_MCAST_FILTER) {
+ if (mode & BGX_XCAST_MCAST_FILTER) {
/* once enabling filtering, we need to signal to PF to add
* its' own LMAC to the filter to accept packets for it.
*/
@@ -1954,23 +1949,46 @@ static void nicvf_set_rx_mode_task(struct work_struct *work_arg)
}
/* check if we have any specific MACs to be added to PF DMAC filter */
- if (vf_work->mc) {
+ if (mc_addrs) {
/* now go through kernel list of MACs and add them one by one */
- for (idx = 0; idx < vf_work->mc->count; idx++) {
+ for (idx = 0; idx < mc_addrs->count; idx++) {
mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST;
- mbx.xcast.data.mac = vf_work->mc->mc[idx];
+ mbx.xcast.data.mac = mc_addrs->mc[idx];
nicvf_send_msg_to_pf(nic, &mbx);
}
- kfree(vf_work->mc);
+ kfree(mc_addrs);
}
/* and finally set rx mode for PF accordingly */
mbx.xcast.msg = NIC_MBOX_MSG_SET_XCAST;
- mbx.xcast.data.mode = vf_work->mode;
+ mbx.xcast.data.mode = mode;
nicvf_send_msg_to_pf(nic, &mbx);
}
+static void nicvf_set_rx_mode_task(struct work_struct *work_arg)
+{
+ struct nicvf_work *vf_work = container_of(work_arg, struct nicvf_work,
+ work.work);
+ struct nicvf *nic = container_of(vf_work, struct nicvf, rx_mode_work);
+ u8 mode;
+ struct xcast_addr_list *mc;
+
+ if (!vf_work)
+ return;
+
+ /* Save message data locally to prevent them from
+ * being overwritten by next ndo_set_rx_mode call().
+ */
+ spin_lock(&nic->rx_mode_wq_lock);
+ mode = vf_work->mode;
+ mc = vf_work->mc;
+ vf_work->mc = NULL;
+ spin_unlock(&nic->rx_mode_wq_lock);
+
+ __nicvf_set_rx_mode_task(mode, mc, nic);
+}
+
static void nicvf_set_rx_mode(struct net_device *netdev)
{
struct nicvf *nic = netdev_priv(netdev);
@@ -2004,9 +2022,12 @@ static void nicvf_set_rx_mode(struct net_device *netdev)
}
}
}
+ spin_lock(&nic->rx_mode_wq_lock);
+ kfree(nic->rx_mode_work.mc);
nic->rx_mode_work.mc = mc_list;
nic->rx_mode_work.mode = mode;
- queue_delayed_work(nicvf_rx_mode_wq, &nic->rx_mode_work.work, 2 * HZ);
+ queue_delayed_work(nicvf_rx_mode_wq, &nic->rx_mode_work.work, 0);
+ spin_unlock(&nic->rx_mode_wq_lock);
}
static const struct net_device_ops nicvf_netdev_ops = {
@@ -2163,6 +2184,7 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
INIT_WORK(&nic->reset_task, nicvf_reset_task);
INIT_DELAYED_WORK(&nic->rx_mode_work.work, nicvf_set_rx_mode_task);
+ spin_lock_init(&nic->rx_mode_wq_lock);
err = register_netdev(netdev);
if (err) {
--
2.14.4
^ permalink raw reply related
* [PATCH v2 1/2] media: v4l2-ctrl: Add control for VP9 profile
From: Hans Verkuil @ 2018-06-08 9:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180530071613.125768-2-keiichiw@chromium.org>
On 05/30/2018 09:16 AM, Keiichi Watanabe wrote:
> Add a new control V4L2_CID_MPEG_VIDEO_VP9_PROFILE for selecting desired
> profile for VP9 encoder and querying for supported profiles by VP9 encoder
> or decoder.
>
> An existing control V4L2_CID_MPEG_VIDEO_VPX_PROFILE cannot be
> used for querying since it is not a menu control but an integer
> control, which cannot return an arbitrary set of supported profiles.
>
> The new control V4L2_CID_MPEG_VIDEO_VP9_PROFILE is a menu control as
> with controls for other codec profiles. (e.g. H264)
Please ignore my reply to patch 2/2. I looked at this a bit more and what you
should do is to change the type of V4L2_CID_MPEG_VIDEO_VPX_PROFILE to enum.
All other codec profile controls are all enums, so the fact that VPX_PROFILE
isn't is a bug. Changing the type should not cause any problems since the same
control value is used when you set the control.
Sylwester: I see that s5p-mfc uses this control, but it is explicitly added
as an integer type control, so the s5p-mfc driver should not be affected by
changing the type of this control.
Stanimir: this will slightly change the venus driver, but since it is a very
recent driver I think we can get away with changing the core type of the
VPX_PROFILE control. I think that's better than ending up with two controls
that do the same thing.
Regards,
Hans
>
> Signed-off-by: Keiichi Watanabe <keiichiw@chromium.org>
> ---
> .../media/uapi/v4l/extended-controls.rst | 26 +++++++++++++++++++
> drivers/media/v4l2-core/v4l2-ctrls.c | 12 +++++++++
> include/uapi/linux/v4l2-controls.h | 8 ++++++
> 3 files changed, 46 insertions(+)
>
> diff --git a/Documentation/media/uapi/v4l/extended-controls.rst b/Documentation/media/uapi/v4l/extended-controls.rst
> index 03931f9b1285..4f7f128a4998 100644
> --- a/Documentation/media/uapi/v4l/extended-controls.rst
> +++ b/Documentation/media/uapi/v4l/extended-controls.rst
> @@ -1959,6 +1959,32 @@ enum v4l2_vp8_golden_frame_sel -
> Select the desired profile for VPx encoder. Acceptable values are 0,
> 1, 2 and 3 corresponding to encoder profiles 0, 1, 2 and 3.
>
> +.. _v4l2-mpeg-video-vp9-profile:
> +
> +``V4L2_CID_MPEG_VIDEO_VP9_PROFILE``
> + (enum)
> +
> +enum v4l2_mpeg_video_vp9_profile -
> + This control allows to select the profile for VP9 encoder.
> + This is also used to enumerate supported profiles by VP9 encoder or decoder.
> + Possible values are:
> +
> +
> +
> +.. flat-table::
> + :header-rows: 0
> + :stub-columns: 0
> +
> + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_0``
> + - Profile 0
> + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_1``
> + - Profile 1
> + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_2``
> + - Profile 2
> + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_3``
> + - Profile 3
> +
> +
>
> High Efficiency Video Coding (HEVC/H.265) Control Reference
> -----------------------------------------------------------
> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
> index d29e45516eb7..401ce21c2e63 100644
> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
> @@ -431,6 +431,13 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
> "Use Previous Specific Frame",
> NULL,
> };
> + static const char * const vp9_profile[] = {
> + "0",
> + "1",
> + "2",
> + "3",
> + NULL,
> + };
>
> static const char * const flash_led_mode[] = {
> "Off",
> @@ -614,6 +621,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
> return mpeg4_profile;
> case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
> return vpx_golden_frame_sel;
> + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
> + return vp9_profile;
> case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
> return jpeg_chroma_subsampling;
> case V4L2_CID_DV_TX_MODE:
> @@ -841,6 +850,8 @@ const char *v4l2_ctrl_get_name(u32 id)
> case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP: return "VPX P-Frame QP Value";
> case V4L2_CID_MPEG_VIDEO_VPX_PROFILE: return "VPX Profile";
>
> + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: return "VP9 Profile";
> +
> /* HEVC controls */
> case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value";
> case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP: return "HEVC P-Frame QP Value";
> @@ -1180,6 +1191,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
> case V4L2_CID_DEINTERLACING_MODE:
> case V4L2_CID_TUNE_DEEMPHASIS:
> case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
> + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
> case V4L2_CID_DETECT_MD_MODE:
> case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
> case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
> index 8d473c979b61..56203b7b715c 100644
> --- a/include/uapi/linux/v4l2-controls.h
> +++ b/include/uapi/linux/v4l2-controls.h
> @@ -589,6 +589,14 @@ enum v4l2_vp8_golden_frame_sel {
> #define V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP (V4L2_CID_MPEG_BASE+510)
> #define V4L2_CID_MPEG_VIDEO_VPX_PROFILE (V4L2_CID_MPEG_BASE+511)
>
> +#define V4L2_CID_MPEG_VIDEO_VP9_PROFILE (V4L2_CID_MPEG_BASE+512)
> +enum v4l2_mpeg_video_vp9_profile {
> + V4L2_MPEG_VIDEO_VP9_PROFILE_0 = 0,
> + V4L2_MPEG_VIDEO_VP9_PROFILE_1 = 1,
> + V4L2_MPEG_VIDEO_VP9_PROFILE_2 = 2,
> + V4L2_MPEG_VIDEO_VP9_PROFILE_3 = 3,
> +};
> +
> /* CIDs for HEVC encoding. */
>
> #define V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP (V4L2_CID_MPEG_BASE + 600)
> --
> 2.17.0.921.gf22659ad46-goog
>
^ permalink raw reply
* [PATCH 11/17] arm64: dts: r8a77965: Add VSP instances
From: Geert Uytterhoeven @ 2018-06-08 9:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1787243.JuNJAuBqMb@avalon>
Hi Laurent,
CC Sergei (for V3H/V3M)
On Thu, Apr 26, 2018 at 11:11 PM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
> On Thursday, 26 April 2018 19:53:40 EEST Kieran Bingham wrote:
>> The r8a77965 has 4 VSP instances.
>>
>> Based on a similar patch of the R8A7796 device tree
>> by Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>.
>>
>> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
>> [Kieran: Rebased to top of tree, fixed sort orders]
>> Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
>> ---
>> arch/arm64/boot/dts/renesas/r8a77965.dtsi | 44 +++++++++++++++++++++++
>> 1 file changed, 44 insertions(+)
>>
>> diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi
>> b/arch/arm64/boot/dts/renesas/r8a77965.dtsi index
>> 1f44ed7c1b1c..e92e6b03333a 100644
>> --- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi
>> +++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
>> @@ -1025,6 +1047,17 @@
>> resets = <&cpg 611>;
>> };
>>
>> + vspd0: vsp at fea20000 {
>> + compatible = "renesas,vsp2";
>> + reg = <0 0xfea20000 0 0x4000>;
>
> RFP2 has a CLUT so the register range needs to be extended. I'd recommend
> covering the entire space (0x8000) even if no LUT or CLU module is present.
Even on V3H/V3M, which have some part of the CLUT, and could do
with 0x5000?
Note that this makes it overlap with fcpvd0 on all R-Car Gen3 SoCs,
as mentioned by Simon on IRC.
>> + interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
>> + clocks = <&cpg CPG_MOD 623>;
>> + power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
>> + resets = <&cpg 623>;
>> +
>> + renesas,fcp = <&fcpvd0>;
>> + };
>> +
>> fcpvd0: fcp at fea27000 {
>> compatible = "renesas,fcpv";
>> reg = <0 0xfea27000 0 0x200>;
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [PATCH v2 1/2] media: v4l2-ctrl: Add control for VP9 profile
From: Tomasz Figa @ 2018-06-08 9:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a16dca32-4198-72c1-cf22-83f18a8cfcb6@xs4all.nl>
Hi Hans,
On Fri, Jun 8, 2018 at 6:29 PM Hans Verkuil <hverkuil@xs4all.nl> wrote:
>
> On 05/30/2018 09:16 AM, Keiichi Watanabe wrote:
> > Add a new control V4L2_CID_MPEG_VIDEO_VP9_PROFILE for selecting desired
> > profile for VP9 encoder and querying for supported profiles by VP9 encoder
> > or decoder.
> >
> > An existing control V4L2_CID_MPEG_VIDEO_VPX_PROFILE cannot be
> > used for querying since it is not a menu control but an integer
> > control, which cannot return an arbitrary set of supported profiles.
> >
> > The new control V4L2_CID_MPEG_VIDEO_VP9_PROFILE is a menu control as
> > with controls for other codec profiles. (e.g. H264)
>
> Please ignore my reply to patch 2/2. I looked at this a bit more and what you
> should do is to change the type of V4L2_CID_MPEG_VIDEO_VPX_PROFILE to enum.
Note that we still need a way to query VP8 and VP9 separately, since
the supported profiles will differ. (Most of hardware we have today
support all 4 profiles of VP8 and only profile 0 of VP9.)
Best regards,
Tomasz
>
> All other codec profile controls are all enums, so the fact that VPX_PROFILE
> isn't is a bug. Changing the type should not cause any problems since the same
> control value is used when you set the control.
>
> Sylwester: I see that s5p-mfc uses this control, but it is explicitly added
> as an integer type control, so the s5p-mfc driver should not be affected by
> changing the type of this control.
>
> Stanimir: this will slightly change the venus driver, but since it is a very
> recent driver I think we can get away with changing the core type of the
> VPX_PROFILE control. I think that's better than ending up with two controls
> that do the same thing.
>
> Regards,
>
> Hans
>
> >
> > Signed-off-by: Keiichi Watanabe <keiichiw@chromium.org>
> > ---
> > .../media/uapi/v4l/extended-controls.rst | 26 +++++++++++++++++++
> > drivers/media/v4l2-core/v4l2-ctrls.c | 12 +++++++++
> > include/uapi/linux/v4l2-controls.h | 8 ++++++
> > 3 files changed, 46 insertions(+)
> >
> > diff --git a/Documentation/media/uapi/v4l/extended-controls.rst b/Documentation/media/uapi/v4l/extended-controls.rst
> > index 03931f9b1285..4f7f128a4998 100644
> > --- a/Documentation/media/uapi/v4l/extended-controls.rst
> > +++ b/Documentation/media/uapi/v4l/extended-controls.rst
> > @@ -1959,6 +1959,32 @@ enum v4l2_vp8_golden_frame_sel -
> > Select the desired profile for VPx encoder. Acceptable values are 0,
> > 1, 2 and 3 corresponding to encoder profiles 0, 1, 2 and 3.
> >
> > +.. _v4l2-mpeg-video-vp9-profile:
> > +
> > +``V4L2_CID_MPEG_VIDEO_VP9_PROFILE``
> > + (enum)
> > +
> > +enum v4l2_mpeg_video_vp9_profile -
> > + This control allows to select the profile for VP9 encoder.
> > + This is also used to enumerate supported profiles by VP9 encoder or decoder.
> > + Possible values are:
> > +
> > +
> > +
> > +.. flat-table::
> > + :header-rows: 0
> > + :stub-columns: 0
> > +
> > + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_0``
> > + - Profile 0
> > + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_1``
> > + - Profile 1
> > + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_2``
> > + - Profile 2
> > + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_3``
> > + - Profile 3
> > +
> > +
> >
> > High Efficiency Video Coding (HEVC/H.265) Control Reference
> > -----------------------------------------------------------
> > diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
> > index d29e45516eb7..401ce21c2e63 100644
> > --- a/drivers/media/v4l2-core/v4l2-ctrls.c
> > +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
> > @@ -431,6 +431,13 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
> > "Use Previous Specific Frame",
> > NULL,
> > };
> > + static const char * const vp9_profile[] = {
> > + "0",
> > + "1",
> > + "2",
> > + "3",
> > + NULL,
> > + };
> >
> > static const char * const flash_led_mode[] = {
> > "Off",
> > @@ -614,6 +621,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
> > return mpeg4_profile;
> > case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
> > return vpx_golden_frame_sel;
> > + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
> > + return vp9_profile;
> > case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
> > return jpeg_chroma_subsampling;
> > case V4L2_CID_DV_TX_MODE:
> > @@ -841,6 +850,8 @@ const char *v4l2_ctrl_get_name(u32 id)
> > case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP: return "VPX P-Frame QP Value";
> > case V4L2_CID_MPEG_VIDEO_VPX_PROFILE: return "VPX Profile";
> >
> > + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: return "VP9 Profile";
> > +
> > /* HEVC controls */
> > case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value";
> > case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP: return "HEVC P-Frame QP Value";
> > @@ -1180,6 +1191,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
> > case V4L2_CID_DEINTERLACING_MODE:
> > case V4L2_CID_TUNE_DEEMPHASIS:
> > case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
> > + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
> > case V4L2_CID_DETECT_MD_MODE:
> > case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
> > case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
> > diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
> > index 8d473c979b61..56203b7b715c 100644
> > --- a/include/uapi/linux/v4l2-controls.h
> > +++ b/include/uapi/linux/v4l2-controls.h
> > @@ -589,6 +589,14 @@ enum v4l2_vp8_golden_frame_sel {
> > #define V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP (V4L2_CID_MPEG_BASE+510)
> > #define V4L2_CID_MPEG_VIDEO_VPX_PROFILE (V4L2_CID_MPEG_BASE+511)
> >
> > +#define V4L2_CID_MPEG_VIDEO_VP9_PROFILE (V4L2_CID_MPEG_BASE+512)
> > +enum v4l2_mpeg_video_vp9_profile {
> > + V4L2_MPEG_VIDEO_VP9_PROFILE_0 = 0,
> > + V4L2_MPEG_VIDEO_VP9_PROFILE_1 = 1,
> > + V4L2_MPEG_VIDEO_VP9_PROFILE_2 = 2,
> > + V4L2_MPEG_VIDEO_VP9_PROFILE_3 = 3,
> > +};
> > +
> > /* CIDs for HEVC encoding. */
> >
> > #define V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP (V4L2_CID_MPEG_BASE + 600)
> > --
> > 2.17.0.921.gf22659ad46-goog
> >
>
^ permalink raw reply
* [PATCH v2 1/2] media: v4l2-ctrl: Add control for VP9 profile
From: Hans Verkuil @ 2018-06-08 9:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAAFQd5B8W0KqnPXs3yo8-ndKTE2n5yYmNEjbCWq6yR6iQYjouA@mail.gmail.com>
On 06/08/2018 11:31 AM, Tomasz Figa wrote:
> Hi Hans,
>
> On Fri, Jun 8, 2018 at 6:29 PM Hans Verkuil <hverkuil@xs4all.nl> wrote:
>>
>> On 05/30/2018 09:16 AM, Keiichi Watanabe wrote:
>>> Add a new control V4L2_CID_MPEG_VIDEO_VP9_PROFILE for selecting desired
>>> profile for VP9 encoder and querying for supported profiles by VP9 encoder
>>> or decoder.
>>>
>>> An existing control V4L2_CID_MPEG_VIDEO_VPX_PROFILE cannot be
>>> used for querying since it is not a menu control but an integer
>>> control, which cannot return an arbitrary set of supported profiles.
>>>
>>> The new control V4L2_CID_MPEG_VIDEO_VP9_PROFILE is a menu control as
>>> with controls for other codec profiles. (e.g. H264)
>>
>> Please ignore my reply to patch 2/2. I looked at this a bit more and what you
>> should do is to change the type of V4L2_CID_MPEG_VIDEO_VPX_PROFILE to enum.
>
> Note that we still need a way to query VP8 and VP9 separately, since
> the supported profiles will differ. (Most of hardware we have today
> support all 4 profiles of VP8 and only profile 0 of VP9.)
Urgh. So V4L2_CID_MPEG_VIDEO_VPX_PROFILE is really just for VP8?
In that case I would suggest that we rename V4L2_CID_MPEG_VIDEO_VPX_PROFILE to
V4L2_CID_MPEG_VIDEO_VP8_PROFILE and change it to an enum. Also add this line
to v4l2-controls.h:
#define V4L2_CID_MPEG_VIDEO_VPX_PROFILE V4L2_CID_MPEG_VIDEO_VP8_PROFILE
And add a new V4L2_CID_MPEG_VIDEO_VP9_PROFILE (basically this patch).
Would that work?
This standardizes on enums for all profile controls (except s5p-mfc, which
makes its own int control, up to samsung to decide whether or not to change
that), and you have VP8 and VP9 specific profiles.
Regards,
Hans
>
> Best regards,
> Tomasz
>
>>
>> All other codec profile controls are all enums, so the fact that VPX_PROFILE
>> isn't is a bug. Changing the type should not cause any problems since the same
>> control value is used when you set the control.
>>
>> Sylwester: I see that s5p-mfc uses this control, but it is explicitly added
>> as an integer type control, so the s5p-mfc driver should not be affected by
>> changing the type of this control.
>>
>> Stanimir: this will slightly change the venus driver, but since it is a very
>> recent driver I think we can get away with changing the core type of the
>> VPX_PROFILE control. I think that's better than ending up with two controls
>> that do the same thing.
>>
>> Regards,
>>
>> Hans
>>
>>>
>>> Signed-off-by: Keiichi Watanabe <keiichiw@chromium.org>
>>> ---
>>> .../media/uapi/v4l/extended-controls.rst | 26 +++++++++++++++++++
>>> drivers/media/v4l2-core/v4l2-ctrls.c | 12 +++++++++
>>> include/uapi/linux/v4l2-controls.h | 8 ++++++
>>> 3 files changed, 46 insertions(+)
>>>
>>> diff --git a/Documentation/media/uapi/v4l/extended-controls.rst b/Documentation/media/uapi/v4l/extended-controls.rst
>>> index 03931f9b1285..4f7f128a4998 100644
>>> --- a/Documentation/media/uapi/v4l/extended-controls.rst
>>> +++ b/Documentation/media/uapi/v4l/extended-controls.rst
>>> @@ -1959,6 +1959,32 @@ enum v4l2_vp8_golden_frame_sel -
>>> Select the desired profile for VPx encoder. Acceptable values are 0,
>>> 1, 2 and 3 corresponding to encoder profiles 0, 1, 2 and 3.
>>>
>>> +.. _v4l2-mpeg-video-vp9-profile:
>>> +
>>> +``V4L2_CID_MPEG_VIDEO_VP9_PROFILE``
>>> + (enum)
>>> +
>>> +enum v4l2_mpeg_video_vp9_profile -
>>> + This control allows to select the profile for VP9 encoder.
>>> + This is also used to enumerate supported profiles by VP9 encoder or decoder.
>>> + Possible values are:
>>> +
>>> +
>>> +
>>> +.. flat-table::
>>> + :header-rows: 0
>>> + :stub-columns: 0
>>> +
>>> + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_0``
>>> + - Profile 0
>>> + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_1``
>>> + - Profile 1
>>> + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_2``
>>> + - Profile 2
>>> + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_3``
>>> + - Profile 3
>>> +
>>> +
>>>
>>> High Efficiency Video Coding (HEVC/H.265) Control Reference
>>> -----------------------------------------------------------
>>> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
>>> index d29e45516eb7..401ce21c2e63 100644
>>> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
>>> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
>>> @@ -431,6 +431,13 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
>>> "Use Previous Specific Frame",
>>> NULL,
>>> };
>>> + static const char * const vp9_profile[] = {
>>> + "0",
>>> + "1",
>>> + "2",
>>> + "3",
>>> + NULL,
>>> + };
>>>
>>> static const char * const flash_led_mode[] = {
>>> "Off",
>>> @@ -614,6 +621,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
>>> return mpeg4_profile;
>>> case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
>>> return vpx_golden_frame_sel;
>>> + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
>>> + return vp9_profile;
>>> case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
>>> return jpeg_chroma_subsampling;
>>> case V4L2_CID_DV_TX_MODE:
>>> @@ -841,6 +850,8 @@ const char *v4l2_ctrl_get_name(u32 id)
>>> case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP: return "VPX P-Frame QP Value";
>>> case V4L2_CID_MPEG_VIDEO_VPX_PROFILE: return "VPX Profile";
>>>
>>> + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: return "VP9 Profile";
>>> +
>>> /* HEVC controls */
>>> case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value";
>>> case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP: return "HEVC P-Frame QP Value";
>>> @@ -1180,6 +1191,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
>>> case V4L2_CID_DEINTERLACING_MODE:
>>> case V4L2_CID_TUNE_DEEMPHASIS:
>>> case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
>>> + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
>>> case V4L2_CID_DETECT_MD_MODE:
>>> case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
>>> case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
>>> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
>>> index 8d473c979b61..56203b7b715c 100644
>>> --- a/include/uapi/linux/v4l2-controls.h
>>> +++ b/include/uapi/linux/v4l2-controls.h
>>> @@ -589,6 +589,14 @@ enum v4l2_vp8_golden_frame_sel {
>>> #define V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP (V4L2_CID_MPEG_BASE+510)
>>> #define V4L2_CID_MPEG_VIDEO_VPX_PROFILE (V4L2_CID_MPEG_BASE+511)
>>>
>>> +#define V4L2_CID_MPEG_VIDEO_VP9_PROFILE (V4L2_CID_MPEG_BASE+512)
>>> +enum v4l2_mpeg_video_vp9_profile {
>>> + V4L2_MPEG_VIDEO_VP9_PROFILE_0 = 0,
>>> + V4L2_MPEG_VIDEO_VP9_PROFILE_1 = 1,
>>> + V4L2_MPEG_VIDEO_VP9_PROFILE_2 = 2,
>>> + V4L2_MPEG_VIDEO_VP9_PROFILE_3 = 3,
>>> +};
>>> +
>>> /* CIDs for HEVC encoding. */
>>>
>>> #define V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP (V4L2_CID_MPEG_BASE + 600)
>>> --
>>> 2.17.0.921.gf22659ad46-goog
>>>
>>
^ permalink raw reply
* [PATCH v2 0/5] add virt-dma support for imx-sdma
From: Robin Gong @ 2018-06-08 9:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180608084310.bzxeazqht5u6mgdw@pengutronix.de>
Thanks Sacha, I'll intergrate it into v3.
-----Original Message-----
From: Sascha Hauer [mailto:s.hauer at pengutronix.de]
Sent: 2018?6?8? 16:43
To: Robin Gong <yibin.gong@nxp.com>
Cc: vkoul at kernel.org; dan.j.williams at intel.com; dmaengine at vger.kernel.org; linux-kernel at vger.kernel.org; linux-arm-kernel at lists.infradead.org; dl-linux-imx <linux-imx@nxp.com>
Subject: Re: [PATCH v2 0/5] add virt-dma support for imx-sdma
On Fri, Jun 08, 2018 at 09:44:45PM +0800, Robin Gong wrote:
> The legacy sdma driver has below limitations or drawbacks:
> 1. Hardcode the max BDs number as "PAGE_SIZE / sizeof(*)", and alloc
> one page size for one channel regardless of only few BDs needed
> most time. But in few cases, the max PAGE_SIZE maybe not enough.
> 2. One SDMA channel can't stop immediatley once channel disabled which
> means SDMA interrupt may come in after this channel terminated.There
> are some patches for this corner case such as commit "2746e2c389f9",
> but not cover non-cyclic.
>
> The common virt-dma overcomes the above limitations. It can alloc bd
> dynamically and free bd once this tx transfer done. No memory wasted
> or maximum limititation here, only depends on how many memory can be
> requested from kernel. For No.2, such issue can be workaround by
> checking if there is available descript("sdmac->desc") now once the
> unwanted interrupt coming. At last the common virt-dma is easier for sdma driver maintain.
>
> Change from v1:
> 1. split v1 patch into 5 patches.
> 2. remove some unnecessary condition check.
> 3. remove unneccessary 'pending' list.
>
> Robin Gong (5):
> dmaengine: imx-sdma: add virt-dma support
> Revert "dmaengine: imx-sdma: fix pagefault when channel is disabled
> during interrupt"
> dmaengine: imx-sdma: remove usless lock
> dmaengine: imx-sdma: remove the maximum limation for bd numbers
> dmaengine: imx-sdma: add sdma_transfer_init to decrease code overlap
>
> drivers/dma/Kconfig | 1 +
> drivers/dma/imx-sdma.c | 392
> ++++++++++++++++++++++++++++---------------------
> 2 files changed, 227 insertions(+), 166 deletions(-)
Please put the attached patch in front of your series. It makes the virt-dma support patch smaller and thus easier to review.
Sascha
--------------------------------8<----------------------------------
>From a70ccdf780cc6fcddd2d06c4a3eb0123d4aba443 Mon Sep 17 00:00:00 2001
From: Sascha Hauer <s.hauer@pengutronix.de>
Date: Fri, 8 Jun 2018 10:20:18 +0200
Subject: [PATCH 1/2] dmaengine: imx-sdma: factor out a struct sdma_desc from struct sdma_channel
This is a preparation step to make the adding of virt-dma easier.
We create a struct sdma_desc, move some fields from struct sdma_channel there and add a pointer from the former to the latter. For now we allocate the data statically in struct sdma_channel, but with virt-dma support it will be dynamically allocated.
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
drivers/dma/imx-sdma.c | 137 +++++++++++++++++++++++++----------------
1 file changed, 83 insertions(+), 54 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index ccd03c3cedfe..556d08712f4a 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -295,6 +295,30 @@ struct sdma_context_data {
struct sdma_engine;
+/**
+ * struct sdma_desc - descriptor structor for one transfer
+ * @vd descriptor for virt dma
+ * @num_bd max NUM_BD. number of descriptors currently handling
+ * @buf_tail ID of the buffer that was processed
+ * @buf_ptail ID of the previous buffer that was processed
+ * @period_len period length, used in cyclic.
+ * @chn_real_count the real count updated from bd->mode.count
+ * @chn_count the transfer count setuped
+ * @sdmac sdma_channel pointer
+ * @bd pointer of alloced bd
+ */
+struct sdma_desc {
+ unsigned int num_bd;
+ dma_addr_t bd_phys;
+ unsigned int buf_tail;
+ unsigned int buf_ptail;
+ unsigned int period_len;
+ unsigned int chn_real_count;
+ unsigned int chn_count;
+ struct sdma_channel *sdmac;
+ struct sdma_buffer_descriptor *bd;
+};
+
/**
* struct sdma_channel - housekeeping for a SDMA channel
*
@@ -305,11 +329,10 @@ struct sdma_engine;
* @event_id0 aka dma request line
* @event_id1 for channels that use 2 events
* @word_size peripheral access size
- * @buf_tail ID of the buffer that was processed
- * @buf_ptail ID of the previous buffer that was processed
- * @num_bd max NUM_BD. number of descriptors currently handling
*/
struct sdma_channel {
+ struct sdma_desc *desc;
+ struct sdma_desc _desc;
struct sdma_engine *sdma;
unsigned int channel;
enum dma_transfer_direction direction;
@@ -317,12 +340,6 @@ struct sdma_channel {
unsigned int event_id0;
unsigned int event_id1;
enum dma_slave_buswidth word_size;
- unsigned int buf_tail;
- unsigned int buf_ptail;
- unsigned int num_bd;
- unsigned int period_len;
- struct sdma_buffer_descriptor *bd;
- dma_addr_t bd_phys;
unsigned int pc_from_device, pc_to_device;
unsigned int device_to_device;
unsigned long flags;
@@ -332,10 +349,8 @@ struct sdma_channel {
u32 shp_addr, per_addr;
struct dma_chan chan;
spinlock_t lock;
- struct dma_async_tx_descriptor desc;
+ struct dma_async_tx_descriptor txdesc;
enum dma_status status;
- unsigned int chn_count;
- unsigned int chn_real_count;
struct tasklet_struct tasklet;
struct imx_dma_data data;
bool enabled;
@@ -398,6 +413,8 @@ struct sdma_engine {
u32 spba_start_addr;
u32 spba_end_addr;
unsigned int irq;
+ dma_addr_t bd0_phys;
+ struct sdma_buffer_descriptor *bd0;
};
static struct sdma_driver_data sdma_imx31 = { @@ -632,7 +649,7 @@ static int sdma_run_channel0(struct sdma_engine *sdma) static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
u32 address)
{
- struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
+ struct sdma_buffer_descriptor *bd0 = sdma->bd0;
void *buf_virt;
dma_addr_t buf_phys;
int ret;
@@ -707,7 +724,9 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* call callback function.
*/
while (1) {
- bd = &sdmac->bd[sdmac->buf_tail];
+ struct sdma_desc *desc = sdmac->desc;
+
+ bd = &desc->bd[desc->buf_tail];
if (bd->mode.status & BD_DONE)
break;
@@ -723,11 +742,11 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* the number of bytes present in the current buffer descriptor.
*/
- sdmac->chn_real_count = bd->mode.count;
+ desc->chn_real_count = bd->mode.count;
bd->mode.status |= BD_DONE;
- bd->mode.count = sdmac->period_len;
- sdmac->buf_ptail = sdmac->buf_tail;
- sdmac->buf_tail = (sdmac->buf_tail + 1) % sdmac->num_bd;
+ bd->mode.count = desc->period_len;
+ desc->buf_ptail = desc->buf_tail;
+ desc->buf_tail = (desc->buf_tail + 1) % desc->num_bd;
/*
* The callback is called from the interrupt context in order @@ -736,7 +755,7 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* executed.
*/
- dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
+ dmaengine_desc_get_callback_invoke(&sdmac->txdesc, NULL);
if (error)
sdmac->status = old_status;
@@ -749,17 +768,17 @@ static void mxc_sdma_handle_channel_normal(unsigned long data)
struct sdma_buffer_descriptor *bd;
int i, error = 0;
- sdmac->chn_real_count = 0;
+ sdmac->desc->chn_real_count = 0;
/*
* non loop mode. Iterate over all descriptors, collect
* errors and call callback function
*/
- for (i = 0; i < sdmac->num_bd; i++) {
- bd = &sdmac->bd[i];
+ for (i = 0; i < sdmac->desc->num_bd; i++) {
+ bd = &sdmac->desc->bd[i];
if (bd->mode.status & (BD_DONE | BD_RROR))
error = -EIO;
- sdmac->chn_real_count += bd->mode.count;
+ sdmac->desc->chn_real_count += bd->mode.count;
}
if (error)
@@ -767,9 +786,9 @@ static void mxc_sdma_handle_channel_normal(unsigned long data)
else
sdmac->status = DMA_COMPLETE;
- dma_cookie_complete(&sdmac->desc);
+ dma_cookie_complete(&sdmac->txdesc);
- dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
+ dmaengine_desc_get_callback_invoke(&sdmac->txdesc, NULL);
}
static irqreturn_t sdma_int_handler(int irq, void *dev_id) @@ -897,7 +916,7 @@ static int sdma_load_context(struct sdma_channel *sdmac)
int channel = sdmac->channel;
int load_address;
struct sdma_context_data *context = sdma->context;
- struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
+ struct sdma_buffer_descriptor *bd0 = sdma->bd0;
int ret;
unsigned long flags;
@@ -1100,18 +1119,22 @@ static int sdma_set_channel_priority(struct sdma_channel *sdmac, static int sdma_request_channel(struct sdma_channel *sdmac) {
struct sdma_engine *sdma = sdmac->sdma;
+ struct sdma_desc *desc;
int channel = sdmac->channel;
int ret = -EBUSY;
- sdmac->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys,
+ sdmac->desc = &sdmac->_desc;
+ desc = sdmac->desc;
+
+ desc->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &desc->bd_phys,
GFP_KERNEL);
- if (!sdmac->bd) {
+ if (!desc->bd) {
ret = -ENOMEM;
goto out;
}
- sdma->channel_control[channel].base_bd_ptr = sdmac->bd_phys;
- sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
+ sdma->channel_control[channel].base_bd_ptr = desc->bd_phys;
+ sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
sdma_set_channel_priority(sdmac, MXC_SDMA_DEFAULT_PRIORITY);
return 0;
@@ -1176,10 +1199,10 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
if (ret)
goto disable_clk_ahb;
- dma_async_tx_descriptor_init(&sdmac->desc, chan);
- sdmac->desc.tx_submit = sdma_tx_submit;
+ dma_async_tx_descriptor_init(&sdmac->txdesc, chan);
+ sdmac->txdesc.tx_submit = sdma_tx_submit;
/* txd.flags will be overwritten in prep funcs */
- sdmac->desc.flags = DMA_CTRL_ACK;
+ sdmac->txdesc.flags = DMA_CTRL_ACK;
return 0;
@@ -1194,6 +1217,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan) {
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
+ struct sdma_desc *desc = sdmac->desc;
sdma_disable_channel(chan);
@@ -1207,7 +1231,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
sdma_set_channel_priority(sdmac, 0);
- dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys);
+ dma_free_coherent(NULL, PAGE_SIZE, desc->bd, desc->bd_phys);
clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb);
@@ -1223,6 +1247,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
int ret, i, count;
int channel = sdmac->channel;
struct scatterlist *sg;
+ struct sdma_desc *desc = sdmac->desc;
if (sdmac->status == DMA_IN_PROGRESS)
return NULL;
@@ -1230,9 +1255,9 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
sdmac->flags = 0;
- sdmac->buf_tail = 0;
- sdmac->buf_ptail = 0;
- sdmac->chn_real_count = 0;
+ desc->buf_tail = 0;
+ desc->buf_ptail = 0;
+ desc->chn_real_count = 0;
dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
sg_len, channel);
@@ -1249,9 +1274,9 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
goto err_out;
}
- sdmac->chn_count = 0;
+ desc->chn_count = 0;
for_each_sg(sgl, sg, sg_len, i) {
- struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
+ struct sdma_buffer_descriptor *bd = &desc->bd[i];
int param;
bd->buffer_addr = sg->dma_address;
@@ -1266,7 +1291,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
}
bd->mode.count = count;
- sdmac->chn_count += count;
+ desc->chn_count += count;
if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
ret = -EINVAL;
@@ -1307,10 +1332,10 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
bd->mode.status = param;
}
- sdmac->num_bd = sg_len;
- sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
+ desc->num_bd = sg_len;
+ sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
- return &sdmac->desc;
+ return &sdmac->txdesc;
err_out:
sdmac->status = DMA_ERROR;
return NULL;
@@ -1326,6 +1351,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
int num_periods = buf_len / period_len;
int channel = sdmac->channel;
int ret, i = 0, buf = 0;
+ struct sdma_desc *desc = sdmac->desc;
dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel);
@@ -1334,10 +1360,10 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
sdmac->status = DMA_IN_PROGRESS;
- sdmac->buf_tail = 0;
- sdmac->buf_ptail = 0;
- sdmac->chn_real_count = 0;
- sdmac->period_len = period_len;
+ desc->buf_tail = 0;
+ desc->buf_ptail = 0;
+ desc->chn_real_count = 0;
+ desc->period_len = period_len;
sdmac->flags |= IMX_DMA_SG_LOOP;
sdmac->direction = direction;
@@ -1358,7 +1384,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
}
while (buf < buf_len) {
- struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
+ struct sdma_buffer_descriptor *bd = &desc->bd[i];
int param;
bd->buffer_addr = dma_addr;
@@ -1389,10 +1415,10 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
i++;
}
- sdmac->num_bd = num_periods;
- sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
+ desc->num_bd = num_periods;
+ sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
- return &sdmac->desc;
+ return &sdmac->txdesc;
err_out:
sdmac->status = DMA_ERROR;
return NULL;
@@ -1431,13 +1457,14 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
struct dma_tx_state *txstate) {
struct sdma_channel *sdmac = to_sdma_chan(chan);
+ struct sdma_desc *desc = sdmac->desc;
u32 residue;
if (sdmac->flags & IMX_DMA_SG_LOOP)
- residue = (sdmac->num_bd - sdmac->buf_ptail) *
- sdmac->period_len - sdmac->chn_real_count;
+ residue = (desc->num_bd - desc->buf_ptail) *
+ desc->period_len - desc->chn_real_count;
else
- residue = sdmac->chn_count - sdmac->chn_real_count;
+ residue = desc->chn_count - desc->chn_real_count;
dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
residue);
@@ -1661,6 +1688,8 @@ static int sdma_init(struct sdma_engine *sdma)
if (ret)
goto err_dma_alloc;
+ sdma->bd0 = sdma->channel[0].desc->bd;
+
sdma_config_ownership(&sdma->channel[0], false, true, false);
/* Set Command Channel (Channel Zero) */
--
2.17.1
--
Pengutronix e.K. | |
Industrial Linux Solutions | https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.pengutronix.de%2F&data=02%7C01%7Cyibin.gong%40nxp.com%7Cf4671adfeaa947506e2b08d5cd1be23d%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636640442016947893&sdata=6FkizxBudOfDkWUrj28qYaycOz%2Br0bwf7DJJ8vZgaKg%3D&reserved=0 |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
^ permalink raw reply
* [PATCH v2 1/2] media: v4l2-ctrl: Add control for VP9 profile
From: Tomasz Figa @ 2018-06-08 9:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <2dabdd75-1351-ae71-7d40-8d836ec05308@xs4all.nl>
On Fri, Jun 8, 2018 at 6:40 PM Hans Verkuil <hverkuil@xs4all.nl> wrote:
>
> On 06/08/2018 11:31 AM, Tomasz Figa wrote:
> > Hi Hans,
> >
> > On Fri, Jun 8, 2018 at 6:29 PM Hans Verkuil <hverkuil@xs4all.nl> wrote:
> >>
> >> On 05/30/2018 09:16 AM, Keiichi Watanabe wrote:
> >>> Add a new control V4L2_CID_MPEG_VIDEO_VP9_PROFILE for selecting desired
> >>> profile for VP9 encoder and querying for supported profiles by VP9 encoder
> >>> or decoder.
> >>>
> >>> An existing control V4L2_CID_MPEG_VIDEO_VPX_PROFILE cannot be
> >>> used for querying since it is not a menu control but an integer
> >>> control, which cannot return an arbitrary set of supported profiles.
> >>>
> >>> The new control V4L2_CID_MPEG_VIDEO_VP9_PROFILE is a menu control as
> >>> with controls for other codec profiles. (e.g. H264)
> >>
> >> Please ignore my reply to patch 2/2. I looked at this a bit more and what you
> >> should do is to change the type of V4L2_CID_MPEG_VIDEO_VPX_PROFILE to enum.
> >
> > Note that we still need a way to query VP8 and VP9 separately, since
> > the supported profiles will differ. (Most of hardware we have today
> > support all 4 profiles of VP8 and only profile 0 of VP9.)
>
> Urgh. So V4L2_CID_MPEG_VIDEO_VPX_PROFILE is really just for VP8?
I don't know the background, but it's completely inconsistent to
similar controls we have for other codecs. (Also we don't have
V4L2_CID_MPEG_VIDEO_PROFILE, but rather 1 control for each codec).
>
> In that case I would suggest that we rename V4L2_CID_MPEG_VIDEO_VPX_PROFILE to
> V4L2_CID_MPEG_VIDEO_VP8_PROFILE and change it to an enum. Also add this line
> to v4l2-controls.h:
>
> #define V4L2_CID_MPEG_VIDEO_VPX_PROFILE V4L2_CID_MPEG_VIDEO_VP8_PROFILE
>
> And add a new V4L2_CID_MPEG_VIDEO_VP9_PROFILE (basically this patch).
>
> Would that work?
>
> This standardizes on enums for all profile controls (except s5p-mfc, which
> makes its own int control, up to samsung to decide whether or not to change
> that), and you have VP8 and VP9 specific profiles.
Sounds good to me, thanks.
Best regards,
Tomasz
>
> Regards,
>
> Hans
>
> >
> > Best regards,
> > Tomasz
> >
> >>
> >> All other codec profile controls are all enums, so the fact that VPX_PROFILE
> >> isn't is a bug. Changing the type should not cause any problems since the same
> >> control value is used when you set the control.
> >>
> >> Sylwester: I see that s5p-mfc uses this control, but it is explicitly added
> >> as an integer type control, so the s5p-mfc driver should not be affected by
> >> changing the type of this control.
> >>
> >> Stanimir: this will slightly change the venus driver, but since it is a very
> >> recent driver I think we can get away with changing the core type of the
> >> VPX_PROFILE control. I think that's better than ending up with two controls
> >> that do the same thing.
> >>
> >> Regards,
> >>
> >> Hans
> >>
> >>>
> >>> Signed-off-by: Keiichi Watanabe <keiichiw@chromium.org>
> >>> ---
> >>> .../media/uapi/v4l/extended-controls.rst | 26 +++++++++++++++++++
> >>> drivers/media/v4l2-core/v4l2-ctrls.c | 12 +++++++++
> >>> include/uapi/linux/v4l2-controls.h | 8 ++++++
> >>> 3 files changed, 46 insertions(+)
> >>>
> >>> diff --git a/Documentation/media/uapi/v4l/extended-controls.rst b/Documentation/media/uapi/v4l/extended-controls.rst
> >>> index 03931f9b1285..4f7f128a4998 100644
> >>> --- a/Documentation/media/uapi/v4l/extended-controls.rst
> >>> +++ b/Documentation/media/uapi/v4l/extended-controls.rst
> >>> @@ -1959,6 +1959,32 @@ enum v4l2_vp8_golden_frame_sel -
> >>> Select the desired profile for VPx encoder. Acceptable values are 0,
> >>> 1, 2 and 3 corresponding to encoder profiles 0, 1, 2 and 3.
> >>>
> >>> +.. _v4l2-mpeg-video-vp9-profile:
> >>> +
> >>> +``V4L2_CID_MPEG_VIDEO_VP9_PROFILE``
> >>> + (enum)
> >>> +
> >>> +enum v4l2_mpeg_video_vp9_profile -
> >>> + This control allows to select the profile for VP9 encoder.
> >>> + This is also used to enumerate supported profiles by VP9 encoder or decoder.
> >>> + Possible values are:
> >>> +
> >>> +
> >>> +
> >>> +.. flat-table::
> >>> + :header-rows: 0
> >>> + :stub-columns: 0
> >>> +
> >>> + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_0``
> >>> + - Profile 0
> >>> + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_1``
> >>> + - Profile 1
> >>> + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_2``
> >>> + - Profile 2
> >>> + * - ``V4L2_MPEG_VIDEO_VP9_PROFILE_3``
> >>> + - Profile 3
> >>> +
> >>> +
> >>>
> >>> High Efficiency Video Coding (HEVC/H.265) Control Reference
> >>> -----------------------------------------------------------
> >>> diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
> >>> index d29e45516eb7..401ce21c2e63 100644
> >>> --- a/drivers/media/v4l2-core/v4l2-ctrls.c
> >>> +++ b/drivers/media/v4l2-core/v4l2-ctrls.c
> >>> @@ -431,6 +431,13 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
> >>> "Use Previous Specific Frame",
> >>> NULL,
> >>> };
> >>> + static const char * const vp9_profile[] = {
> >>> + "0",
> >>> + "1",
> >>> + "2",
> >>> + "3",
> >>> + NULL,
> >>> + };
> >>>
> >>> static const char * const flash_led_mode[] = {
> >>> "Off",
> >>> @@ -614,6 +621,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
> >>> return mpeg4_profile;
> >>> case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
> >>> return vpx_golden_frame_sel;
> >>> + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
> >>> + return vp9_profile;
> >>> case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
> >>> return jpeg_chroma_subsampling;
> >>> case V4L2_CID_DV_TX_MODE:
> >>> @@ -841,6 +850,8 @@ const char *v4l2_ctrl_get_name(u32 id)
> >>> case V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP: return "VPX P-Frame QP Value";
> >>> case V4L2_CID_MPEG_VIDEO_VPX_PROFILE: return "VPX Profile";
> >>>
> >>> + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE: return "VP9 Profile";
> >>> +
> >>> /* HEVC controls */
> >>> case V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP: return "HEVC I-Frame QP Value";
> >>> case V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_QP: return "HEVC P-Frame QP Value";
> >>> @@ -1180,6 +1191,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
> >>> case V4L2_CID_DEINTERLACING_MODE:
> >>> case V4L2_CID_TUNE_DEEMPHASIS:
> >>> case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
> >>> + case V4L2_CID_MPEG_VIDEO_VP9_PROFILE:
> >>> case V4L2_CID_DETECT_MD_MODE:
> >>> case V4L2_CID_MPEG_VIDEO_HEVC_PROFILE:
> >>> case V4L2_CID_MPEG_VIDEO_HEVC_LEVEL:
> >>> diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
> >>> index 8d473c979b61..56203b7b715c 100644
> >>> --- a/include/uapi/linux/v4l2-controls.h
> >>> +++ b/include/uapi/linux/v4l2-controls.h
> >>> @@ -589,6 +589,14 @@ enum v4l2_vp8_golden_frame_sel {
> >>> #define V4L2_CID_MPEG_VIDEO_VPX_P_FRAME_QP (V4L2_CID_MPEG_BASE+510)
> >>> #define V4L2_CID_MPEG_VIDEO_VPX_PROFILE (V4L2_CID_MPEG_BASE+511)
> >>>
> >>> +#define V4L2_CID_MPEG_VIDEO_VP9_PROFILE (V4L2_CID_MPEG_BASE+512)
> >>> +enum v4l2_mpeg_video_vp9_profile {
> >>> + V4L2_MPEG_VIDEO_VP9_PROFILE_0 = 0,
> >>> + V4L2_MPEG_VIDEO_VP9_PROFILE_1 = 1,
> >>> + V4L2_MPEG_VIDEO_VP9_PROFILE_2 = 2,
> >>> + V4L2_MPEG_VIDEO_VP9_PROFILE_3 = 3,
> >>> +};
> >>> +
> >>> /* CIDs for HEVC encoding. */
> >>>
> >>> #define V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP (V4L2_CID_MPEG_BASE + 600)
> >>> --
> >>> 2.17.0.921.gf22659ad46-goog
> >>>
> >>
>
^ permalink raw reply
* [PATCH] pinctrl: actions: Fix uninitialized error in owl_pin_config_set()
From: Geert Uytterhoeven @ 2018-06-08 10:05 UTC (permalink / raw)
To: linux-arm-kernel
With gcc 4.1.2:
drivers/pinctrl/actions/pinctrl-owl.c: In function ?owl_pin_config_set?:
drivers/pinctrl/actions/pinctrl-owl.c:336: warning: ?ret? may be used uninitialized in this function
Indeed, if num_configs is zero, the uninitialized value will be returned
as an error code.
Fix this by preinitializing it to zero.
Fixes: 2242ddfbf4d699b5 ("pinctrl: actions: Add Actions S900 pinctrl driver")
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
---
drivers/pinctrl/actions/pinctrl-owl.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/pinctrl/actions/pinctrl-owl.c b/drivers/pinctrl/actions/pinctrl-owl.c
index 76243caa08c630c0..b5c880b50bb371f5 100644
--- a/drivers/pinctrl/actions/pinctrl-owl.c
+++ b/drivers/pinctrl/actions/pinctrl-owl.c
@@ -333,7 +333,7 @@ static int owl_pin_config_set(struct pinctrl_dev *pctrldev,
unsigned long flags;
unsigned int param;
u32 reg, bit, width, arg;
- int ret, i;
+ int ret = 0, i;
info = &pctrl->soc->padinfo[pin];
--
2.7.4
^ permalink raw reply related
* [PATCH] clk: imx6: fix video_27m parent for IMX6QDL_CLK_CKO1_SEL
From: Philipp Puschmann @ 2018-06-08 10:19 UTC (permalink / raw)
To: linux-arm-kernel
q/dl datasheets list the 5th selection value for ck01_sel as
video_27M_clk_root.
By replacing the dummy value we then can set IMX6QDL_CLK_VIDEO_27M
as parent for IMX6QDL_CLK_CKO1_SEL.
Signed-off-by: Philipp Puschmann <pp@emlix.com>
---
drivers/clk/imx/clk-imx6q.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index 8d518ad5dc13..7e6a8f079634 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -65,7 +65,7 @@ static const char *ipg_per_sels[] = { "ipg", "osc", };
static const char *ecspi_sels[] = { "pll3_60m", "osc", };
static const char *can_sels[] = { "pll3_60m", "osc", "pll3_80m", };
static const char *cko1_sels[] = { "pll3_usb_otg", "pll2_bus", "pll1_sys", "pll5_video_div",
- "dummy", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0",
+ "video_27m", "axi", "enfc", "ipu1_di0", "ipu1_di1", "ipu2_di0",
"ipu2_di1", "ahb", "ipg", "ipg_per", "ckil", "pll4_audio_div", };
static const char *cko2_sels[] = {
"mmdc_ch0_axi", "mmdc_ch1_axi", "usdhc4", "usdhc1",
--
2.17.0
^ permalink raw reply related
* [PATCH] clk: imx6: fix video_27m parent for IMX6SX_CLK_CKO1_SEL
From: Philipp Puschmann @ 2018-06-08 10:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOMZO5B-T2UWdv-tf5vsCuRQ6f_o1gw1pAn-b6h9zfmi5ng4Ug@mail.gmail.com>
I screwed up the title: IMX6SX_CLK_CKO1_SEL instead of IMX6QDL_CLK_CKO1_SEL
I have resent the patch with correct title. Sorry for the inconvenience.
Am 06.06.2018 um 15:07 schrieb Fabio Estevam:
> On Wed, Jun 6, 2018 at 6:29 AM, Philipp Puschmann <pp@emlix.com> wrote:
>> q/dl datasheets list the 5th selection value for ck01_sel as
>> video_27M_clk_root.
>>
>> By replacing the dummy value we then can set IMX6QDL_CLK_VIDEO_27M
>> as parent for IMX6QDL_CLK_CKO1_SEL.
>>
>> Signed-off-by: Philipp Puschmann <pp@emlix.com>
>
> Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>
^ permalink raw reply
* [PATCH] pinctrl: actions: Fix uninitialized error in owl_pin_config_set()
From: Manivannan Sadhasivam @ 2018-06-08 10:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528452347-23986-1-git-send-email-geert@linux-m68k.org>
On Fri, Jun 08, 2018 at 12:05:47PM +0200, Geert Uytterhoeven wrote:
> With gcc 4.1.2:
>
> drivers/pinctrl/actions/pinctrl-owl.c: In function ?owl_pin_config_set?:
> drivers/pinctrl/actions/pinctrl-owl.c:336: warning: ?ret? may be used uninitialized in this function
>
> Indeed, if num_configs is zero, the uninitialized value will be returned
> as an error code.
>
> Fix this by preinitializing it to zero.
>
> Fixes: 2242ddfbf4d699b5 ("pinctrl: actions: Add Actions S900 pinctrl driver")
> Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Thanks,
Mani
> ---
> drivers/pinctrl/actions/pinctrl-owl.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/pinctrl/actions/pinctrl-owl.c b/drivers/pinctrl/actions/pinctrl-owl.c
> index 76243caa08c630c0..b5c880b50bb371f5 100644
> --- a/drivers/pinctrl/actions/pinctrl-owl.c
> +++ b/drivers/pinctrl/actions/pinctrl-owl.c
> @@ -333,7 +333,7 @@ static int owl_pin_config_set(struct pinctrl_dev *pctrldev,
> unsigned long flags;
> unsigned int param;
> u32 reg, bit, width, arg;
> - int ret, i;
> + int ret = 0, i;
>
> info = &pctrl->soc->padinfo[pin];
>
> --
> 2.7.4
>
^ permalink raw reply
* [PATCH v2 09/16] irqchip/irq-mvebu-sei: add new driver for Marvell SEI
From: Miquel Raynal @ 2018-06-08 10:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <b11849f0-3593-51e1-8d4f-b05bfe6412a1@arm.com>
Hi Marc,
> > +static struct irq_chip mvebu_sei_ap_wired_irq_chip = {
> > + .name = "AP wired SEI",
> > + .irq_mask = mvebu_sei_mask_irq,
> > + .irq_unmask = mvebu_sei_unmask_irq,
> > + .irq_eoi = irq_chip_eoi_parent,
> > + .irq_set_affinity = irq_chip_set_affinity_parent,
> > + .irq_set_type = irq_chip_set_type_parent,
>
> You seem to assume that this driver is purely dealing with edge
> interrupts. And yet you pass the request directly to the parrent. What
> does it mean? Shouldn't you at least check that this is an edge request
> and fail otherwise?
MSI are rising-edge interrupts while wired ones are level (high)
interrupts. I will correct this.
> > + irq_chip = &mvebu_sei_ap_wired_irq_chip;
> > + hwirq = fwspec->param[0];
> > + } else {
> > + irq_chip = &mvebu_sei_cp_msi_irq_chip;
> > + spin_lock(&sei->cp_msi_lock);
>
> This could as well be a mutex.
Ok.
>
> > + hwirq = bitmap_find_free_region(sei->cp_msi_bitmap,
> > + SEI_IRQ_COUNT, 0);
>
> It is a bit weird that you're allocating from a 64bit bitmap while you
> only have 43 interrupts available... At the 44th interrupt, something
> bad is going to happen.
Absolutely, to solve this issue, I just had to:
s/SEI_IRQ_COUNT/sei->cp_interrupts.number/
>
> > + spin_unlock(&sei->cp_msi_lock);
> > + if (hwirq < 0)
> > + return -ENOSPC;
> > + }
> > +
[...]
> > +static void mvebu_sei_handle_cascade_irq(struct irq_desc *desc)
> > +{
> > + struct mvebu_sei *sei = irq_desc_get_handler_data(desc);
> > + struct irq_chip *chip = irq_desc_get_chip(desc);
> > + unsigned long irqmap, irq_bit;
> > + u32 reg_idx, virq, irqn;
> > +
> > + chained_irq_enter(chip, desc);
> > +
> > + /* Read both SEI cause registers (64 bits) */
> > + for (reg_idx = 0; reg_idx < SEI_IRQ_REG_COUNT; reg_idx++) {
> > + irqmap = readl_relaxed(sei->base + GICP_SECR(reg_idx));
> > +
> > + /* Call handler for each set bit */
> > + for_each_set_bit(irq_bit, &irqmap, SEI_IRQ_COUNT_PER_REG) {
> > + /* Cause Register gives the SEI number */
> > + irqn = irq_bit + reg_idx * SEI_IRQ_COUNT_PER_REG;
> > + /*
> > + * Finding Linux mapping (virq) needs the right domain
> > + * and the relative hwirq (which start at 0 in both
> > + * cases, while irqn is relative to all SEI interrupts).
> > + */
>
> It is a bit odd that you're virtualizing the hwirq number. The whole
> point of splitting hwirq from virq is that you don't have to do that and
> can use the the raw HW number. You're saving a tiny bit of memory in the
> irq_domain, at the expense of more complexity. I don't know if that's
> worth it...
>
> > + if (irqn < sei->ap_interrupts.number) {
> > + virq = irq_find_mapping(sei->ap_domain, irqn);
> > + } else {
> > + irqn -= sei->ap_interrupts.number;
> > + virq = irq_find_mapping(sei->cp_domain, irqn);
> > + }
> > +
> > + /* Call IRQ handler */
> > + generic_handle_irq(virq);
> > + }
> > +
> > + /* Clear interrupt indication by writing 1 to it */
> > + writel(irqmap, sei->base + GICP_SECR(reg_idx));
> > + }
> > +
> > + chained_irq_exit(chip, desc);
> > +}
[...]
> It feels like this patch could do with a total split:
>
> - Introduce the wired side of the driver
> - then the MSI part
>
> Drop the common domain callbacks, and treat the two domains separately.
> I seriously doubt there will be much of an overlap anyway.
Maybe I don't get what "saving a tiny bit of memory" really means in
this situation. What I am doing right now is duplicating hundreds of
lines and changing things like:
sei_hwirq = mvebu_sei_domain_to_sei_irq(..., hwirq)
into
sei_hwirq = sei->ap_interrupts.first + d->hwirq;
and
sei_hwirq = sei->cp_interrupts.first + d->hwirq;
because I still need to translate this hwirq number into an offset
within 64 bits. In fact, for each configuration/management operation
like clearing, checking or masking an interrupt, a bit must be twisted
within a pair of registers. This offset cannot be just the hwirq
number, it must be shifted depending on the IRQ domain/type of
interrupt.
I'm sorry but I will need more guidance on this because I don't see the
point in duplicating so much code that was factorized.
Thanks,
Miqu?l
^ permalink raw reply
* Do you need a loan?
From: Dr. Mohamad Hasmat Ali @ 2018-06-08 10:43 UTC (permalink / raw)
To: linux-arm-kernel
Salaam,
Do you need a business loan?
Do you need fund for a business idea you have but need huge funding?
Do you own a business and want to expand?
I am writing from a UAE based investment group.We are expanding our investment presence by granting loan as debt to fund projects outside UAE and to all viable and lucrative sectors at 4% interest per annum with up to 15 years repayment plan with 1 year grace period and also can fund projects from $300,000 to $2Billion USD.
Are you looking for fund for personal loan, large investment projects, commercial real estate, small business enterprises and government contracts, etc or If you have a project that needs funding, kindly revert to me via e-mail (mohamad_hasmat at yahoo.com)
Best Regards
Dr. Mohamad Hasmat Ali----Director Investment Services
Financial Street, Off Sheikh Zayed Road
Opp. Dubai Mall / Burj Khalifa
Downtown Dubai, Dubai, United Arab
mohamad_hasmat at yahoo.com
^ permalink raw reply
* [PATCH 11/17] arm64: dts: r8a77965: Add VSP instances
From: Laurent Pinchart @ 2018-06-08 11:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAMuHMdU7OyUvgNqbkjtHyb0LPjgTdPp_BBcGNbjiqfQUgCdMuw@mail.gmail.com>
Hi Geert,
On Friday, 8 June 2018 12:29:29 EEST Geert Uytterhoeven wrote:
> On Thu, Apr 26, 2018 at 11:11 PM, Laurent Pinchart wrote:
> > On Thursday, 26 April 2018 19:53:40 EEST Kieran Bingham wrote:
> >> The r8a77965 has 4 VSP instances.
> >>
> >> Based on a similar patch of the R8A7796 device tree
> >> by Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>.
> >>
> >> Signed-off-by: Takeshi Kihara <takeshi.kihara.df@renesas.com>
> >> [Kieran: Rebased to top of tree, fixed sort orders]
> >> Signed-off-by: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
> >> ---
> >>
> >> arch/arm64/boot/dts/renesas/r8a77965.dtsi | 44 +++++++++++++++++++++++
> >> 1 file changed, 44 insertions(+)
> >>
> >> diff --git a/arch/arm64/boot/dts/renesas/r8a77965.dtsi
> >> b/arch/arm64/boot/dts/renesas/r8a77965.dtsi index
> >> 1f44ed7c1b1c..e92e6b03333a 100644
> >> --- a/arch/arm64/boot/dts/renesas/r8a77965.dtsi
> >> +++ b/arch/arm64/boot/dts/renesas/r8a77965.dtsi
> >> @@ -1025,6 +1047,17 @@
> >> resets = <&cpg 611>;
> >> };
> >>
> >> + vspd0: vsp at fea20000 {
> >> + compatible = "renesas,vsp2";
> >> + reg = <0 0xfea20000 0 0x4000>;
> >
> > RFP2 has a CLUT so the register range needs to be extended. I'd recommend
> > covering the entire space (0x8000) even if no LUT or CLU module is
> > present.
>
> Even on V3H/V3M, which have some part of the CLUT, and could do
> with 0x5000?
>
> Note that this makes it overlap with fcpvd0 on all R-Car Gen3 SoCs,
> as mentioned by Simon on IRC.
My bad :-/ I'll submit fixes shortly.
> >> + interrupts = <GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>;
> >> + clocks = <&cpg CPG_MOD 623>;
> >> + power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
> >> + resets = <&cpg 623>;
> >> +
> >> + renesas,fcp = <&fcpvd0>;
> >> + };
> >> +
> >> fcpvd0: fcp at fea27000 {
> >> compatible = "renesas,fcpv";
> >> reg = <0 0xfea27000 0 0x200>;
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [PATCH] arm64: Fix syscall restarting around signal suppressed by tracer
From: Catalin Marinas @ 2018-06-08 12:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528371125-24505-1-git-send-email-Dave.Martin@arm.com>
On Thu, Jun 07, 2018 at 12:32:05PM +0100, Dave P Martin wrote:
> Commit 17c2895 ("arm64: Abstract syscallno manipulation") abstracts
> out the pt_regs.syscallno value for a syscall cancelled by a tracer
> as NO_SYSCALL, and provides helpers to set and check for this
> condition. However, the way this was implemented has the
> unintended side-effect of disabling part of the syscall restart
> logic.
>
> This comes about because the second in_syscall() check in
> do_signal() re-evaluates the "in a syscall" condition based on the
> updated pt_regs instead of the original pt_regs. forget_syscall()
> is explicitly called prior to the second check in order to prevent
> restart logic in the ret_to_user path being spuriously triggered,
> which means that the second in_syscall() check always yields false.
>
> This triggers a failure in
> tools/testing/selftests/seccomp/seccomp_bpf.c, when using ptrace to
> suppress a signal that interrups a nanosleep() syscall.
>
> Misbehaviour of this type is only expected in the case where a
> tracer suppresses a signal and the target process is either being
> single-stepped or the interrupted syscall attempts to restart via
> -ERESTARTBLOCK.
>
> This patch restores the old behaviour by performing the
> in_syscall() check only once at the start of the function.
>
> Fixes: 17c289586009 ("arm64: Abstract syscallno manipulation")
> Signed-off-by: Dave Martin <Dave.Martin@arm.com>
> Reported-by: Sumit Semwal <sumit.semwal@linaro.org>
> Cc: Will Deacon <will.deacon@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: <stable@vger.kernel.org> # 4.14.x-
Applied. Thanks.
--
Catalin
^ permalink raw reply
* [PATCH v2 1/2] media: v4l2-ctrl: Add control for VP9 profile
From: Stanimir Varbanov @ 2018-06-08 12:56 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <a16dca32-4198-72c1-cf22-83f18a8cfcb6@xs4all.nl>
Hi Hans,
On 06/08/2018 12:29 PM, Hans Verkuil wrote:
> On 05/30/2018 09:16 AM, Keiichi Watanabe wrote:
>> Add a new control V4L2_CID_MPEG_VIDEO_VP9_PROFILE for selecting desired
>> profile for VP9 encoder and querying for supported profiles by VP9 encoder
>> or decoder.
>>
>> An existing control V4L2_CID_MPEG_VIDEO_VPX_PROFILE cannot be
>> used for querying since it is not a menu control but an integer
>> control, which cannot return an arbitrary set of supported profiles.
>>
>> The new control V4L2_CID_MPEG_VIDEO_VP9_PROFILE is a menu control as
>> with controls for other codec profiles. (e.g. H264)
>
> Please ignore my reply to patch 2/2. I looked at this a bit more and what you
> should do is to change the type of V4L2_CID_MPEG_VIDEO_VPX_PROFILE to enum.
>
> All other codec profile controls are all enums, so the fact that VPX_PROFILE
> isn't is a bug. Changing the type should not cause any problems since the same
> control value is used when you set the control.
>
> Sylwester: I see that s5p-mfc uses this control, but it is explicitly added
> as an integer type control, so the s5p-mfc driver should not be affected by
> changing the type of this control.
>
> Stanimir: this will slightly change the venus driver, but since it is a very
> recent driver I think we can get away with changing the core type of the
> VPX_PROFILE control. I think that's better than ending up with two controls
> that do the same thing.
I agree. Actually the changes shouldn't be so much in venus driver.
--
regards,
Stan
^ permalink raw reply
* [PATCH] clk: imx6: fix video_27m parent for IMX6QDL_CLK_CKO1_SEL
From: Fabio Estevam @ 2018-06-08 13:00 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180608101924.31195-1-pp@emlix.com>
Hi Philipp,
On Fri, Jun 8, 2018 at 7:19 AM, Philipp Puschmann <pp@emlix.com> wrote:
> q/dl datasheets list the 5th selection value for ck01_sel as
> video_27M_clk_root.
>
> By replacing the dummy value we then can set IMX6QDL_CLK_VIDEO_27M
> as parent for IMX6QDL_CLK_CKO1_SEL.
>
> Signed-off-by: Philipp Puschmann <pp@emlix.com>
You could still have added my Reviewed-by tag that I sent previously :-)
Here it goes:
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
Also in the future, when posting a new version of a patch, please mark
it as such:
[PATCH v2] clk: imx6: fix video_27m parent for IMX6QDL_CLK_CKO1_SEL
and write below the --- line what are the changes in this new version.
Thanks
^ permalink raw reply
* [PATCH v2 11/16] irqchip/irq-mvebu-icu: add support for System Error Interrupts (SEI)
From: Miquel Raynal @ 2018-06-08 13:08 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <cd000f57-e01f-e5b9-77f6-baf4e8f45551@arm.com>
Hi Marc,
Thank you for the review.
On Wed, 23 May 2018 15:23:48 +0100, Marc Zyngier <marc.zyngier@arm.com>
wrote:
> On 22/05/18 10:40, Miquel Raynal wrote:
> > An SEI driver provides an MSI domain through which it is possible to
> > raise SEIs.
> >
> > Handle the NSR probe function in a more generic way to support other
> > type of interrupts (ie. the SEIs).
> >
> > For clarity we do not use tree IRQ domains for now but linear ones
> > instead, allocating the 207 ICU lines for each interrupt group.
>
> What's the rational for not using trees? Because that's effectively a
> 100% overhead...
There is none.
I had a look at how to do it.
In the ICU driver I would like to just drop the nvec parameter (number
of interrupts in the domain) when calling
platform_msi_create_device_domain().
The above function would call irq_domain_create_hierarchy() which would
create a tree domain instead of a linear one because of nvec being 0.
However, there is a check in platform_msi_alloc_priv_data() (also
called by platform_msi_create_device_domain()) that will error out if
nvec is null.
I'm not 100% sure this is safe but I don't see the point of
prohibiting nvec to be null here. So would you accept this
change?
--- a/drivers/base/platform-msi.c
+++ b/drivers/base/platform-msi.c
@@ -203,7 +203,7 @@ platform_msi_alloc_priv_data(struct device *dev,
unsigned int nvec,
* accordingly (which would impact the max number of MSI
* capable devices).
*/
- if (!dev->msi_domain || !write_msi_msg || !nvec || nvec > MAX_DEV_MSIS)
+ if (!dev->msi_domain || !write_msi_msg || nvec > MAX_DEV_MSIS)
return ERR_PTR(-EINVAL);
if (dev->msi_domain->bus_token != DOMAIN_BUS_PLATFORM_MSI) {
>
> > Reallocating an ICU slot is prevented by the use of an ICU-wide bitmap.
> >
> > Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
> > ---
[...]
> > @@ -131,7 +160,8 @@ static int
> > mvebu_icu_irq_domain_translate(struct irq_domain *d, struct irq_fwspec *fwspec,
> > unsigned long *hwirq, unsigned int *type)
> > {
> > - struct mvebu_icu *icu = platform_msi_get_host_data(d);
> > + struct mvebu_icu_msi_data *msi_data = platform_msi_get_host_data(d);
> > + struct mvebu_icu *icu = msi_data->icu;
> > unsigned int param_count = icu->legacy_bindings ? 3 : 2;
> >
> > /* Check the count of the parameters in dt */
> > @@ -172,7 +202,9 @@ mvebu_icu_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
> > int err;
> > unsigned long hwirq;
> > struct irq_fwspec *fwspec = args;
> > - struct mvebu_icu *icu = platform_msi_get_host_data(domain);
> > + struct mvebu_icu_msi_data *msi_data =
> > + platform_msi_get_host_data(domain);
> > + struct mvebu_icu *icu = msi_data->icu;
> > struct mvebu_icu_irq_data *icu_irqd;
> >
> > icu_irqd = kmalloc(sizeof(*icu_irqd), GFP_KERNEL);
> > @@ -186,16 +218,22 @@ mvebu_icu_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
> > goto free_irqd;
> > }
> >
> > + spin_lock(&icu->msi_lock);
> > + err = bitmap_allocate_region(icu->msi_bitmap, hwirq, 0);
> > + spin_unlock(&icu->msi_lock);
>
> This (and the freeing counterpart) could deserve a couple of helpers.
Sure.
>
> > + if (err < 0)
> > + goto free_irqd;
> > +
> > if (icu->legacy_bindings)
> > icu_irqd->icu_group = fwspec->param[0];
> > else
> > - icu_irqd->icu_group = ICU_GRP_NSR;
> > + icu_irqd->icu_group = msi_data->subset_data->icu_group;
> > icu_irqd->icu = icu;
> >
> > err = platform_msi_domain_alloc(domain, virq, nr_irqs);
> > if (err) {
> > dev_err(icu->dev, "failed to allocate ICU interrupt in parent domain\n");
> > - goto free_irqd;
> > + goto free_bitmap;
> > }
> >
> > /* Make sure there is no interrupt left pending by the firmware */
[...]
> > @@ -268,9 +332,30 @@ static int mvebu_icu_subset_probe(struct platform_device *pdev)
> > return 0;
> > }
> >
> > +static const struct mvebu_icu_subset_data mvebu_icu_nsr_subset_data = {
> > + .icu_group = ICU_GRP_NSR,
> > + .offset_set_ah = ICU_SETSPI_NSR_AH,
> > + .offset_set_al = ICU_SETSPI_NSR_AL,
> > + .offset_clr_ah = ICU_CLRSPI_NSR_AH,
> > + .offset_clr_al = ICU_CLRSPI_NSR_AL,
> > +};
> > +
> > +static const struct mvebu_icu_subset_data mvebu_icu_sei_subset_data = {
> > + .icu_group = ICU_GRP_SEI,
> > + .offset_set_ah = ICU_SET_SEI_AH,
> > + .offset_set_al = ICU_SET_SEI_AL,
> > + .offset_clr_ah = ICU_CLR_SEI_AH,
> > + .offset_clr_al = ICU_CLR_SEI_AL,
>
> I thought SEI was edge only, given what you do in mvebu_icu_init.
> Confused...
AFAIK, the ICU can produce both level and edge MSI. Currently,
when it comes to SEI, we don't use the .offset_clr_a[hl] entries
because the SEI block expects edge-MSIs, but I thought useful to fill
them anyway. I will remove them both to avoid the confusion.
Thanks,
Miqu?l
^ permalink raw reply
* [PATCHv4 06/10] arm64: add basic pointer authentication support
From: Kristina Martsenko @ 2018-06-08 13:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20180503132031.25705-7-mark.rutland@arm.com>
Hi Mark,
On 03/05/18 14:20, Mark Rutland wrote:
> This patch adds basic support for pointer authentication, allowing
> userspace to make use of APIAKey. The kernel maintains an APIAKey value
> for each process (shared by all threads within), which is initialised to
> a random value at exec() time.
>
> To describe that address authentication instructions are available, the
> ID_AA64ISAR0.{APA,API} fields are exposed to userspace. A new hwcap,
> APIA, is added to describe that the kernel manages APIAKey.
>
> Instructions using other keys (APIBKey, APDAKey, APDBKey) are disabled,
> and will behave as NOPs. These may be made use of in future patches.
>
> No support is added for the generic key (APGAKey), though this cannot be
> trapped or made to behave as a NOP. Its presence is not advertised with
> a hwcap.
>
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
> Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>
> ---
> arch/arm64/include/asm/mmu.h | 5 +++
> arch/arm64/include/asm/mmu_context.h | 11 ++++-
> arch/arm64/include/asm/pointer_auth.h | 75 +++++++++++++++++++++++++++++++++++
> arch/arm64/include/uapi/asm/hwcap.h | 1 +
> arch/arm64/kernel/cpufeature.c | 9 +++++
> arch/arm64/kernel/cpuinfo.c | 1 +
> 6 files changed, 101 insertions(+), 1 deletion(-)
> create mode 100644 arch/arm64/include/asm/pointer_auth.h
>
> diff --git a/arch/arm64/include/asm/mmu.h b/arch/arm64/include/asm/mmu.h
> index dd320df0d026..f6480ea7b0d5 100644
> --- a/arch/arm64/include/asm/mmu.h
> +++ b/arch/arm64/include/asm/mmu.h
> @@ -25,10 +25,15 @@
>
> #ifndef __ASSEMBLY__
>
> +#include <asm/pointer_auth.h>
> +
> typedef struct {
> atomic64_t id;
> void *vdso;
> unsigned long flags;
> +#ifdef CONFIG_ARM64_PTR_AUTH
> + struct ptrauth_keys ptrauth_keys;
> +#endif
> } mm_context_t;
>
> /*
> diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h
> index 39ec0b8a689e..83eadbc6b946 100644
> --- a/arch/arm64/include/asm/mmu_context.h
> +++ b/arch/arm64/include/asm/mmu_context.h
> @@ -168,7 +168,14 @@ static inline void cpu_replace_ttbr1(pgd_t *pgdp)
> #define destroy_context(mm) do { } while(0)
> void check_and_switch_context(struct mm_struct *mm, unsigned int cpu);
>
> -#define init_new_context(tsk,mm) ({ atomic64_set(&(mm)->context.id, 0); 0; })
> +static inline int init_new_context(struct task_struct *tsk,
> + struct mm_struct *mm)
> +{
> + atomic64_set(&mm->context.id, 0);
> + mm_ctx_ptrauth_init(&mm->context);
> +
> + return 0;
> +}>
> #ifdef CONFIG_ARM64_SW_TTBR0_PAN
> static inline void update_saved_ttbr0(struct task_struct *tsk,
> @@ -216,6 +223,8 @@ static inline void __switch_mm(struct mm_struct *next)
> return;
> }
>
> + mm_ctx_ptrauth_switch(&next->context);
> +
> check_and_switch_context(next, cpu);
> }
It seems you've removed arch_dup_mmap here (as Catalin suggested [1]),
but forgotten to move the key initialization from init_new_context to
arch_bprm_mm_init. In my tests I'm seeing child processes get different
keys than the parent after a fork().
Kristina
[1] https://lkml.org/lkml/2018/4/25/506
^ permalink raw reply
* [PATCH v2 0/5] add virt-dma support for imx-sdma
From: Robin Gong @ 2018-06-08 13:44 UTC (permalink / raw)
To: linux-arm-kernel
The legacy sdma driver has below limitations or drawbacks:
1. Hardcode the max BDs number as "PAGE_SIZE / sizeof(*)", and alloc
one page size for one channel regardless of only few BDs needed
most time. But in few cases, the max PAGE_SIZE maybe not enough.
2. One SDMA channel can't stop immediatley once channel disabled which
means SDMA interrupt may come in after this channel terminated.There
are some patches for this corner case such as commit "2746e2c389f9",
but not cover non-cyclic.
The common virt-dma overcomes the above limitations. It can alloc bd
dynamically and free bd once this tx transfer done. No memory wasted or
maximum limititation here, only depends on how many memory can be requested
from kernel. For No.2, such issue can be workaround by checking if there
is available descript("sdmac->desc") now once the unwanted interrupt
coming. At last the common virt-dma is easier for sdma driver maintain.
Change from v1:
1. split v1 patch into 5 patches.
2. remove some unnecessary condition check.
3. remove unneccessary 'pending' list.
Robin Gong (5):
dmaengine: imx-sdma: add virt-dma support
Revert "dmaengine: imx-sdma: fix pagefault when channel is disabled
during interrupt"
dmaengine: imx-sdma: remove usless lock
dmaengine: imx-sdma: remove the maximum limation for bd numbers
dmaengine: imx-sdma: add sdma_transfer_init to decrease code overlap
drivers/dma/Kconfig | 1 +
drivers/dma/imx-sdma.c | 392 ++++++++++++++++++++++++++++---------------------
2 files changed, 227 insertions(+), 166 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH v2 1/5] dmaengine: imx-sdma: add virt-dma support
From: Robin Gong @ 2018-06-08 13:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528465490-19684-1-git-send-email-yibin.gong@nxp.com>
The legacy sdma driver has below limitations or drawbacks:
1. Hardcode the max BDs number as "PAGE_SIZE / sizeof(*)", and alloc
one page size for one channel regardless of only few BDs needed
most time. But in few cases, the max PAGE_SIZE maybe not enough.
2. One SDMA channel can't stop immediatley once channel disabled which
means SDMA interrupt may come in after this channel terminated.There
are some patches for this corner case such as commit "2746e2c389f9",
but not cover non-cyclic.
The common virt-dma overcomes the above limitations. It can alloc bd
dynamically and free bd once this tx transfer done. No memory wasted or
maximum limititation here, only depends on how many memory can be requested
from kernel. For No.2, such issue can be workaround by checking if there
is available descript("sdmac->desc") now once the unwanted interrupt
coming. At last the common virt-dma is easier for sdma driver maintain.
The main changes as below:
--new "sdma_desc" structure containing virt_dma_desc and some members
which moved from "sdma_channel" such as "num_bd","bd_phys","bd",etc,
since multi descriptors may exist on virtual dma framework
rather than only one as before.
--remove some members of "sdma_channel" structure since it's handled
by virtual dma common framework, such as "tasklet", "dma_chan",etc.
--add specific BD0 for channel0 since such bd descriptor is must and
basic for other dma channel, no need alloc/free as other channel,so
request it during probe.
--remove sdma_request_channel(),sdma_tx_submit(),etc.
--alloc/free bd descriptor added and code changes for virtual dma.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/Kconfig | 1 +
drivers/dma/imx-sdma.c | 332 ++++++++++++++++++++++++++++++++-----------------
2 files changed, 220 insertions(+), 113 deletions(-)
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index ca1680a..d4a4230 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -250,6 +250,7 @@ config IMX_SDMA
tristate "i.MX SDMA support"
depends on ARCH_MXC
select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
help
Support the i.MX SDMA engine. This engine is integrated into
Freescale i.MX25/31/35/51/53/6 chips.
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index ccd03c3..8d0c1fd 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -48,6 +48,7 @@
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include "dmaengine.h"
+#include "virt-dma.h"
/* SDMA registers */
#define SDMA_H_C0PTR 0x000
@@ -296,6 +297,31 @@ struct sdma_context_data {
struct sdma_engine;
/**
+ * struct sdma_desc - descriptor structor for one transfer
+ * @vd descriptor for virt dma
+ * @num_bd max NUM_BD. number of descriptors currently handling
+ * @buf_tail ID of the buffer that was processed
+ * @buf_ptail ID of the previous buffer that was processed
+ * @period_len period length, used in cyclic.
+ * @chn_real_count the real count updated from bd->mode.count
+ * @chn_count the transfer count setuped
+ * @sdmac sdma_channel pointer
+ * @bd pointer of alloced bd
+ */
+struct sdma_desc {
+ struct virt_dma_desc vd;
+ unsigned int num_bd;
+ dma_addr_t bd_phys;
+ unsigned int buf_tail;
+ unsigned int buf_ptail;
+ unsigned int period_len;
+ unsigned int chn_real_count;
+ unsigned int chn_count;
+ struct sdma_channel *sdmac;
+ struct sdma_buffer_descriptor *bd;
+};
+
+/**
* struct sdma_channel - housekeeping for a SDMA channel
*
* @sdma pointer to the SDMA engine for this channel
@@ -305,11 +331,10 @@ struct sdma_engine;
* @event_id0 aka dma request line
* @event_id1 for channels that use 2 events
* @word_size peripheral access size
- * @buf_tail ID of the buffer that was processed
- * @buf_ptail ID of the previous buffer that was processed
- * @num_bd max NUM_BD. number of descriptors currently handling
*/
struct sdma_channel {
+ struct virt_dma_chan vc;
+ struct sdma_desc *desc;
struct sdma_engine *sdma;
unsigned int channel;
enum dma_transfer_direction direction;
@@ -317,12 +342,6 @@ struct sdma_channel {
unsigned int event_id0;
unsigned int event_id1;
enum dma_slave_buswidth word_size;
- unsigned int buf_tail;
- unsigned int buf_ptail;
- unsigned int num_bd;
- unsigned int period_len;
- struct sdma_buffer_descriptor *bd;
- dma_addr_t bd_phys;
unsigned int pc_from_device, pc_to_device;
unsigned int device_to_device;
unsigned long flags;
@@ -330,13 +349,10 @@ struct sdma_channel {
unsigned long event_mask[2];
unsigned long watermark_level;
u32 shp_addr, per_addr;
- struct dma_chan chan;
spinlock_t lock;
- struct dma_async_tx_descriptor desc;
enum dma_status status;
unsigned int chn_count;
unsigned int chn_real_count;
- struct tasklet_struct tasklet;
struct imx_dma_data data;
bool enabled;
};
@@ -398,6 +414,8 @@ struct sdma_engine {
u32 spba_start_addr;
u32 spba_end_addr;
unsigned int irq;
+ dma_addr_t bd0_phys;
+ struct sdma_buffer_descriptor *bd0;
};
static struct sdma_driver_data sdma_imx31 = {
@@ -632,7 +650,7 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
u32 address)
{
- struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
+ struct sdma_buffer_descriptor *bd0 = sdma->bd0;
void *buf_virt;
dma_addr_t buf_phys;
int ret;
@@ -688,6 +706,35 @@ static void sdma_event_disable(struct sdma_channel *sdmac, unsigned int event)
writel_relaxed(val, sdma->regs + chnenbl);
}
+static struct sdma_desc *to_sdma_desc(struct dma_async_tx_descriptor *t)
+{
+ return container_of(t, struct sdma_desc, vd.tx);
+}
+
+static void sdma_start_desc(struct sdma_channel *sdmac)
+{
+ struct virt_dma_desc *vd = vchan_next_desc(&sdmac->vc);
+ struct sdma_desc *desc;
+ struct sdma_engine *sdma = sdmac->sdma;
+ int channel = sdmac->channel;
+
+ if (!vd) {
+ sdmac->desc = NULL;
+ return;
+ }
+ sdmac->desc = desc = to_sdma_desc(&vd->tx);
+ /*
+ * Do not delete the node in desc_issued list in cyclic mode, otherwise
+ * the desc alloced will never be freed in vchan_dma_desc_free_list
+ */
+ if (!(sdmac->flags & IMX_DMA_SG_LOOP))
+ list_del(&vd->node);
+
+ sdma->channel_control[channel].base_bd_ptr = desc->bd_phys;
+ sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
+ sdma_enable_channel(sdma, sdmac->channel);
+}
+
static void sdma_update_channel_loop(struct sdma_channel *sdmac)
{
struct sdma_buffer_descriptor *bd;
@@ -706,8 +753,10 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* loop mode. Iterate over descriptors, re-setup them and
* call callback function.
*/
- while (1) {
- bd = &sdmac->bd[sdmac->buf_tail];
+ while (sdmac->desc) {
+ struct sdma_desc *desc = sdmac->desc;
+
+ bd = &desc->bd[desc->buf_tail];
if (bd->mode.status & BD_DONE)
break;
@@ -723,11 +772,11 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* the number of bytes present in the current buffer descriptor.
*/
- sdmac->chn_real_count = bd->mode.count;
+ desc->chn_real_count = bd->mode.count;
bd->mode.status |= BD_DONE;
- bd->mode.count = sdmac->period_len;
- sdmac->buf_ptail = sdmac->buf_tail;
- sdmac->buf_tail = (sdmac->buf_tail + 1) % sdmac->num_bd;
+ bd->mode.count = desc->period_len;
+ desc->buf_ptail = desc->buf_tail;
+ desc->buf_tail = (desc->buf_tail + 1) % desc->num_bd;
/*
* The callback is called from the interrupt context in order
@@ -736,40 +785,36 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
* executed.
*/
- dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
+ dmaengine_desc_get_callback_invoke(&desc->vd.tx, NULL);
if (error)
sdmac->status = old_status;
}
}
-static void mxc_sdma_handle_channel_normal(unsigned long data)
+static void mxc_sdma_handle_channel_normal(struct sdma_channel *data)
{
struct sdma_channel *sdmac = (struct sdma_channel *) data;
struct sdma_buffer_descriptor *bd;
int i, error = 0;
- sdmac->chn_real_count = 0;
+ sdmac->desc->chn_real_count = 0;
/*
* non loop mode. Iterate over all descriptors, collect
* errors and call callback function
*/
- for (i = 0; i < sdmac->num_bd; i++) {
- bd = &sdmac->bd[i];
+ for (i = 0; i < sdmac->desc->num_bd; i++) {
+ bd = &sdmac->desc->bd[i];
if (bd->mode.status & (BD_DONE | BD_RROR))
error = -EIO;
- sdmac->chn_real_count += bd->mode.count;
+ sdmac->desc->chn_real_count += bd->mode.count;
}
if (error)
sdmac->status = DMA_ERROR;
else
sdmac->status = DMA_COMPLETE;
-
- dma_cookie_complete(&sdmac->desc);
-
- dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
}
static irqreturn_t sdma_int_handler(int irq, void *dev_id)
@@ -785,13 +830,22 @@ static irqreturn_t sdma_int_handler(int irq, void *dev_id)
while (stat) {
int channel = fls(stat) - 1;
struct sdma_channel *sdmac = &sdma->channel[channel];
-
- if (sdmac->flags & IMX_DMA_SG_LOOP)
- sdma_update_channel_loop(sdmac);
- else
- tasklet_schedule(&sdmac->tasklet);
+ struct sdma_desc *desc;
+
+ spin_lock(&sdmac->vc.lock);
+ desc = sdmac->desc;
+ if (desc) {
+ if (sdmac->flags & IMX_DMA_SG_LOOP) {
+ sdma_update_channel_loop(sdmac);
+ } else {
+ mxc_sdma_handle_channel_normal(sdmac);
+ vchan_cookie_complete(&desc->vd);
+ sdma_start_desc(sdmac);
+ }
+ }
__clear_bit(channel, &stat);
+ spin_unlock(&sdmac->vc.lock);
}
return IRQ_HANDLED;
@@ -897,7 +951,7 @@ static int sdma_load_context(struct sdma_channel *sdmac)
int channel = sdmac->channel;
int load_address;
struct sdma_context_data *context = sdma->context;
- struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
+ struct sdma_buffer_descriptor *bd0 = sdma->bd0;
int ret;
unsigned long flags;
@@ -946,7 +1000,7 @@ static int sdma_load_context(struct sdma_channel *sdmac)
static struct sdma_channel *to_sdma_chan(struct dma_chan *chan)
{
- return container_of(chan, struct sdma_channel, chan);
+ return container_of(chan, struct sdma_channel, vc.chan);
}
static int sdma_disable_channel(struct dma_chan *chan)
@@ -968,7 +1022,16 @@ static int sdma_disable_channel(struct dma_chan *chan)
static int sdma_disable_channel_with_delay(struct dma_chan *chan)
{
+ struct sdma_channel *sdmac = to_sdma_chan(chan);
+ unsigned long flags;
+ LIST_HEAD(head);
+
sdma_disable_channel(chan);
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
+ vchan_get_all_descriptors(&sdmac->vc, &head);
+ sdmac->desc = NULL;
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
+ vchan_dma_desc_free_list(&sdmac->vc, &head);
/*
* According to NXP R&D team a delay of one BD SDMA cost time
@@ -1097,42 +1160,55 @@ static int sdma_set_channel_priority(struct sdma_channel *sdmac,
return 0;
}
-static int sdma_request_channel(struct sdma_channel *sdmac)
+static int sdma_request_channel0(struct sdma_engine *sdma)
{
- struct sdma_engine *sdma = sdmac->sdma;
- int channel = sdmac->channel;
- int ret = -EBUSY;
+ int ret = 0;
- sdmac->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys,
+ sdma->bd0 = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdma->bd0_phys,
GFP_KERNEL);
- if (!sdmac->bd) {
+ if (!sdma->bd0) {
ret = -ENOMEM;
goto out;
}
- sdma->channel_control[channel].base_bd_ptr = sdmac->bd_phys;
- sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
+ sdma->channel_control[0].base_bd_ptr = sdma->bd0_phys;
+ sdma->channel_control[0].current_bd_ptr = sdma->bd0_phys;
- sdma_set_channel_priority(sdmac, MXC_SDMA_DEFAULT_PRIORITY);
+ sdma_set_channel_priority(&sdma->channel[0], MXC_SDMA_DEFAULT_PRIORITY);
return 0;
out:
-
return ret;
}
-static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx)
+static int sdma_alloc_bd(struct sdma_desc *desc)
{
- unsigned long flags;
- struct sdma_channel *sdmac = to_sdma_chan(tx->chan);
- dma_cookie_t cookie;
+ u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
+ int ret = 0;
- spin_lock_irqsave(&sdmac->lock, flags);
+ desc->bd = dma_zalloc_coherent(NULL, bd_size, &desc->bd_phys,
+ GFP_KERNEL);
+ if (!desc->bd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+out:
+
+ return ret;
+}
- cookie = dma_cookie_assign(tx);
+static void sdma_free_bd(struct sdma_desc *desc)
+{
+ u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
- spin_unlock_irqrestore(&sdmac->lock, flags);
+ dma_free_coherent(NULL, bd_size, desc->bd, desc->bd_phys);
+}
+
+static void sdma_desc_free(struct virt_dma_desc *vd)
+{
+ struct sdma_desc *desc = container_of(vd, struct sdma_desc, vd);
- return cookie;
+ sdma_free_bd(desc);
+ kfree(desc);
}
static int sdma_alloc_chan_resources(struct dma_chan *chan)
@@ -1168,19 +1244,10 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
if (ret)
goto disable_clk_ipg;
- ret = sdma_request_channel(sdmac);
- if (ret)
- goto disable_clk_ahb;
-
ret = sdma_set_channel_priority(sdmac, prio);
if (ret)
goto disable_clk_ahb;
- dma_async_tx_descriptor_init(&sdmac->desc, chan);
- sdmac->desc.tx_submit = sdma_tx_submit;
- /* txd.flags will be overwritten in prep funcs */
- sdmac->desc.flags = DMA_CTRL_ACK;
-
return 0;
disable_clk_ahb:
@@ -1195,7 +1262,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
- sdma_disable_channel(chan);
+ sdma_disable_channel_with_delay(chan);
if (sdmac->event_id0)
sdma_event_disable(sdmac, sdmac->event_id0);
@@ -1207,8 +1274,6 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
sdma_set_channel_priority(sdmac, 0);
- dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys);
-
clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb);
}
@@ -1223,6 +1288,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
int ret, i, count;
int channel = sdmac->channel;
struct scatterlist *sg;
+ struct sdma_desc *desc;
if (sdmac->status == DMA_IN_PROGRESS)
return NULL;
@@ -1230,9 +1296,20 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
sdmac->flags = 0;
- sdmac->buf_tail = 0;
- sdmac->buf_ptail = 0;
- sdmac->chn_real_count = 0;
+ desc = kzalloc((sizeof(*desc)), GFP_KERNEL);
+ if (!desc)
+ goto err_out;
+
+ desc->buf_tail = 0;
+ desc->buf_ptail = 0;
+ desc->sdmac = sdmac;
+ desc->num_bd = sg_len;
+ desc->chn_real_count = 0;
+
+ if (sdma_alloc_bd(desc)) {
+ kfree(desc);
+ goto err_out;
+ }
dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
sg_len, channel);
@@ -1240,18 +1317,18 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
sdmac->direction = direction;
ret = sdma_load_context(sdmac);
if (ret)
- goto err_out;
+ goto err_bd_out;
if (sg_len > NUM_BD) {
dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
channel, sg_len, NUM_BD);
ret = -EINVAL;
- goto err_out;
+ goto err_bd_out;
}
- sdmac->chn_count = 0;
+ desc->chn_count = 0;
for_each_sg(sgl, sg, sg_len, i) {
- struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
+ struct sdma_buffer_descriptor *bd = &desc->bd[i];
int param;
bd->buffer_addr = sg->dma_address;
@@ -1262,33 +1339,33 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
dev_err(sdma->dev, "SDMA channel %d: maximum bytes for sg entry exceeded: %d > %d\n",
channel, count, 0xffff);
ret = -EINVAL;
- goto err_out;
+ goto err_bd_out;
}
bd->mode.count = count;
- sdmac->chn_count += count;
+ desc->chn_count += count;
if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
ret = -EINVAL;
- goto err_out;
+ goto err_bd_out;
}
switch (sdmac->word_size) {
case DMA_SLAVE_BUSWIDTH_4_BYTES:
bd->mode.command = 0;
if (count & 3 || sg->dma_address & 3)
- return NULL;
+ goto err_bd_out;
break;
case DMA_SLAVE_BUSWIDTH_2_BYTES:
bd->mode.command = 2;
if (count & 1 || sg->dma_address & 1)
- return NULL;
+ goto err_bd_out;
break;
case DMA_SLAVE_BUSWIDTH_1_BYTE:
bd->mode.command = 1;
break;
default:
- return NULL;
+ goto err_bd_out;
}
param = BD_DONE | BD_EXTD | BD_CONT;
@@ -1307,10 +1384,10 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
bd->mode.status = param;
}
- sdmac->num_bd = sg_len;
- sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
-
- return &sdmac->desc;
+ return vchan_tx_prep(&sdmac->vc, &desc->vd, flags);
+err_bd_out:
+ sdma_free_bd(desc);
+ kfree(desc);
err_out:
sdmac->status = DMA_ERROR;
return NULL;
@@ -1326,6 +1403,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
int num_periods = buf_len / period_len;
int channel = sdmac->channel;
int ret, i = 0, buf = 0;
+ struct sdma_desc *desc;
dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel);
@@ -1334,31 +1412,43 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
sdmac->status = DMA_IN_PROGRESS;
- sdmac->buf_tail = 0;
- sdmac->buf_ptail = 0;
- sdmac->chn_real_count = 0;
- sdmac->period_len = period_len;
+ desc = kzalloc((sizeof(*desc)), GFP_KERNEL);
+ if (!desc)
+ goto err_out;
+
+ desc->buf_tail = 0;
+ desc->buf_ptail = 0;
+ desc->sdmac = sdmac;
+ desc->num_bd = num_periods;
+ desc->chn_real_count = 0;
+ desc->period_len = period_len;
sdmac->flags |= IMX_DMA_SG_LOOP;
sdmac->direction = direction;
+
+ if (sdma_alloc_bd(desc)) {
+ kfree(desc);
+ goto err_out;
+ }
+
ret = sdma_load_context(sdmac);
if (ret)
- goto err_out;
+ goto err_bd_out;
if (num_periods > NUM_BD) {
dev_err(sdma->dev, "SDMA channel %d: maximum number of sg exceeded: %d > %d\n",
channel, num_periods, NUM_BD);
- goto err_out;
+ goto err_bd_out;
}
if (period_len > 0xffff) {
dev_err(sdma->dev, "SDMA channel %d: maximum period size exceeded: %zu > %d\n",
channel, period_len, 0xffff);
- goto err_out;
+ goto err_bd_out;
}
while (buf < buf_len) {
- struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
+ struct sdma_buffer_descriptor *bd = &desc->bd[i];
int param;
bd->buffer_addr = dma_addr;
@@ -1366,7 +1456,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
bd->mode.count = period_len;
if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES)
- goto err_out;
+ goto err_bd_out;
if (sdmac->word_size == DMA_SLAVE_BUSWIDTH_4_BYTES)
bd->mode.command = 0;
else
@@ -1389,10 +1479,10 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
i++;
}
- sdmac->num_bd = num_periods;
- sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
-
- return &sdmac->desc;
+ return vchan_tx_prep(&sdmac->vc, &desc->vd, flags);
+err_bd_out:
+ sdma_free_bd(desc);
+ kfree(desc);
err_out:
sdmac->status = DMA_ERROR;
return NULL;
@@ -1432,12 +1522,30 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
u32 residue;
+ struct virt_dma_desc *vd;
+ struct sdma_desc *desc;
+ enum dma_status ret;
+ unsigned long flags;
- if (sdmac->flags & IMX_DMA_SG_LOOP)
- residue = (sdmac->num_bd - sdmac->buf_ptail) *
- sdmac->period_len - sdmac->chn_real_count;
- else
- residue = sdmac->chn_count - sdmac->chn_real_count;
+ ret = dma_cookie_status(chan, cookie, txstate);
+ if (ret == DMA_COMPLETE || !txstate)
+ return ret;
+
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
+ vd = vchan_find_desc(&sdmac->vc, cookie);
+ if (vd) {
+ desc = to_sdma_desc(&vd->tx);
+ if (sdmac->flags & IMX_DMA_SG_LOOP)
+ residue = (desc->num_bd - desc->buf_ptail) *
+ desc->period_len - desc->chn_real_count;
+ else
+ residue = desc->chn_count - desc->chn_real_count;
+ } else if (sdmac->desc && sdmac->desc->vd.tx.cookie == cookie) {
+ residue = sdmac->desc->chn_count - sdmac->desc->chn_real_count;
+ } else {
+ residue = 0;
+ }
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
residue);
@@ -1448,10 +1556,12 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
static void sdma_issue_pending(struct dma_chan *chan)
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
- struct sdma_engine *sdma = sdmac->sdma;
+ unsigned long flags;
- if (sdmac->status == DMA_IN_PROGRESS)
- sdma_enable_channel(sdma, sdmac->channel);
+ spin_lock_irqsave(&sdmac->vc.lock, flags);
+ if (vchan_issue_pending(&sdmac->vc) && !sdmac->desc)
+ sdma_start_desc(sdmac);
+ spin_unlock_irqrestore(&sdmac->vc.lock, flags);
}
#define SDMA_SCRIPT_ADDRS_ARRAY_SIZE_V1 34
@@ -1657,7 +1767,7 @@ static int sdma_init(struct sdma_engine *sdma)
for (i = 0; i < MAX_DMA_CHANNELS; i++)
writel_relaxed(0, sdma->regs + SDMA_CHNPRI_0 + i * 4);
- ret = sdma_request_channel(&sdma->channel[0]);
+ ret = sdma_request_channel0(sdma);
if (ret)
goto err_dma_alloc;
@@ -1821,20 +1931,15 @@ static int sdma_probe(struct platform_device *pdev)
sdmac->sdma = sdma;
spin_lock_init(&sdmac->lock);
- sdmac->chan.device = &sdma->dma_device;
- dma_cookie_init(&sdmac->chan);
sdmac->channel = i;
-
- tasklet_init(&sdmac->tasklet, mxc_sdma_handle_channel_normal,
- (unsigned long) sdmac);
+ sdmac->vc.desc_free = sdma_desc_free;
/*
* Add the channel to the DMAC list. Do not add channel 0 though
* because we need it internally in the SDMA driver. This also means
* that channel 0 in dmaengine counting matches sdma channel 1.
*/
if (i)
- list_add_tail(&sdmac->chan.device_node,
- &sdma->dma_device.channels);
+ vchan_init(&sdmac->vc, &sdma->dma_device);
}
ret = sdma_init(sdma);
@@ -1939,7 +2044,8 @@ static int sdma_remove(struct platform_device *pdev)
for (i = 0; i < MAX_DMA_CHANNELS; i++) {
struct sdma_channel *sdmac = &sdma->channel[i];
- tasklet_kill(&sdmac->tasklet);
+ tasklet_kill(&sdmac->vc.task);
+ sdma_free_chan_resources(&sdmac->vc.chan);
}
platform_set_drvdata(pdev, NULL);
--
2.7.4
^ permalink raw reply related
* [PATCH v2 2/5] Revert "dmaengine: imx-sdma: fix pagefault when channel is disabled during interrupt"
From: Robin Gong @ 2018-06-08 13:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1528465490-19684-1-git-send-email-yibin.gong@nxp.com>
This reverts commit 2746e2c389f9d50043d21e2204270403efb9d62f.
Don't need this patch anymore,since we can easily check 'sdmac->desc' to avoid
handling dma interrupt after channel disabled if virt-dma used.
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
drivers/dma/imx-sdma.c | 21 ---------------------
1 file changed, 21 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 8d0c1fd..d93b58f 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -354,7 +354,6 @@ struct sdma_channel {
unsigned int chn_count;
unsigned int chn_real_count;
struct imx_dma_data data;
- bool enabled;
};
#define IMX_DMA_SG_LOOP BIT(0)
@@ -615,14 +614,7 @@ static int sdma_config_ownership(struct sdma_channel *sdmac,
static void sdma_enable_channel(struct sdma_engine *sdma, int channel)
{
- unsigned long flags;
- struct sdma_channel *sdmac = &sdma->channel[channel];
-
writel(BIT(channel), sdma->regs + SDMA_H_START);
-
- spin_lock_irqsave(&sdmac->lock, flags);
- sdmac->enabled = true;
- spin_unlock_irqrestore(&sdmac->lock, flags);
}
/*
@@ -740,14 +732,6 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
struct sdma_buffer_descriptor *bd;
int error = 0;
enum dma_status old_status = sdmac->status;
- unsigned long flags;
-
- spin_lock_irqsave(&sdmac->lock, flags);
- if (!sdmac->enabled) {
- spin_unlock_irqrestore(&sdmac->lock, flags);
- return;
- }
- spin_unlock_irqrestore(&sdmac->lock, flags);
/*
* loop mode. Iterate over descriptors, re-setup them and
@@ -1008,15 +992,10 @@ static int sdma_disable_channel(struct dma_chan *chan)
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
int channel = sdmac->channel;
- unsigned long flags;
writel_relaxed(BIT(channel), sdma->regs + SDMA_H_STATSTOP);
sdmac->status = DMA_ERROR;
- spin_lock_irqsave(&sdmac->lock, flags);
- sdmac->enabled = false;
- spin_unlock_irqrestore(&sdmac->lock, flags);
-
return 0;
}
--
2.7.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox