* [PATCH v7 0/5] vfs: Non-blockling buffered fs read (page cache only)
From: Milosz Tanski @ 2015-03-16 18:27 UTC (permalink / raw)
To: linux-kernel
Cc: Christoph Hellwig, linux-fsdevel, linux-aio, Mel Gorman,
Volker Lendecke, Tejun Heo, Jeff Moyer, Theodore Ts'o,
Al Viro, linux-api, Michael Kerrisk, linux-arch, Dave Chinner,
Andrew Morton
This patchset introduces two new syscalls preadv2 and pwritev2. They are the
same syscalls as preadv and pwrite but with a flag argument. Additionally,
preadv2 implements an extra RWF_NONBLOCK flag.
The RWF_NONBLOCK flag in preadv2 introduces an ability to perform a
non-blocking read from regular files in buffered IO mode. This works by only
for those filesystems that have data in the page cache.
We discussed these changes at this year's LSF/MM summit in Boston. More details
on the Samba use case, the numbers, and presentation is available at this link:
https://lists.samba.org/archive/samba-technical/2015-March/106290.html
Please stayed tune for man pages patches and xfstest patches. They will be sent
as In-Reply-To.
Latest changes highlight:
- Drops RWF_DSYNC from pwritev2, per Christoph and Andrew
- Updated man pages
- Added tests for this functionality to xfstests, per Dave Chinner
- Based on top of 4.1-rc3
- Tests / numbers using samba and a CIFS client FIO engine
Forward looking:
Christoph committed to sending a separate patch series for the RWF_DSYNC for
pwritev2 implementation so it can be evaluated independently. This helps
with implementing userspace file servers for protocols that have a per operation
sync flag (CIFS).
Additionally, Christoph committed to implementing RWF_NONBLOCK for the write
case as well (in pwritev2) at a later date.
Background:
Using a threadpool to emulate non-blocking operations on regular buffered
files is a common pattern today (samba, libuv, etc...) Applications split the
work between network bound threads (epoll) and IO threadpool. Not every
application can use sendfile syscall (TLS / post-processing).
This common pattern leads to increased request latency. Latency can be due to
additional synchronization between the threads or fast (cached data) request
stuck behind slow request (large / uncached data).
The preadv2 syscall with RWF_NONBLOCK lets userspace applications bypass
enqueuing operation in the threadpool if it's already available in the
pagecache.
Performance numbers (newer Samba):
https://drive.google.com/file/d/0B3maCn0jCvYncndGbXJKbGlhejQ/view?usp=sharing
https://docs.google.com/spreadsheets/d/1GGTivi-MfZU0doMzomG4XUo9ioWtRvOGQ5FId042L6s/edit?usp=sharing
Performance number (older):
Some perf data generated using fio comparing the posix aio engine to a version
of the posix AIO engine that attempts to performs "fast" reads before
submitting the operations to the queue. This workflow is on ext4 partition on
raid0 (test / build-rig.) Simulating our database access patern workload using
16kb read accesses. Our database uses a home-spun posix aio like queue (samba
does the same thing.)
f1: ~73% rand read over mostly cached data (zipf med-size dataset)
f2: ~18% rand read over mostly un-cached data (uniform large-dataset)
f3: ~9% seq-read over large dataset
before:
f1:
bw (KB /s): min= 11, max= 9088, per=0.56%, avg=969.54, stdev=827.99
lat (msec) : 50=0.01%, 100=1.06%, 250=5.88%, 500=4.08%, 750=12.48%
lat (msec) : 1000=17.27%, 2000=49.86%, >=2000=9.42%
f2:
bw (KB /s): min= 2, max= 1882, per=0.16%, avg=273.28, stdev=220.26
lat (msec) : 250=5.65%, 500=3.31%, 750=15.64%, 1000=24.59%, 2000=46.56%
lat (msec) : >=2000=4.33%
f3:
bw (KB /s): min= 0, max=265568, per=99.95%, avg=174575.10,
stdev=34526.89
lat (usec) : 2=0.01%, 4=0.01%, 10=0.02%, 20=0.27%, 50=10.82%
lat (usec) : 100=50.34%, 250=5.05%, 500=7.12%, 750=6.60%, 1000=4.55%
lat (msec) : 2=8.73%, 4=3.49%, 10=1.83%, 20=0.89%, 50=0.22%
lat (msec) : 100=0.05%, 250=0.02%, 500=0.01%
total:
READ: io=102365MB, aggrb=174669KB/s, minb=240KB/s, maxb=173599KB/s,
mint=600001msec, maxt=600113msec
after (with fast read using preadv2 before submit):
f1:
bw (KB /s): min= 3, max=14897, per=1.28%, avg=2276.69, stdev=2930.39
lat (usec) : 2=70.63%, 4=0.01%
lat (msec) : 250=0.20%, 500=2.26%, 750=1.18%, 2000=0.22%, >=2000=25.53%
f2:
bw (KB /s): min= 2, max= 2362, per=0.14%, avg=249.83, stdev=222.00
lat (msec) : 250=6.35%, 500=1.78%, 750=9.29%, 1000=20.49%, 2000=52.18%
lat (msec) : >=2000=9.99%
f3:
bw (KB /s): min= 1, max=245448, per=100.00%, avg=177366.50,
stdev=35995.60
lat (usec) : 2=64.04%, 4=0.01%, 10=0.01%, 20=0.06%, 50=0.43%
lat (usec) : 100=0.20%, 250=1.27%, 500=2.93%, 750=3.93%, 1000=7.35%
lat (msec) : 2=14.27%, 4=2.88%, 10=1.54%, 20=0.81%, 50=0.22%
lat (msec) : 100=0.05%, 250=0.02%
total:
READ: io=103941MB, aggrb=177339KB/s, minb=213KB/s, maxb=176375KB/s,
mint=600020msec, maxt=600178msec
Interpreting the results you can see total bandwidth stays the same but overall
request latency is decreased in f1 (random, mostly cached) and f3 (sequential)
workloads. There is a slight bump in latency for since it's random data that's
unlikely to be cached but we're always trying "fast read".
In our application we have starting keeping track of "fast read" hits/misses
and for files / requests that have a lot hit ratio we don't do "fast reads"
mostly getting rid of extra latency in the uncached cases. In our real world
work load we were able to reduce average response time by 20 to 30% (depends
on amount of IO done by request).
I've performed other benchmarks and I have no observed any perf regressions in
any of the normal (old) code paths.
Full change log:
Version 7 highlight:
- Drops RWF_DSYNC from pwritev2, per Christoph and Andrew
- Updated man pages
- Added tests for this functionality to xfstests, per Dave Chinner
- Based on top of 4.1-rc3
- Tests / numbers using samba and a CIFS client FIO engine
Version 6 highlight:
- Compat syscall flag checks, per. Jeff.
- Minor stylistic suggestions.
Version 5 highlight:
- XFS support for RWF_NONBLOCK. from Christoph.
- RWF_DSYNC flag and support for pwritev2, from Christoph.
- Implemented compat syscalls, per. Jeff.
- Missing nfs, ceph changes from older patchset.
Version 4 highlight:
- Updated for 3.18-rc1.
- Performance data from our application.
- First stab at man page with Jeff's help. Patch is in-reply to.
RFC Version 3 highlights:
- Down to 2 syscalls from 4; can user fp or argument position.
- RWF_NONBLOCK value flag is not the same O_NONBLOCK, per Jeff.
RFC Version 2 highlights:
- Put the flags argument into kiocb (less noise), per. Al Viro
- O_DIRECT checking early in the process, per. Jeff Moyer
- Resolved duplicate (c&p) code in syscall code, per. Jeff
- Included perf data in thread cover letter, per. Jeff
- Created a new flag (not O_NONBLOCK) for readv2, perf Jeff
I have co-developed these changes with Christoph Hellwig.
Christoph Hellwig (1):
xfs: add RWF_NONBLOCK support
Milosz Tanski (4):
vfs: Prepare for adding a new preadv/pwritev with user flags.
vfs: Define new syscalls preadv2,pwritev2
x86: wire up preadv2 and pwritev2
vfs: RWF_NONBLOCK flag for preadv2
arch/x86/syscalls/syscall_32.tbl | 2 +
arch/x86/syscalls/syscall_64.tbl | 2 +
drivers/target/target_core_file.c | 6 +-
fs/ceph/file.c | 2 +
fs/cifs/file.c | 6 +
fs/nfs/file.c | 5 +-
fs/nfsd/vfs.c | 4 +-
fs/ocfs2/file.c | 6 +
fs/pipe.c | 3 +-
fs/read_write.c | 229 +++++++++++++++++++++++++++++---------
fs/splice.c | 2 +-
fs/xfs/xfs_file.c | 28 ++++-
include/linux/aio.h | 2 +
include/linux/compat.h | 6 +
include/linux/fs.h | 6 +-
include/linux/syscalls.h | 6 +
include/uapi/asm-generic/unistd.h | 6 +-
mm/filemap.c | 23 +++-
mm/shmem.c | 4 +
19 files changed, 279 insertions(+), 69 deletions(-)
--
1.9.1
^ permalink raw reply
* RE: [PATCH RFCv2 00/21] Drivers: hv: utils: re-implement the kernel/userspace communication layer
From: KY Srinivasan @ 2015-03-16 18:15 UTC (permalink / raw)
To: Vitaly Kuznetsov,
devel-tBiZLqfeLfOHmIFyCCdPziST3g8Odh+X@public.gmane.org
Cc: Haiyang Zhang,
linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Dexuan Cui,
Radim Krcmar, Greg Kroah-Hartman,
linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
In-Reply-To: <1426080574-9011-1-git-send-email-vkuznets-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
> -----Original Message-----
> From: Vitaly Kuznetsov [mailto:vkuznets-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org]
> Sent: Wednesday, March 11, 2015 6:29 AM
> To: KY Srinivasan; devel-tBiZLqfeLfOHmIFyCCdPziST3g8Odh+X@public.gmane.org
> Cc: Haiyang Zhang; linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Dexuan Cui; Radim Krcmar;
> Greg Kroah-Hartman; linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> Subject: [PATCH RFCv2 00/21] Drivers: hv: utils: re-implement the
> kernel/userspace communication layer
>
> Changes in RFCv2:
> - Preserve backwards compatibility with netlink-speaking daemons. [K. Y.
> Srinivasan]
> - Introduce transport abstraction layer. [K. Y. Srinivasan]
> - Get rid of ioctls [Radim Krcmar]
> - Make the series reviewable by splitting it into smaller patches.
>
> Anatomy of the series:
> Patches 01 - 07 are cleanup with minor functional change.
> Patch 08 defines the state machine.
> Patches 09-11 convert all 3 drivers to using the state machine.
> Patch 12 fixes a bug in fcopy. This change is going away in Patch 15, I just
> want to highlight the fix.
> Patch 13 introduces a transport abstraction.
> Patch 14-16 convert all drivers to using the transport abstraction.
> Patches 17-18 switch KVP and VSS daemon to using char devices.
> Patches 19-20 convert FCOPY and VSS to hull handshake (the same we have
> in KVP). These two can be postponed till we really need to distinguish
> between different kernels in the daemon code.
> Patch 21 unifies log messages on daemons connect across all drivers and
> moves these messages to debug level.
>
> I smoke-tested this series with both old (netlink) and new (char devices)
> daemons and tested the daemon upgrade procedure.
>
> Original description:
> This series converts kvp/vss daemons to use misc char devices instead of
> netlink for userspace/kernel communication and then updates fcopy to be
> consistent with kvp/vss.
>
> Userspace/kernel communication via netlink has a number of issues:
> - It is hard for userspace to figure out if the kernel part was loaded or not
> and this fact can change as there is a way to enable/disable the service from
> host side. Racy daemon startup is also a problem.
> - When the userspace daemon restarts/dies kernel part doesn't receive a
> notification.
> - Netlink communication is not stable under heavy load.
> - ...
>
> Vitaly Kuznetsov (21):
> Drivers: hv: util: move kvp/vss function declarations to
> hyperv_vmbus.h
> Drivers: hv: kvp: reset kvp_context
> Drivers: hv: kvp: move poll_channel() to hyperv_vmbus.h
> Drivers: hv: fcopy: process deferred messages when we complete the
> transaction
> Drivers: hv: vss: process deferred messages when we complete the
> transaction
> Drivers: hv: kvp: rename kvp_work -> kvp_timeout_work
> Drivers: hv: fcopy: rename fcopy_work -> fcopy_timeout_work
> Drivers: hv: util: introduce state machine for util drivers
> Drivers: hv: kvp: switch to using the hvutil_device_state state
> machine
> Drivers: hv: vss: switch to using the hvutil_device_state state
> machine
> Drivers: hv: fcopy: switch to using the hvutil_device_state state
> machine
> Drivers: hv: fcopy: set .owner reference for file operations
> Drivers: hv: util: introduce hv_utils_transport abstraction
> Drivers: hv: vss: convert to hv_utils_transport
> Drivers: hv: fcopy: convert to hv_utils_transport
> Drivers: hv: kvp: convert to hv_utils_transport
> Tools: hv: kvp: use misc char device to communicate with kernel
> Tools: hv: vss: use misc char device to communicate with kernel
> Drivers: hv: vss: full handshake support
> Drivers: hv: fcopy: full handshake support
> Drivers: hv: utils: unify driver registration reporting
>
> drivers/hv/Makefile | 2 +-
> drivers/hv/hv_fcopy.c | 287 ++++++++++++++--------------------------
> drivers/hv/hv_kvp.c | 192 +++++++++++++--------------
> drivers/hv/hv_snapshot.c | 168 +++++++++++++++--------
> drivers/hv/hv_utils_transport.c | 276
> ++++++++++++++++++++++++++++++++++++++
> drivers/hv/hv_utils_transport.h | 51 +++++++
> drivers/hv/hyperv_vmbus.h | 29 ++++
> include/linux/hyperv.h | 8 --
> include/uapi/linux/hyperv.h | 8 +-
> tools/hv/hv_fcopy_daemon.c | 15 +++
> tools/hv/hv_kvp_daemon.c | 166 +++++------------------
> tools/hv/hv_vss_daemon.c | 149 ++++++---------------
> 12 files changed, 752 insertions(+), 599 deletions(-) create mode 100644
> drivers/hv/hv_utils_transport.c create mode 100644
> drivers/hv/hv_utils_transport.h
Vitaly,
Thank you very much for taking on this project; very well done. I have mostly reviewed the code and I should be
done shortly. Also, I am going to test this code as well. If there are no issues, I will send this out to Greg in my next
installment of patches.
Regards,
K. Y
>
> --
> 1.9.3
^ permalink raw reply
* [PATCH 2/2] imx-drm: ipuv3-crtc: Use DRM mode flags to configure pixel clock polarity
From: Sébastien Szymanski @ 2015-03-16 17:29 UTC (permalink / raw)
To: David Airlie, Philipp Zabel,
dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA
Cc: Sébastien Szymanski, Mohsin Kazmi, Steve Longerbeam
In-Reply-To: <1426526944-16762-1-git-send-email-sebastien.szymanski-d2DlULPkwbNWk0Htik3J/w@public.gmane.org>
From: Steve Longerbeam <steve_longerbeam-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
Previously, pixel clock polarity was hardcoded and wasn't configurable.
This patch adds support to configure the pixel clock polarity from the
DRM mode flags.
[Sébastien - rebase]
Signed-off-by: Mohsin Kazmi <mohsin_kazmi-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
Signed-off-by: Steve Longerbeam <steve_longerbeam-nmGgyN9QBj3QT0dZR+AlfA@public.gmane.org>
Signed-off-by: Sébastien Szymanski <sebastien.szymanski@armadeus.com>
---
drivers/gpu/drm/imx/ipuv3-crtc.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c
index 98551e3..71f888b 100644
--- a/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -171,10 +171,12 @@ static int ipu_crtc_mode_set(struct drm_crtc *crtc,
else
sig_cfg.clkflags = 0;
+ if (mode->flags & DRM_MODE_FLAG_PCLK)
+ sig_cfg.clk_pol = 1;
+
out_pixel_fmt = ipu_crtc->interface_pix_fmt;
sig_cfg.enable_pol = 1;
- sig_cfg.clk_pol = 0;
sig_cfg.pixel_fmt = out_pixel_fmt;
sig_cfg.v_to_h_sync = 0;
sig_cfg.hsync_pin = ipu_crtc->di_hsync_pin;
--
2.0.5
^ permalink raw reply related
* [PATCH 1/2] drm_modes: videomode: add pos/neg pixel clock polarity flag
From: Sébastien Szymanski @ 2015-03-16 17:29 UTC (permalink / raw)
To: David Airlie, Philipp Zabel, dri-devel, linux-kernel, linux-api
Cc: Sébastien Szymanski, Steve Longerbeam
From: Steve Longerbeam <steve_longerbeam@mentor.com>
[Sébastien - rebase, update drm_display_mode_to_videomode function]
Signed-off-by: Steve Longerbeam <steve_longerbeam@mentor.com>
Signed-off-by: Sébastien Szymanski <sebastien.szymanski@armadeus.com>
---
drivers/gpu/drm/drm_modes.c | 8 ++++++++
include/uapi/drm/drm_mode.h | 4 ++++
2 files changed, 12 insertions(+)
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 487d0e3..464828f 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -611,6 +611,10 @@ void drm_display_mode_from_videomode(const struct videomode *vm,
dmode->flags |= DRM_MODE_FLAG_DBLSCAN;
if (vm->flags & DISPLAY_FLAGS_DOUBLECLK)
dmode->flags |= DRM_MODE_FLAG_DBLCLK;
+ if (vm->flags & DISPLAY_FLAGS_PIXDATA_POSEDGE)
+ dmode->flags |= DRM_MODE_FLAG_PCLK;
+ else if (vm->flags & DISPLAY_FLAGS_PIXDATA_NEGEDGE)
+ dmode->flags |= DRM_MODE_FLAG_NCLK;
drm_mode_set_name(dmode);
}
EXPORT_SYMBOL_GPL(drm_display_mode_from_videomode);
@@ -652,6 +656,10 @@ void drm_display_mode_to_videomode(const struct drm_display_mode *dmode,
vm->flags |= DISPLAY_FLAGS_DOUBLESCAN;
if (dmode->flags & DRM_MODE_FLAG_DBLCLK)
vm->flags |= DISPLAY_FLAGS_DOUBLECLK;
+ if (dmode->flags & DRM_MODE_FLAG_PCLK)
+ vm->flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
+ else if (dmode->flags & DRM_MODE_FLAG_NCLK)
+ vm->flags |= DISPLAY_FLAGS_PIXDATA_NEGEDGE;
}
EXPORT_SYMBOL_GPL(drm_display_mode_to_videomode);
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index ca788e0..1abb2fc 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -72,6 +72,10 @@
#define DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH (6<<14)
#define DRM_MODE_FLAG_3D_TOP_AND_BOTTOM (7<<14)
#define DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF (8<<14)
+/* drive data on rising pixclk edge */
+#define DRM_MODE_FLAG_PCLK (1<<19)
+/* drive data on falling pixclk edge */
+#define DRM_MODE_FLAG_NCLK (1<<20)
/* DPMS flags */
--
2.0.5
^ permalink raw reply related
* Re: [v9 4/5] ext4: adds FS_IOC_FSSETXATTR/FS_IOC_FSGETXATTR interface support
From: Jan Kara @ 2015-03-16 15:26 UTC (permalink / raw)
To: Li Xi
Cc: linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-ext4-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA, tytso-3s7WtUTddSA,
adilger-m1MBpc4rdrD3fQ9qLvQP4Q, jack-AlSwsSmVLrQ,
viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn, hch-wEGCiKHe2LqWVfeAwA7xHQ,
dmonakhov-GEFAQzZX7r8dnm+yROfE0A
In-Reply-To: <1426043003-31043-5-git-send-email-lixi-LfVdkaOWEx8@public.gmane.org>
On Wed 11-03-15 12:03:22, Li Xi wrote:
> This patch adds FS_IOC_FSSETXATTR/FS_IOC_FSGETXATTR ioctl interface
> support for ext4. The interface is kept consistent with
> XFS_IOC_FSGETXATTR/XFS_IOC_FSGETXATTR.
Thanks for the patch! I think we are getting to a working solution :) Apart
from the bug Konstantin pointed out, I have a few comments below.
> Signed-off-by: Li Xi <lixi-LfVdkaOWEx8@public.gmane.org>
> ---
> fs/ext4/ext4.h | 47 +++++++
> fs/ext4/ioctl.c | 341 +++++++++++++++++++++++++++++++++--------------
> fs/xfs/xfs_fs.h | 47 +++----
> include/uapi/linux/fs.h | 32 +++++
> 4 files changed, 338 insertions(+), 129 deletions(-)
>
> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
> index 3443456..2f4b9ba 100644
> --- a/fs/ext4/ext4.h
> +++ b/fs/ext4/ext4.h
> @@ -385,6 +385,51 @@ struct flex_groups {
> #define EXT4_FL_USER_VISIBLE 0x204BDFFF /* User visible flags */
> #define EXT4_FL_USER_MODIFIABLE 0x204380FF /* User modifiable flags */
>
> +#define EXT4_FL_XFLAG_VISIBLE (EXT4_SYNC_FL | \
> + EXT4_IMMUTABLE_FL | \
> + EXT4_APPEND_FL | \
> + EXT4_NOATIME_FL | \
> + EXT4_PROJINHERIT_FL)
> +
> +/* Transfer internal flags to xflags */
> +static inline __u32 ext4_iflags_to_xflags(unsigned long iflags)
> +{
> + __u32 xflags = 0;
> +
> + if (iflags & EXT4_SYNC_FL)
> + xflags |= FS_XFLAG_SYNC;
> + if (iflags & EXT4_IMMUTABLE_FL)
> + xflags |= FS_XFLAG_IMMUTABLE;
> + if (iflags & EXT4_APPEND_FL)
> + xflags |= FS_XFLAG_APPEND;
> + if (iflags & EXT4_NOATIME_FL)
> + xflags |= FS_XFLAG_NOATIME;
> + if (iflags & EXT4_PROJINHERIT_FL)
> + xflags |= FS_XFLAG_PROJINHERIT;
> + return xflags;
> +}
I think EXT4_NODUMP_FL is missing in EXT4_FL_XFLAG_VISIBLE and isn't
handled in ext4_iflags_to_xflags().
> +/* Transfer xflags flags to internal */
> +static inline unsigned long ext4_xflags_to_iflags(__u32 xflags)
> +{
> + unsigned long iflags = 0;
> +
> + if (xflags & FS_XFLAG_SYNC)
> + iflags |= EXT4_SYNC_FL;
> + if (xflags & FS_XFLAG_IMMUTABLE)
> + iflags |= EXT4_IMMUTABLE_FL;
> + if (xflags & FS_XFLAG_APPEND)
> + iflags |= EXT4_APPEND_FL;
> + if (xflags & FS_XFLAG_NODUMP)
> + iflags |= EXT4_NODUMP_FL;
> + if (xflags & FS_XFLAG_NOATIME)
> + iflags |= EXT4_NOATIME_FL;
> + if (xflags & FS_XFLAG_PROJINHERIT)
> + iflags |= EXT4_PROJINHERIT_FL;
> +
> + return iflags;
> +}
These two functions are only used in fs/ext4/ioctl.c. So just move their
definition there.
...
> diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
> index f58a0d1..20a6337 100644
> --- a/fs/ext4/ioctl.c
> +++ b/fs/ext4/ioctl.c
> @@ -14,6 +14,8 @@
> #include <linux/compat.h>
> #include <linux/mount.h>
> #include <linux/file.h>
> +#include <linux/quotaops.h>
> +#include <linux/quota.h>
> #include <asm/uaccess.h>
> #include "ext4_jbd2.h"
> #include "ext4.h"
> @@ -196,126 +198,229 @@ journal_err_out:
> return err;
> }
>
> -long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
> +static int ext4_ioctl_setflags(struct file *filp,
> + unsigned int flags, int is_from_xflags)
> {
Hum, I think we can get rid of the is_from_xflags argument. As I'm
looking into the code below the only real reason why we have is_from_xflags
is that we need to compare old value of flags against new value of flags
and see what has changed. So what we can do is that FSSETXATTR ioctl will
construct flags to pass to ext4_ioctl_setflags() like:
flags = (ei->i_flags & ~EXT4_FL_XFLAG_VISIBLE) |
(flags & EXT4_FL_XFLAG_VISIBLE);
That way we don't change any flags outside of EXT4_FL_XFLAG_VISIBLE and
ext4_ioctl_setflags() doesn't have to be aware about different callers. The
only downside is that we need to hold i_mutex to reliably create 'flags'
value which requires moving mnt_want_write_file() and
mutex_lock(&inode->i_mutex) into the caller but that's pretty simple.
> struct inode *inode = file_inode(filp);
> - struct super_block *sb = inode->i_sb;
> struct ext4_inode_info *ei = EXT4_I(inode);
> - unsigned int flags;
> + handle_t *handle = NULL;
> + int err, migrate = 0;
> + struct ext4_iloc iloc;
> + unsigned int oldflags, mask, i;
> + unsigned int jflag;
>
> - ext4_debug("cmd = %u, arg = %lu\n", cmd, arg);
> + if (!inode_owner_or_capable(inode))
> + return -EACCES;
>
> - switch (cmd) {
> - case EXT4_IOC_GETFLAGS:
> - ext4_get_inode_flags(ei);
> - flags = ei->i_flags & EXT4_FL_USER_VISIBLE;
> - return put_user(flags, (int __user *) arg);
> - case EXT4_IOC_SETFLAGS: {
> - handle_t *handle = NULL;
> - int err, migrate = 0;
> - struct ext4_iloc iloc;
> - unsigned int oldflags, mask, i;
> - unsigned int jflag;
> + err = mnt_want_write_file(filp);
> + if (err)
> + return err;
>
> - if (!inode_owner_or_capable(inode))
> - return -EACCES;
> + flags = ext4_mask_flags(inode->i_mode, flags);
> + if (is_from_xflags)
> + flags &= EXT4_FL_XFLAG_VISIBLE;
> +
> + err = -EPERM;
> + mutex_lock(&inode->i_mutex);
> + /* Is it quota file? Do not allow user to mess with it */
> + if (IS_NOQUOTA(inode))
> + goto flags_out;
> +
> + oldflags = ei->i_flags;
> + if (is_from_xflags)
> + oldflags &= EXT4_FL_XFLAG_VISIBLE;
> +
> + /* The JOURNAL_DATA flag is modifiable only by root */
> + jflag = flags & EXT4_JOURNAL_DATA_FL;
> + if (is_from_xflags)
> + jflag &= EXT4_FL_XFLAG_VISIBLE;
> +
> + /*
> + * The IMMUTABLE and APPEND_ONLY flags can only be changed by
> + * the relevant capability.
> + *
> + * This test looks nicer. Thanks to Pauline Middelink
> + */
> + if ((flags ^ oldflags) & (EXT4_APPEND_FL | EXT4_IMMUTABLE_FL)) {
> + if (!capable(CAP_LINUX_IMMUTABLE))
> + goto flags_out;
> + }
>
> - if (get_user(flags, (int __user *) arg))
> - return -EFAULT;
> + /*
> + * The JOURNAL_DATA flag can only be changed by
> + * the relevant capability.
> + */
> + if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL)) {
> + if (!capable(CAP_SYS_RESOURCE))
> + goto flags_out;
> + }
> + if ((flags ^ oldflags) & EXT4_EXTENTS_FL)
> + migrate = 1;
> + if (flags & EXT4_EOFBLOCKS_FL) {
> + /* we don't support adding EOFBLOCKS flag */
> + if (!(oldflags & EXT4_EOFBLOCKS_FL)) {
> + err = -EOPNOTSUPP;
> + goto flags_out;
> + }
> + } else if (oldflags & EXT4_EOFBLOCKS_FL)
> + ext4_truncate(inode);
>
> - err = mnt_want_write_file(filp);
> - if (err)
> - return err;
> + handle = ext4_journal_start(inode, EXT4_HT_INODE, 1);
> + if (IS_ERR(handle)) {
> + err = PTR_ERR(handle);
> + goto flags_out;
> + }
> + if (IS_SYNC(inode))
> + ext4_handle_sync(handle);
> + err = ext4_reserve_inode_write(handle, inode, &iloc);
> + if (err)
> + goto flags_err;
> +
> + for (i = 0, mask = 1; i < 32; i++, mask <<= 1) {
> + if (!(mask & EXT4_FL_USER_MODIFIABLE))
> + continue;
> + if (is_from_xflags && !(mask & EXT4_FL_XFLAG_VISIBLE))
> + continue;
> + if (mask & flags)
> + ext4_set_inode_flag(inode, i);
> + else
> + ext4_clear_inode_flag(inode, i);
> + }
>
> - flags = ext4_mask_flags(inode->i_mode, flags);
> + ext4_set_inode_flags(inode);
> + inode->i_ctime = ext4_current_time(inode);
>
> - err = -EPERM;
> - mutex_lock(&inode->i_mutex);
> - /* Is it quota file? Do not allow user to mess with it */
> - if (IS_NOQUOTA(inode))
> - goto flags_out;
> + err = ext4_mark_iloc_dirty(handle, inode, &iloc);
> +flags_err:
> + ext4_journal_stop(handle);
> + if (err)
> + goto flags_out;
> +
> + if ((jflag ^ oldflags) & (EXT4_JOURNAL_DATA_FL))
> + err = ext4_change_inode_journal_flag(inode, jflag);
> + if (err)
> + goto flags_out;
> + if (migrate) {
> + if (flags & EXT4_EXTENTS_FL)
> + err = ext4_ext_migrate(inode);
> + else
> + err = ext4_ind_migrate(inode);
> + }
>
> - oldflags = ei->i_flags;
> +flags_out:
> + mutex_unlock(&inode->i_mutex);
> + mnt_drop_write_file(filp);
> + return err;
> +}
>
> - /* The JOURNAL_DATA flag is modifiable only by root */
> - jflag = flags & EXT4_JOURNAL_DATA_FL;
> +static int ext4_ioctl_setproject(struct file *filp, __u32 projid)
> +{
> + struct inode *inode = file_inode(filp);
> + struct super_block *sb = inode->i_sb;
> + struct ext4_inode_info *ei = EXT4_I(inode);
> + int err;
> + handle_t *handle;
> + kprojid_t kprojid;
> + struct ext4_iloc iloc;
> + struct ext4_inode *raw_inode;
> +
> + struct dquot *transfer_to[EXT4_MAXQUOTAS] = { };
> +
> + /* Make sure caller can change project. */
> + if (!capable(CAP_SYS_ADMIN))
> + return -EACCES;
> +
> + if (projid != EXT4_DEF_PROJID
> + && !EXT4_HAS_RO_COMPAT_FEATURE(sb,
> + EXT4_FEATURE_RO_COMPAT_PROJECT))
> + return -EOPNOTSUPP;
> +
> + if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,
> + EXT4_FEATURE_RO_COMPAT_PROJECT)) {
> + BUG_ON(__kprojid_val(EXT4_I(inode)->i_projid)
> + != EXT4_DEF_PROJID);
> + if (projid != EXT4_DEF_PROJID)
> + return -EOPNOTSUPP;
> + else
> + return 0;
> + }
Why is the test here twice? The first one seems to be redundant...
Honza
--
Jan Kara <jack-AlSwsSmVLrQ@public.gmane.org>
SUSE Labs, CR
^ permalink raw reply
* Re: [v9 2/5] ext4: adds project ID support
From: Jan Kara @ 2015-03-16 14:37 UTC (permalink / raw)
To: Li Xi
Cc: linux-fsdevel-u79uwXL29TY76Z2rM5mHXA,
linux-ext4-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA, tytso-3s7WtUTddSA,
adilger-m1MBpc4rdrD3fQ9qLvQP4Q, jack-AlSwsSmVLrQ,
viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn, hch-wEGCiKHe2LqWVfeAwA7xHQ,
dmonakhov-GEFAQzZX7r8dnm+yROfE0A
In-Reply-To: <1426043003-31043-3-git-send-email-lixi-LfVdkaOWEx8@public.gmane.org>
On Wed 11-03-15 12:03:20, Li Xi wrote:
> This patch adds a new internal field of ext4 inode to save project
> identifier. Also a new flag EXT4_INODE_PROJINHERIT is added for
> inheriting project ID from parent directory.
>
> Signed-off-by: Li Xi <lixi-LfVdkaOWEx8@public.gmane.org>
> Reviewed-by: Jan Kara <jack-AlSwsSmVLrQ@public.gmane.org>
...
> @@ -3395,6 +3405,13 @@ static int ext4_cross_rename(struct inode *old_dir, struct dentry *old_dentry,
> u8 new_file_type;
> int retval;
>
> + if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT)) &&
> + ((!projid_eq(EXT4_I(new_dir)->i_projid,
> + EXT4_I(old_dentry->d_inode)->i_projid)) ||
> + (!projid_eq(EXT4_I(old_dir)->i_projid,
> + EXT4_I(new_dentry->d_inode)->i_projid))))
> + return -EXDEV;
> +
I believe this needs to also check EXT4_INODE_PROJINHERIT on old_dir. So
something like:
if ((ext4_test_inode_flag(new_dir, EXT4_INODE_PROJINHERIT) &&
!projid_eq(EXT4_I(new_dir)->i_projid,
EXT4_I(old_dentry->d_inode)->i_projid)) ||
(ext4_test_inode_flag(old_dir, EXT4_INODE_PROJINHERIT) &&
!projid_eq(EXT4_I(old_dir)->i_projid,
EXT4_I(new_dentry->d_inode)->i_projid)))
return -EXDEV;
Honza
--
Jan Kara <jack-AlSwsSmVLrQ@public.gmane.org>
SUSE Labs, CR
^ permalink raw reply
* Re: [v9 1/5] vfs: adds general codes to enforces project quota limits
From: Jan Kara @ 2015-03-16 14:29 UTC (permalink / raw)
To: Li Xi
Cc: linux-fsdevel, linux-ext4, linux-api, tytso, adilger, jack, viro,
hch, dmonakhov, dchinner
In-Reply-To: <1426043003-31043-2-git-send-email-lixi@ddn.com>
On Wed 11-03-15 12:03:19, Li Xi wrote:
> This patch adds support for a new quota type PRJQUOTA for project quota
> enforcement. Also a new method get_projid() is added into dquot_operations
> structure.
>
> Signed-off-by: Li Xi <lixi@ddn.com>
> Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
> Reviewed-by: Jan Kara <jack@suse.cz>
...
> diff --git a/fs/quota/quota.c b/fs/quota/quota.c
> index 2aa4151..c76b350 100644
> --- a/fs/quota/quota.c
> +++ b/fs/quota/quota.c
> @@ -30,11 +30,15 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
> case Q_XGETQSTATV:
> case Q_XQUOTASYNC:
> break;
> - /* allow to query information for dquots we "own" */
> + /*
> + * allow to query information for dquots we "own"
> + * always allow querying project quota
> + */
> case Q_GETQUOTA:
> case Q_XGETQUOTA:
> if ((type == USRQUOTA && uid_eq(current_euid(), make_kuid(current_user_ns(), id))) ||
> - (type == GRPQUOTA && in_egroup_p(make_kgid(current_user_ns(), id))))
> + (type == GRPQUOTA && in_egroup_p(make_kgid(current_user_ns(), id))) ||
> + (type == PRJQUOTA))
> break;
I wanted to merge this patch but this hunk caught my eye. Why do we
suddently allow querying of project quotas? Traditionally that has been
allowed only with CAP_SYS_ADMIN. I agree it looks too restrictive to me but
unless that's a bug, I think we have to adhere to original behavior and
drop this hunk. Dave, was that behavior of project quotas intended?
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH V5] Allow compaction of unevictable pages
From: Eric B Munson @ 2015-03-16 13:49 UTC (permalink / raw)
To: Vlastimil Babka
Cc: Michal Hocko, Rik van Riel, Andrew Morton, Thomas Gleixner,
Christoph Lameter, Peter Zijlstra, Mel Gorman, David Rientjes,
linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
linux-kernel-u79uwXL29TY76Z2rM5mHXA, Linux API
In-Reply-To: <5506ACEC.9010403-AlSwsSmVLrQ@public.gmane.org>
[-- Attachment #1: Type: text/plain, Size: 4935 bytes --]
On Mon, 16 Mar 2015, Vlastimil Babka wrote:
> [CC += linux-api@]
>
> Since this is a kernel-user-space API change, please CC linux-api@.
> The kernel source file Documentation/SubmitChecklist notes that all
> Linux kernel patches that change userspace interfaces should be CCed
> to linux-api-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, so that the various parties who are
> interested in API changes are informed. For further information, see
> https://urldefense.proofpoint.com/v2/url?u=https-3A__www.kernel.org_doc_man-2Dpages_linux-2Dapi-2Dml.html&d=AwIC-g&c=96ZbZZcaMF4w0F4jpN6LZg&r=aUmMDRRT0nx4IfILbQLv8xzE0wB9sQxTHI3QrQ2lkBU&m=GUotTNnv26L0HxtXrBgiHqu6kwW3ufx2_TQpXIA216c&s=IFFYQ7Zr-4SIaF3slOZqiSP_noyva42kCwVRxxDm5wo&e=
Added to the Cc list, thanks.
>
>
> On 03/13/2015 09:19 PM, Michal Hocko wrote:
> >On Fri 13-03-15 15:09:15, Eric B Munson wrote:
> >>On Fri, 13 Mar 2015, Rik van Riel wrote:
> >>
> >>>On 03/13/2015 01:26 PM, Eric B Munson wrote:
> >>>
> >>>>--- a/mm/compaction.c
> >>>>+++ b/mm/compaction.c
> >>>>@@ -1046,6 +1046,8 @@ typedef enum {
> >>>> ISOLATE_SUCCESS, /* Pages isolated, migrate */
> >>>> } isolate_migrate_t;
> >>>>
> >>>>+int sysctl_compact_unevictable;
>
> A comment here would be useful I think, as well as explicit default
> value. Maybe also __read_mostly although I don't know how much that
> matters.
I am going to sit on V6 for a couple of days incase anyone from rt wants
to chime in. But these will be in V6.
>
> I also wonder if it might be confusing that "compact_memory" is a
> write-only trigger that doesn't even show under "sysctl -a", while
> "compact_unevictable" is a read/write setting. But I don't have a
> better suggestion right now.
Does allow_unevictable_compaction sound better? It feels too much like
variable naming conventions from other languages which seems to
encourage verbosity to me, but does indicate a difference from
compact_memory.
>
> >>>>+
> >>>> /*
> >>>> * Isolate all pages that can be migrated from the first suitable block,
> >>>> * starting at the block pointed to by the migrate scanner pfn within
> >>>
> >>>I suspect that the use cases where users absolutely do not want
> >>>unevictable pages migrated are special cases, and it may make
> >>>sense to enable sysctl_compact_unevictable by default.
> >>
> >>Given that sysctl_compact_unevictable=0 is the way the kernel behaves
> >>now and the push back against always enabling compaction on unevictable
> >>pages, I left the default to be the behavior as it is today.
> >
> >The question is _why_ we have this behavior now. Is it intentional?
>
> It's there since 748446bb6 ("mm: compaction: memory compaction
> core"). Commit c53919adc0 ("mm: vmscan: remove lumpy reclaim")
> changes the comment in __isolate_lru_page() handling of unevictable
> pages to mention compaction explicitly. It could have been
> accidental in 748446bb6 though, maybe it just reused
> __isolate_lru_page() for compaction - it seems that the skipping of
> unevictable was initially meant to optimize lumpy reclaim.
>
> >e46a28790e59 (CMA: migrate mlocked pages) is a precedence in that
>
> Well, CMA and realtime kernels are probably mutually exclusive enough.
>
> >direction. Vlastimil has then changed that by edc2ca612496 (mm,
> >compaction: move pageblock checks up from isolate_migratepages_range()).
> >There is no mention about mlock pages so I guess it was more an
> >unintentional side effect of the patch. At least that is my current
> >understanding. I might be wrong here.
>
> Although that commit did change unintentionally more details that I
> would have liked (unfortunately), I think you are wrong on this one.
> ISOLATE_UNEVICTABLE is still passed from
> isolate_migratepages_range() which is used by CMA, while the
> compaction variant isolate_migratepages() does not pass it. So it's
> kept CMA-specific as before.
>
> >The thing about RT is that it is not usable with the upstream kernel
> >without the RT patchset AFAIU. So the default should be reflect what is
> >better for the standard kernel. RT loads have to tune the system anyway
> >so it is not so surprising they would disable this option as well. We
> >should help those guys and do not require them to touch the code but the
> >knob is reasonable IMHO.
> >
> >Especially when your changelog suggests that having this enabled by
> >default is beneficial for the standard kernel.
>
> I agree, but if there's a danger of becoming too of a bikeshed
> topic, I'm fine with keeping the default same as current behavior
> and changing it later. Or maybe we should ask some -rt mailing list
> instead of just Peter and Thomas?
According to the rt wiki, there is no -rt development list so lkml is
it. I will change the default to 1 for V6 if I don't hear otherwise by
the time I get back around to spinning V6.
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]
^ permalink raw reply
* Re: [PATCH] selftests: Fix kcmp build to not require headers install
From: Michael Ellerman @ 2015-03-16 11:00 UTC (permalink / raw)
To: Shuah Khan
Cc: gorcunov-GEFAQzZX7r8dnm+yROfE0A,
tranmanphong-Re5JQEeQqe8AvxtiuMwx3w,
akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1426297504-14432-2-git-send-email-shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
On Fri, 2015-03-13 at 19:45 -0600, Shuah Khan wrote:
> Change CFLAGS to look in uapi to allow kcmp to be built without
> requiring headers install. This will make it easier to run tests
> without going through the headers install step.
>
> Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
> ---
> tools/testing/selftests/kcmp/Makefile | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/testing/selftests/kcmp/Makefile b/tools/testing/selftests/kcmp/Makefile
> index ff0eefd..d405ad4 100644
> --- a/tools/testing/selftests/kcmp/Makefile
> +++ b/tools/testing/selftests/kcmp/Makefile
> @@ -1,5 +1,5 @@
> CC := $(CROSS_COMPILE)$(CC)
> -CFLAGS += -I../../../../usr/include/
> +CFLAGS += -I../../../../include/uapi -I../../../../usr/include/
Hi Shuah,
Sorry but this is wrong. The contents of include/uapi are not the same as the
exported kernel headers.
Mixing the unprocessed kernel headers with user headers leads to all sorts of
mess, eg:
$ cc -I../../../../include/uapi -I../../../../usr/include/ kcmp_test.c -o kcmp_test
In file included from /usr/include/powerpc64le-linux-gnu/asm/ptrace.h:27:0,
from /usr/include/powerpc64le-linux-gnu/asm/sigcontext.h:11,
from /usr/include/powerpc64le-linux-gnu/bits/sigcontext.h:27,
from /usr/include/signal.h:332,
from kcmp_test.c:5:
../../../../include/uapi/linux/types.h:9:2: warning: #warning "Attempt to use kernel headers from user space, see http://kernelnewbies.org/KernelHeaders" [-Wcpp]
#warning "Attempt to use kernel headers from user space, see http://kernelnewbies.org/KernelHeaders"
^
In file included from ../../../../include/uapi/linux/posix_types.h:4:0,
from ../../../../include/uapi/linux/types.h:13,
from /usr/include/powerpc64le-linux-gnu/asm/ptrace.h:27,
from /usr/include/powerpc64le-linux-gnu/asm/sigcontext.h:11,
from /usr/include/powerpc64le-linux-gnu/bits/sigcontext.h:27,
from /usr/include/signal.h:332,
from kcmp_test.c:5:
../../../../include/uapi/linux/stddef.h:1:28: fatal error: linux/compiler.h: No such file or directory
#include <linux/compiler.h>
^
compilation terminated.
<builtin>: recipe for target 'kcmp_test' failed
make: *** [kcmp_test] Error 1
If you want to make it easier to build tests that need the kernel headers then
maybe kselftest should depend on headers_install?
cheers
^ permalink raw reply
* Re: [PATCH V5] Allow compaction of unevictable pages
From: Vlastimil Babka @ 2015-03-16 10:14 UTC (permalink / raw)
To: Michal Hocko, Eric B Munson
Cc: Rik van Riel, Andrew Morton, Thomas Gleixner, Christoph Lameter,
Peter Zijlstra, Mel Gorman, David Rientjes, linux-mm,
linux-kernel, Linux API
In-Reply-To: <20150313201954.GB28848@dhcp22.suse.cz>
[CC += linux-api@]
Since this is a kernel-user-space API change, please CC linux-api@.
The kernel source file Documentation/SubmitChecklist notes that all
Linux kernel patches that change userspace interfaces should be CCed
to linux-api@vger.kernel.org, so that the various parties who are
interested in API changes are informed. For further information, see
https://www.kernel.org/doc/man-pages/linux-api-ml.html
On 03/13/2015 09:19 PM, Michal Hocko wrote:
> On Fri 13-03-15 15:09:15, Eric B Munson wrote:
>> On Fri, 13 Mar 2015, Rik van Riel wrote:
>>
>>> On 03/13/2015 01:26 PM, Eric B Munson wrote:
>>>
>>>> --- a/mm/compaction.c
>>>> +++ b/mm/compaction.c
>>>> @@ -1046,6 +1046,8 @@ typedef enum {
>>>> ISOLATE_SUCCESS, /* Pages isolated, migrate */
>>>> } isolate_migrate_t;
>>>>
>>>> +int sysctl_compact_unevictable;
A comment here would be useful I think, as well as explicit default
value. Maybe also __read_mostly although I don't know how much that matters.
I also wonder if it might be confusing that "compact_memory" is a
write-only trigger that doesn't even show under "sysctl -a", while
"compact_unevictable" is a read/write setting. But I don't have a better
suggestion right now.
>>>> +
>>>> /*
>>>> * Isolate all pages that can be migrated from the first suitable block,
>>>> * starting at the block pointed to by the migrate scanner pfn within
>>>
>>> I suspect that the use cases where users absolutely do not want
>>> unevictable pages migrated are special cases, and it may make
>>> sense to enable sysctl_compact_unevictable by default.
>>
>> Given that sysctl_compact_unevictable=0 is the way the kernel behaves
>> now and the push back against always enabling compaction on unevictable
>> pages, I left the default to be the behavior as it is today.
>
> The question is _why_ we have this behavior now. Is it intentional?
It's there since 748446bb6 ("mm: compaction: memory compaction core").
Commit c53919adc0 ("mm: vmscan: remove lumpy reclaim") changes the
comment in __isolate_lru_page() handling of unevictable pages to mention
compaction explicitly. It could have been accidental in 748446bb6
though, maybe it just reused __isolate_lru_page() for compaction - it
seems that the skipping of unevictable was initially meant to optimize
lumpy reclaim.
> e46a28790e59 (CMA: migrate mlocked pages) is a precedence in that
Well, CMA and realtime kernels are probably mutually exclusive enough.
> direction. Vlastimil has then changed that by edc2ca612496 (mm,
> compaction: move pageblock checks up from isolate_migratepages_range()).
> There is no mention about mlock pages so I guess it was more an
> unintentional side effect of the patch. At least that is my current
> understanding. I might be wrong here.
Although that commit did change unintentionally more details that I
would have liked (unfortunately), I think you are wrong on this one.
ISOLATE_UNEVICTABLE is still passed from isolate_migratepages_range()
which is used by CMA, while the compaction variant
isolate_migratepages() does not pass it. So it's kept CMA-specific as
before.
> The thing about RT is that it is not usable with the upstream kernel
> without the RT patchset AFAIU. So the default should be reflect what is
> better for the standard kernel. RT loads have to tune the system anyway
> so it is not so surprising they would disable this option as well. We
> should help those guys and do not require them to touch the code but the
> knob is reasonable IMHO.
>
> Especially when your changelog suggests that having this enabled by
> default is beneficial for the standard kernel.
I agree, but if there's a danger of becoming too of a bikeshed topic,
I'm fine with keeping the default same as current behavior and changing
it later. Or maybe we should ask some -rt mailing list instead of just
Peter and Thomas?
^ permalink raw reply
* Re: [RFC/PATCH 0/5] Add live source objects to DRM
From: Daniel Vetter @ 2015-03-16 8:35 UTC (permalink / raw)
To: Laurent Pinchart
Cc: linux-sh, linux-api, Magnus Damm, dri-devel, Daniel Vetter,
linux-media
In-Reply-To: <1426456540-21006-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com>
On Sun, Mar 15, 2015 at 11:55:35PM +0200, Laurent Pinchart wrote:
> Hello,
>
> I have a feeling that RFC/PATCH will work better than just RFC, so here's a
> patch set that adds a new object named live source to DRM.
>
> The need comes from the Renesas R-Car SoCs in which a video processing engine
> (named VSP1) that operates from memory to memory has one output directly
> connected to a plane of the display engine (DU) without going through memory.
>
> The VSP1 is supported by a V4L2 driver. While it could be argued that it
> should instead be supported directly by the DRM rcar-du driver, this wouldn't
> be a good idea for at least two reasons. First, the R-Car SoCs contain several
> VSP1 instances, of which only a subset have a direct DU connection. The only
> other instances operate solely in memory to memory mode. Then, the VSP1 is a
> video processing engine and not a display engine. Its features are easily
> supported by the V4L2 API, but don't map to the DRM/KMS API. Significant
> changes to DRM/KMS would be required, beyond what is in my opinion an
> acceptable scope for a display API.
>
> Now that the need to interface two separate devices supported by two different
> drivers in two separate subsystems has been established, we need an API to do
> so. It should be noted that while that API doesn't exist in the mainline
> kernel, the need isn't limited to Renesas SoCs.
>
> This patch set proposes one possible solution for the problem in the form of a
> new DRM object named live source. Live sources are created by drivers to model
> hardware connections between a plane input and an external source, and are
> attached to planes through the KMS userspace API.
>
> Patch 1/5 adds live source objects to DRM, with an in-kernel API for drivers
> to register the sources, and a userspace API to enumerate and configure them.
> Configuring a live source sets the width, height and pixel format of the
> video stream. This should ideally be queried directly from the driver that
> supports the live source device, but I've decided not to implement such
> communication between V4L2 and DRM/KMS at the moment to keep the proposal
> simple.
>
> Patch 2/2 implements connection between live sources and planes. This takes
> different forms depending on whether drivers use the setplane or the atomic
> updates API:
>
> - For setplane, the fb field can now contain a live source ID in addition to
> a framebuffer ID. As DRM allocates object IDs from a single ID space, the
> type can be inferred from the ID. This makes specifying both a framebuffer
> and a live source impossible, which isn't an issue given that such a
> configuration would be invalid.
>
> The live source is looked up by the DRM core and passed as a pointer to the
> .update_plane() operation. Unlike framebuffers live sources are not
> refcounted as they're created statically at driver initialization time.
>
> - For atomic update, a new SRC_ID property has been added to planes. The live
> source is looked up from the source ID and stored into the plane state.
What about directly treating live sources as (very) special framebuffers?
A bunch of reasons:
- All the abi fu above gets resolved naturally.
- You have lot of duplication between fb and live source wrt size,
possible/selected pixel format and other stuff.
- The backing storage of framebuffers is fully opaque anyway ...
I think we still need separate live source objects though for things like
telling userspace what v4l thing it corresponds to, and for getting at the
pixel format. But connecting the live source with the plane could still be
done with a framebuffer and a special flag in the addfb2 ioctl to use
live sources as backing storage ids instead of gem/ttm handles.
That would also give you a good point to enforce pixel format
compatibility: As soon as someone created a framebuffer for a live source
you disallow pixel format changes in the v4l pipeline to make sure things
will fit.
> Patches 3/5 to 5/5 then implement support for live sources in the R-Car DU
> driver.
>
> Nothing here is set in stone. One point I'm not sure about is whether live
> sources support should be enabled for setplane or only for atomic updates.
> Other parts of the API can certainly be modified as well, and I'm open for
> totally different implementations as well.
Imo this should be irrespective of atomic or not really. And by using
magic framebuffers as the link we'd get that for free.
Cheers, Daniel
>
> Laurent Pinchart (5):
> drm: Add live source object
> drm: Connect live source to plane
> drm/rcar-du: Add VSP1 support to the planes allocator
> drm/rcar-du: Add VSP1 live source support
> drm/rcar-du: Restart the DU group when a plane source changes
>
> drivers/gpu/drm/armada/armada_overlay.c | 2 +-
> drivers/gpu/drm/drm_atomic.c | 7 +
> drivers/gpu/drm/drm_atomic_helper.c | 4 +
> drivers/gpu/drm/drm_crtc.c | 365 ++++++++++++++++++++++++++--
> drivers/gpu/drm/drm_fops.c | 6 +-
> drivers/gpu/drm/drm_ioctl.c | 3 +
> drivers/gpu/drm/drm_plane_helper.c | 1 +
> drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 +-
> drivers/gpu/drm/exynos/exynos_drm_plane.c | 3 +-
> drivers/gpu/drm/exynos/exynos_drm_plane.h | 3 +-
> drivers/gpu/drm/i915/intel_display.c | 4 +-
> drivers/gpu/drm/i915/intel_sprite.c | 2 +-
> drivers/gpu/drm/imx/ipuv3-plane.c | 3 +-
> drivers/gpu/drm/nouveau/dispnv04/overlay.c | 6 +-
> drivers/gpu/drm/omapdrm/omap_plane.c | 1 +
> drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +-
> drivers/gpu/drm/rcar-du/rcar_du_drv.c | 6 +-
> drivers/gpu/drm/rcar-du/rcar_du_drv.h | 3 +
> drivers/gpu/drm/rcar-du/rcar_du_group.c | 21 +-
> drivers/gpu/drm/rcar-du/rcar_du_group.h | 2 +
> drivers/gpu/drm/rcar-du/rcar_du_kms.c | 62 ++++-
> drivers/gpu/drm/rcar-du/rcar_du_plane.c | 196 ++++++++++++---
> drivers/gpu/drm/rcar-du/rcar_du_plane.h | 11 +
> drivers/gpu/drm/rcar-du/rcar_du_regs.h | 1 +
> drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +-
> drivers/gpu/drm/shmobile/shmob_drm_plane.c | 3 +-
> drivers/gpu/drm/sti/sti_drm_plane.c | 3 +-
> drivers/gpu/drm/sti/sti_hqvdp.c | 2 +-
> include/drm/drmP.h | 3 +
> include/drm/drm_atomic_helper.h | 1 +
> include/drm/drm_crtc.h | 48 ++++
> include/drm/drm_plane_helper.h | 1 +
> include/uapi/drm/drm.h | 4 +
> include/uapi/drm/drm_mode.h | 32 +++
> 34 files changed, 728 insertions(+), 100 deletions(-)
>
> --
> Regards,
>
> Laurent Pinchart
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* Re: [PATCH v4 4/9] selftests: Add install target
From: Michael Ellerman @ 2015-03-16 3:12 UTC (permalink / raw)
To: Shuah Khan
Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
davej-rdkfGonbjUTCLXcRTR1eJlpr/1R2p/CL, mmarek-AlSwsSmVLrQ,
linux-api-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1426475092.20210.4.camel-Gsx/Oe8HsFggBc27wqDAHg@public.gmane.org>
On Mon, 2015-03-16 at 14:04 +1100, Michael Ellerman wrote:
> On Fri, 2015-03-13 at 15:32 -0600, Shuah Khan wrote:
> > On 03/13/2015 11:20 AM, Shuah Khan wrote:
> > > On 03/10/2015 10:06 PM, Michael Ellerman wrote:
> > >> This adds make install support to selftests. The basic usage is:
> > >>
> > >> $ cd tools/testing/selftests
> > >> $ make install
> > >>
> > >> That installs into tools/testing/selftests/install, which can then be
> > >> copied where ever necessary.
> > >>
> > >> The install destination is also configurable using eg:
> > >>
> > >> $ INSTALL_PATH=/mnt/selftests make install
> > >>
> > >> The implementation uses two targets in the child makefiles. The first
> > >> "install" is expected to install all files into $(INSTALL_PATH).
> > >>
> > >> The second, "emit_tests", is expected to emit the test instructions (ie.
> > >> bash script) on stdout. Separating this from install means the child
> > >> makefiles need no knowledge of the location of the test script.
> > >>
> > >> Signed-off-by: Michael Ellerman <mpe-Gsx/Oe8HsFggBc27wqDAHg@public.gmane.org>
> > >
> > > Thanks for doing the work. This patch will be applied to next and will
> > > be queued for 4.1
> > >
> >
> > ok. linux-kselftest next has both shared logic and install patches
> > now.
>
> Thanks, looks good to me.
And also 6/9 "selftests: Set CC using CROSS_COMPILE once in lib.mk" would be
nice and is uncontroversial, I think:
https://lkml.org/lkml/2015/3/11/5
cheers
^ permalink raw reply
* Re: [PATCH v4 4/9] selftests: Add install target
From: Michael Ellerman @ 2015-03-16 3:04 UTC (permalink / raw)
To: Shuah Khan; +Cc: linux-kernel, davej, mmarek, linux-api
In-Reply-To: <5503577C.9050002@osg.samsung.com>
On Fri, 2015-03-13 at 15:32 -0600, Shuah Khan wrote:
> On 03/13/2015 11:20 AM, Shuah Khan wrote:
> > On 03/10/2015 10:06 PM, Michael Ellerman wrote:
> >> This adds make install support to selftests. The basic usage is:
> >>
> >> $ cd tools/testing/selftests
> >> $ make install
> >>
> >> That installs into tools/testing/selftests/install, which can then be
> >> copied where ever necessary.
> >>
> >> The install destination is also configurable using eg:
> >>
> >> $ INSTALL_PATH=/mnt/selftests make install
> >>
> >> The implementation uses two targets in the child makefiles. The first
> >> "install" is expected to install all files into $(INSTALL_PATH).
> >>
> >> The second, "emit_tests", is expected to emit the test instructions (ie.
> >> bash script) on stdout. Separating this from install means the child
> >> makefiles need no knowledge of the location of the test script.
> >>
> >> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
> >
> > Thanks for doing the work. This patch will be applied to next and will
> > be queued for 4.1
> >
>
> ok. linux-kselftest next has both shared logic and install patches
> now.
Thanks, looks good to me.
Can you also apply the patch to install the powerpc tests, or was there a
problem with it? It seems to apply cleanly for me.
https://lkml.org/lkml/2015/3/11/9
cheers
^ permalink raw reply
* Re: [PATCH 2/2] selftests/timers: change to use shared logic to run and install tests
From: Michael Ellerman @ 2015-03-16 2:48 UTC (permalink / raw)
To: John Stultz; +Cc: Shuah Khan, Thomas Gleixner, Linux API, lkml
In-Reply-To: <CALAqxLXApErmHgCzgoo9xkBCZaP59yu=f9WEmmYwTH29ZrDadQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
On Fri, 2015-03-13 at 20:14 -0700, John Stultz wrote:
> On Fri, Mar 13, 2015 at 3:57 PM, Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org> wrote:
> > Change the timers Makefile to make use of shared run and install
> > logic in lib.mk. Destructive tests are installed. Regular tests
> > are emited to run_kselftest script to match the run_tests behavior.
> >
> > Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
> > ---
> > tools/testing/selftests/timers/Makefile | 20 +++++++++++---------
> > 1 file changed, 11 insertions(+), 9 deletions(-)
> >
> > diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile
> > index 9da3498..61e7284 100644
> > --- a/tools/testing/selftests/timers/Makefile
> > +++ b/tools/testing/selftests/timers/Makefile
> > @@ -7,19 +7,21 @@ bins = posix_timers nanosleep inconsistency-check nsleep-lat raw_skew \
> > alarmtimer-suspend change_skew skew_consistency clocksource-switch \
> > leap-a-day leapcrash set-tai set-2038
> >
> > +TEST_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
> > + inconsistency-check raw_skew
> > +TEST_FILES = threadtest alarmtimer-suspend valid-adjtimex change_skew \
> > + skew_consistency clocksource-switch leap-a-day leapcrash \
> > + set-tai set-2038
> > +
> > +RUN_TESTS_WITH_ARGS := ./threadtest -t 30 -n 8 || echo "selftests: threadtest [FAIL]"
> > +
> > +EMIT_TESTS_WITH_ARGS := echo "$(RUN_TESTS_WITH_ARGS)"
> > +
>
> So my make-foo isn't very strong, but no objections from me.
>
> My only thoughts:
> 1) Would it be better if threadtest can be made to have better
> defaults for kselftest so you don't need that extra logic?
That would help. But with the patch I just sent I think it's no bother, it's
only a little extra logic and it's only in the timers Makefile.
> 2) While I get that TEST_FILES is likely going to be used to copy the
> destructive tests over, It feels a little like its being bundled in
> with something like data files that tests might need, which seems sort
> of hackish. Would TEST_PROGS_EXTENDED or something be more clear and
> make more sense?
That doesn't really bother me. You're right that TEST_FILES is originally
intended for data files etc. but I don't think it's a big hack to use it for
other tests that shouldn't be run by default. Still if it bothers you I'm happy
to add a separate variable for it, they are cheap :)
cheers
^ permalink raw reply
* Re: [PATCH 2/2] selftests/timers: change to use shared logic to run and install tests
From: Michael Ellerman @ 2015-03-16 2:46 UTC (permalink / raw)
To: Shuah Khan
Cc: john.stultz-QSEj5FYQhm4dnm+yROfE0A, tglx-hfZtesqFncYOwBW4kG4KsQ,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <4E4E8162-A30D-4460-BF55-12C269760577-Gsx/Oe8HsFggBc27wqDAHg@public.gmane.org>
On Sun, 2015-03-15 at 19:42 +1100, Michael Ellerman wrote:
>
> On 14 March 2015 09:57:51 GMT+11:00, Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org> wrote:
> >Change the timers Makefile to make use of shared run and install
> >logic in lib.mk. Destructive tests are installed. Regular tests
> >are emited to run_kselftest script to match the run_tests behavior.
> >
> >Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
> >---
> > tools/testing/selftests/timers/Makefile | 20 +++++++++++---------
> > 1 file changed, 11 insertions(+), 9 deletions(-)
> >
> >diff --git a/tools/testing/selftests/timers/Makefile
> >b/tools/testing/selftests/timers/Makefile
> >index 9da3498..61e7284 100644
> >--- a/tools/testing/selftests/timers/Makefile
> >+++ b/tools/testing/selftests/timers/Makefile
> >@@ -7,19 +7,21 @@ bins = posix_timers nanosleep inconsistency-check
> >nsleep-lat raw_skew \
> > alarmtimer-suspend change_skew skew_consistency clocksource-switch \
> > leap-a-day leapcrash set-tai set-2038
> >
> >+TEST_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat
> >mqueue-lat \
> >+ inconsistency-check raw_skew
> >+TEST_FILES = threadtest alarmtimer-suspend valid-adjtimex change_skew
> >\
> >+ skew_consistency clocksource-switch leap-a-day leapcrash \
> >+ set-tai set-2038
> >+
> >+RUN_TESTS_WITH_ARGS := ./threadtest -t 30 -n 8 || echo "selftests:
> >threadtest [FAIL]"
>
> You shouldn't need this separate variable. As long as you override RUN_TESTS after you include lib.mk you can include the default value, eg:
>
> override RUN_TESTS := $(RUN_TESTS) ./threadtest -t 30 -n 8 || echo "selftests: threadtest [FAIL]"
>
> I'll test that in the morning and send a proper patch.
How's this look?
Contents of install/timers (same as with your patch):
$ ls install/timers/
alarmtimer-suspend* clocksource-switch* leap-a-day* mqueue-lat* nsleep-lat* raw_skew* set-tai* skew_consistency* valid-adjtimex*
change_skew* inconsistency-check* leapcrash* nanosleep* posix_timers* set-2038* set-timer-lat* threadtest*
And in run_kselftest.sh:
echo ; echo Running tests in timers
echo ========================================
cd timers
(./posix_timers && echo "selftests: posix_timers [PASS]") || echo "selftests: posix_timers [FAIL]"
(./nanosleep && echo "selftests: nanosleep [PASS]") || echo "selftests: nanosleep [FAIL]"
(./nsleep-lat && echo "selftests: nsleep-lat [PASS]") || echo "selftests: nsleep-lat [FAIL]"
(./set-timer-lat && echo "selftests: set-timer-lat [PASS]") || echo "selftests: set-timer-lat [FAIL]"
(./mqueue-lat && echo "selftests: mqueue-lat [PASS]") || echo "selftests: mqueue-lat [FAIL]"
(./inconsistency-check && echo "selftests: inconsistency-check [PASS]") || echo "selftests: inconsistency-check [FAIL]"
(./raw_skew && echo "selftests: raw_skew [PASS]") || echo "selftests: raw_skew [FAIL]"
./threadtest -t 30 -n 8 || echo selftests: threadtest [FAIL]
cd $ROOT
cheers
>From 5ea5ea0e5adee5317978965acc4594dce648da63 Mon Sep 17 00:00:00 2001
From: Michael Ellerman <mpe-Gsx/Oe8HsFggBc27wqDAHg@public.gmane.org>
Date: Mon, 16 Mar 2015 13:38:06 +1100
Subject: [PATCH] selftests/timers: Use shared logic to run and install tests
Change the timers Makefile to make use of shared run and install logic
in lib.mk. Destructive tests are installed. Regular tests are emited to
run_kselftest script to match the run_tests behavior.
Signed-off-by: Michael Ellerman <mpe-Gsx/Oe8HsFggBc27wqDAHg@public.gmane.org>
---
tools/testing/selftests/timers/Makefile | 33 +++++++++++++++++----------------
1 file changed, 17 insertions(+), 16 deletions(-)
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile
index 9da3498987c8..8ba056ee8b48 100644
--- a/tools/testing/selftests/timers/Makefile
+++ b/tools/testing/selftests/timers/Makefile
@@ -1,25 +1,26 @@
-CC = $(CROSS_COMPILE)gcc
BUILD_FLAGS = -DKTEST
CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS)
LDFLAGS += -lrt -lpthread
-bins = posix_timers nanosleep inconsistency-check nsleep-lat raw_skew \
- set-timer-lat threadtest mqueue-lat valid-adjtimex \
- alarmtimer-suspend change_skew skew_consistency clocksource-switch \
- leap-a-day leapcrash set-tai set-2038
-
-all: ${bins}
# these are all "safe" tests that don't modify
# system time or require escalated privledges
-run_tests: all
- ./posix_timers
- ./nanosleep
- ./nsleep-lat
- ./set-timer-lat
- ./mqueue-lat
- ./inconsistency-check
- ./raw_skew
- ./threadtest -t 30 -n 8
+TEST_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
+ inconsistency-check raw_skew
+
+TEST_FILES = threadtest alarmtimer-suspend valid-adjtimex change_skew \
+ skew_consistency clocksource-switch leap-a-day leapcrash \
+ set-tai set-2038
+
+bins = $(TEST_PROGS) $(TEST_FILES)
+
+all: ${bins}
+
+include ../lib.mk
+
+THREADTEST := ./threadtest -t 30 -n 8 || echo "selftests: threadtest [FAIL]"
+
+override RUN_TESTS := $(RUN_TESTS) $(THREADTEST)
+override EMIT_TESTS := $(EMIT_TESTS) echo "$(THREADTEST)"
# these tests require escalated privledges
# and may modify the system time or trigger
--
2.1.0
^ permalink raw reply related
* Re: [PATCH v2 net-next 0/2] bpf: allow eBPF access skb fields
From: David Miller @ 2015-03-16 2:03 UTC (permalink / raw)
To: ast-uqk4Ao+rVK5Wk0Htik3J/w
Cc: daniel-FeC+5ew28dpmcu3hnIyYJQ, tgraf-G/eBtMaohhA,
linux-api-u79uwXL29TY76Z2rM5mHXA, netdev-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1426273064-4837-1-git-send-email-ast-uqk4Ao+rVK5Wk0Htik3J/w@public.gmane.org>
From: Alexei Starovoitov <ast-uqk4Ao+rVK5Wk0Htik3J/w@public.gmane.org>
Date: Fri, 13 Mar 2015 11:57:41 -0700
> Hi All,
>
> V1->V2:
> - refactored field access converter into common helper convert_skb_access()
> used in both classic and extended BPF
> - added missing build_bug_on for field 'len'
> - added comment to uapi/linux/bpf.h as suggested by Daniel
> - dropped exposing 'ifindex' field for now
>
> classic BPF has a way to access skb fields, whereas extended BPF didn't.
> This patch introduces this ability.
I've applied this series.
I guess you guys can argue forever where the SKB offset validation
checks should be, and if you decide to do things differently than
it is done in this series just send me a followup patch.
Thanks.
^ permalink raw reply
* Re: [PATCH] selftests: Fix build failures when invoked from kselftest target
From: Michael Ellerman @ 2015-03-16 0:38 UTC (permalink / raw)
To: Shuah Khan
Cc: linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-kernel-u79uwXL29TY76Z2rM5mHXA
In-Reply-To: <1426297504-14432-1-git-send-email-shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
On Fri, 2015-03-13 at 19:45 -0600, Shuah Khan wrote:
> Several tests that rely on implicit build rules fail to build,
> when invoked from the main Makefile kselftest target. These
> failures are due to --no-builtin-rules and --no-builtin-variables
> options set in the inherited MAKEFLAGS.
>
> --no-builtin-rules eliminates the use of built-in implicit rules
> and --no-builtin-variables is for not defining built-in variables.
> These two options override the use of implicit rules resulting in
> build failures. In addition, inherited LDFLAGS result in build
> failures and there is no need to define LDFLAGS. Clear LDFLAGS
> and MAKEFLAG when make is invoked from the main Makefile kselftest
> target. Fixing this at selftests Makefile avoids changing the main
> Makefile and keeps this change self contained at selftests level.
>
> Signed-off-by: Shuah Khan <shuahkh-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org>
> ---
> tools/testing/selftests/Makefile | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
> index 4e51122..8e09db7 100644
> --- a/tools/testing/selftests/Makefile
> +++ b/tools/testing/selftests/Makefile
> @@ -22,6 +22,15 @@ TARGETS += vm
> TARGETS_HOTPLUG = cpu-hotplug
> TARGETS_HOTPLUG += memory-hotplug
>
> +# Clear LDFLAGS and MAKEFLAGS if called from main
> +# Makefile to avoid test build failures when test
> +# Makefile doesn't have explicit build rules.
> +ifeq (1,$(MAKELEVEL))
> +undefine LDFLAGS
> +override define MAKEFLAGS =
> +endef
> +endif
You shouldn't need to use define/endef here, that is just for multi-line
variables.
This should be equivalent:
ifeq (1,$(MAKELEVEL))
undefine LDFLAGS
override MAKEFLAGS =
endif
cheers
^ permalink raw reply
* Re: [PATCH v2 5/7] clone4: Add a CLONE_AUTOREAP flag to automatically reap the child process
From: Josh Triplett @ 2015-03-15 23:34 UTC (permalink / raw)
To: Oleg Nesterov
Cc: Al Viro, Andrew Morton, Andy Lutomirski, Ingo Molnar, Kees Cook,
Paul E. McKenney, H. Peter Anvin, Rik van Riel, Thomas Gleixner,
Michael Kerrisk, Thiago Macieira,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20150315195506.GA29475-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
On Sun, Mar 15, 2015 at 08:55:06PM +0100, Oleg Nesterov wrote:
> On 03/15, Josh Triplett wrote:
> > On Sun, Mar 15, 2015 at 03:52:23PM +0100, Oleg Nesterov wrote:
> > > On 03/15, Josh Triplett wrote:
> > > > Add a CLONE_AUTOREAP flag to request this behavior unconditionally,
> > >
> > > Yes, CLONE_AUTOREAP is much better. And I agree (mostly) with that
> > > we should rely on do_notify_parent().
> > >
> > > Howver the patch still doesn't look right. First of all, ->autoreap
> > > should be per-process, not per-thread.
> >
> > Ah, you're thinking of the case where the parent process launches a
> > ...
>
> Not really, although we probably need more sanity checks.
>
> It should be per-process simply because this "autoreap" affects the whole
> process. And the sub-threads are already "autoreap". And these 2 autoreap's
> semantics differ, we should not confuse them.
Will the approach I suggested, of having clones with CLONE_THREAD
inherit the autoreap value rather than setting it from CLONE_AUTOREAP,
implement the semantics you're looking for?
Also, are you suggesting that CLONE_AUTOREAP with CLONE_THREAD should
produce -EINVAL, or just that it should be ignored?
> > (As an aside, what *is* the use case for CLONE_PARENT without
> > CLONE_THREAD?)
>
> To me CLONE_PARENT is another historical mistake and the source of misc
> problems ;)
I kinda figured. :)
> > > And there are ptrace/mt issues,
> > > it seems. Just for example, we should avoid EXIT_TRACE if autoreap in
> > > wait_task_zombie() even if we are going to re-notify parent.
> >
> > I don't see how EXIT_TRACE can happen in wait_task_zombie if autoreap is
> > set. wait_task_zombie does a cmpxchg with exit_state and doesn't
> > proceed unless exit_state was EXIT_ZOMBIE, and I don't see how we can
> > ever reach the EXIT_ZOMBIE state if autoreap.
>
> Because you again forgot about ptrace ;)
>
> Josh. Let me try to summarise this later when I have time. Again, I am
> not sure, perhaps this is even simpler than I currently think. And let
> me apologize in advance, most probably I will be busy tomorrow.
I look forward to your later review and feedback.
- Josh Triplett
^ permalink raw reply
* [RFC/PATCH 5/5] drm/rcar-du: Restart the DU group when a plane source changes
From: Laurent Pinchart @ 2015-03-15 21:55 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh, linux-api, Magnus Damm, Daniel Vetter, linux-media
In-Reply-To: <1426456540-21006-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com>
Plane sources are configured by the VSPS bit in the PnDDCR4 register.
Although the datasheet states that the bit is updated during vertical
blanking, it seems that updates only occur when the DU group is held in
reset through the DSYSR.DRES bit. Restart the group if the source
changes.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 ++++++++--
drivers/gpu/drm/rcar-du/rcar_du_group.c | 2 ++
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 22 ++++++++++++++++++++--
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 1 +
4 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 7d0b8ef9bea2..969d49ab0d09 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -249,6 +249,8 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
}
}
+ mutex_lock(&rcrtc->group->lock);
+
/* Select display timing and dot clock generator 2 for planes associated
* with superposition controller 2.
*/
@@ -260,15 +262,19 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
* split, or through a module parameter). Flicker would then
* occur only if we need to break the pre-association.
*/
- mutex_lock(&rcrtc->group->lock);
if (rcar_du_group_read(rcrtc->group, DPTSR) != dptsr) {
rcar_du_group_write(rcrtc->group, DPTSR, dptsr);
if (rcrtc->group->used_crtcs)
rcar_du_group_restart(rcrtc->group);
}
- mutex_unlock(&rcrtc->group->lock);
}
+ /* Restart the group if plane sources have changed. */
+ if (rcrtc->group->planes.need_restart)
+ rcar_du_group_restart(rcrtc->group);
+
+ mutex_unlock(&rcrtc->group->lock);
+
rcar_du_group_write(rcrtc->group, rcrtc->index % 2 ? DS2PR : DS1PR,
dspr);
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 71f50bf45581..101997e6e531 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -154,6 +154,8 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
void rcar_du_group_restart(struct rcar_du_group *rgrp)
{
+ rgrp->planes.need_restart = false;
+
__rcar_du_group_start_stop(rgrp, false);
__rcar_du_group_start_stop(rgrp, true);
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index e77f9d93c1c5..51a9f9d5fa46 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -360,9 +360,27 @@ static void rcar_du_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct rcar_du_plane *rplane = to_rcar_plane(plane);
+ struct rcar_du_plane_state *old_rstate;
+ struct rcar_du_plane_state *new_rstate;
- if (plane->state->crtc)
- rcar_du_plane_setup(rplane);
+ if (!plane->state->crtc)
+ return;
+
+ rcar_du_plane_setup(rplane);
+
+ /* Check whether the source has changed from memory to live source or
+ * from live source to memory. The source has been configured by the
+ * VSPS bit in the PnDDCR4 register. Although the datasheet states that
+ * the bit is updated during vertical blanking, it seems that updates
+ * only occur when the DU group is held in reset through the DSYSR.DRES
+ * bit. We thus need to restart the group if the source changes.
+ */
+ old_rstate = to_rcar_du_plane_state(old_state);
+ new_rstate = to_rcar_du_plane_state(plane->state);
+
+ if ((old_rstate->source == RCAR_DU_PLANE_MEMORY) !=
+ (new_rstate->source == RCAR_DU_PLANE_MEMORY))
+ rplane->group->planes.need_restart = true;
}
static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 9a6132899d59..694b44c151b6 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -47,6 +47,7 @@ static inline struct rcar_du_plane *to_rcar_plane(struct drm_plane *plane)
struct rcar_du_planes {
struct rcar_du_plane planes[RCAR_DU_NUM_KMS_PLANES];
+ bool need_restart;
struct drm_property *alpha;
struct drm_property *colorkey;
--
2.0.5
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [RFC/PATCH 4/5] drm/rcar-du: Add VSP1 live source support
From: Laurent Pinchart @ 2015-03-15 21:55 UTC (permalink / raw)
To: dri-devel; +Cc: linux-sh, linux-api, Magnus Damm, Daniel Vetter, linux-media
In-Reply-To: <1426456540-21006-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com>
Register live sources for VSPD0 and VSPD1 and configure the plane source
at plane setup time to source frames from memory or from the VSP1.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_drv.c | 6 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 3 +
drivers/gpu/drm/rcar-du/rcar_du_group.c | 19 ++--
drivers/gpu/drm/rcar-du/rcar_du_group.h | 2 +
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 22 +++-
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 173 +++++++++++++++++++++++++-------
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 3 +
drivers/gpu/drm/rcar-du/rcar_du_regs.h | 1 +
8 files changed, 177 insertions(+), 52 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index da1216a73969..e16a912327b7 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -58,7 +58,8 @@ static const struct rcar_du_device_info rcar_du_r8a7779_info = {
static const struct rcar_du_device_info rcar_du_r8a7790_info = {
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
- | RCAR_DU_FEATURE_EXT_CTRL_REGS,
+ | RCAR_DU_FEATURE_EXT_CTRL_REGS
+ | RCAR_DU_FEATURE_VSP1_SOURCE,
.quirks = RCAR_DU_QUIRK_ALIGN_128B | RCAR_DU_QUIRK_LVDS_LANES,
.num_crtcs = 3,
.routes = {
@@ -86,7 +87,8 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = {
static const struct rcar_du_device_info rcar_du_r8a7791_info = {
.features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
- | RCAR_DU_FEATURE_EXT_CTRL_REGS,
+ | RCAR_DU_FEATURE_EXT_CTRL_REGS
+ | RCAR_DU_FEATURE_VSP1_SOURCE,
.num_crtcs = 2,
.routes = {
/* R8A7791 has one RGB output, one LVDS output and one
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index c7c538dd2e68..b5be16053e71 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -29,6 +29,7 @@ struct rcar_du_lvdsenc;
#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */
#define RCAR_DU_FEATURE_EXT_CTRL_REGS (1 << 1) /* Has extended control registers */
+#define RCAR_DU_FEATURE_VSP1_SOURCE (1 << 2) /* Has inputs from VSP1 */
#define RCAR_DU_QUIRK_ALIGN_128B (1 << 0) /* Align pitches to 128 bytes */
#define RCAR_DU_QUIRK_LVDS_LANES (1 << 1) /* LVDS lanes 1 and 3 inverted */
@@ -84,6 +85,8 @@ struct rcar_du_device {
struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];
unsigned int dpad0_source;
+ unsigned int vspd1_sink;
+
struct rcar_du_lvdsenc *lvds[RCAR_DU_MAX_LVDS];
struct {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
index 1bdc0ee0c248..71f50bf45581 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -49,10 +49,13 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;
/* The DEFR8 register for the first group also controls RGB output
- * routing to DPAD0
+ * routing to DPAD0 and VSPD1 routing to DU0/1/2.
*/
- if (rgrp->index == 0)
+ if (rgrp->index == 0) {
defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
+ if (rgrp->dev->vspd1_sink == 2)
+ defr8 |= DEFR8_VSCS;
+ }
rcar_du_group_write(rgrp, DEFR8, defr8);
}
@@ -155,17 +158,17 @@ void rcar_du_group_restart(struct rcar_du_group *rgrp)
__rcar_du_group_start_stop(rgrp, true);
}
-static int rcar_du_set_dpad0_routing(struct rcar_du_device *rcdu)
+int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu)
{
int ret;
if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_EXT_CTRL_REGS))
return 0;
- /* RGB output routing to DPAD0 is configured in the DEFR8 register of
- * the first group. As this function can be called with the DU0 and DU1
- * CRTCs disabled, we need to enable the first group clock before
- * accessing the register.
+ /* RGB output routing to DPAD0 and VSP1D routing to DU0/1/2 are
+ * configured in the DEFR8 register of the first group. As this function
+ * can be called with the DU0 and DU1 CRTCs disabled, we need to enable
+ * the first group clock before accessing the register.
*/
ret = clk_prepare_enable(rcdu->crtcs[0].clock);
if (ret < 0)
@@ -196,5 +199,5 @@ int rcar_du_group_set_routing(struct rcar_du_group *rgrp)
rcar_du_group_write(rgrp, DORCR, dorcr);
- return rcar_du_set_dpad0_routing(rgrp->dev);
+ return rcar_du_set_dpad0_vsp1_routing(rgrp->dev);
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
index ed36433fbe84..3fdf77171034 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_group.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
@@ -52,4 +52,6 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start);
void rcar_du_group_restart(struct rcar_du_group *rgrp);
int rcar_du_group_set_routing(struct rcar_du_group *rgrp);
+int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu);
+
#endif /* __RCAR_DU_GROUP_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index 17f89bfca8f8..b78ced38b696 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -217,17 +217,25 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
*/
static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
- struct rcar_du_plane_state *state)
+ struct rcar_du_plane_state *new_state)
{
- const struct rcar_du_format_info *cur_format;
+ struct rcar_du_plane_state *cur_state;
- cur_format = to_rcar_du_plane_state(plane->plane.state)->format;
+ cur_state = to_rcar_du_plane_state(plane->plane.state);
/* Lowering the number of planes doesn't strictly require reallocation
* as the extra hardware plane will be freed when committing, but doing
* so could lead to more fragmentation.
*/
- return !cur_format || cur_format->planes != state->format->planes;
+ if (!cur_state->format ||
+ cur_state->format->planes != new_state->format->planes)
+ return true;
+
+ /* Reallocate hardware planes if the source has changed. */
+ if (cur_state->source != new_state->source)
+ return true;
+
+ return false;
}
static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
@@ -776,6 +784,12 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
drm_mode_config_reset(dev);
+ if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
+ ret = rcar_du_vsp1_sources_init(rcdu);
+ if (ret < 0)
+ return ret;
+ }
+
drm_kms_helper_poll_init(dev);
if (dev->mode_config.num_connector) {
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 80e4dba78aef..e77f9d93c1c5 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -20,21 +20,84 @@
#include <drm/drm_plane_helper.h>
#include "rcar_du_drv.h"
+#include "rcar_du_group.h"
#include "rcar_du_kms.h"
#include "rcar_du_plane.h"
#include "rcar_du_regs.h"
-#define RCAR_DU_COLORKEY_NONE (0 << 24)
-#define RCAR_DU_COLORKEY_SOURCE (1 << 24)
-#define RCAR_DU_COLORKEY_MASK (1 << 24)
+/* -----------------------------------------------------------------------------
+ * Live Sources
+ */
+
+struct rcar_du_vsp1_source {
+ struct drm_live_source base;
+
+ enum rcar_du_plane_source source;
+};
-static u32 rcar_du_plane_read(struct rcar_du_group *rgrp,
- unsigned int index, u32 reg)
+static inline struct rcar_du_vsp1_source *
+to_rcar_vsp1_source(struct drm_live_source *src)
{
- return rcar_du_read(rgrp->dev,
- rgrp->mmio_offset + index * PLANE_OFF + reg);
+ return container_of(src, struct rcar_du_vsp1_source, base);
+}
+
+static const struct drm_live_source_funcs rcar_du_live_source_funcs = {
+ .destroy = drm_live_source_cleanup,
+};
+
+static const uint32_t source_formats[] = {
+ DRM_FORMAT_XRGB8888,
+};
+
+int rcar_du_vsp1_sources_init(struct rcar_du_device *rcdu)
+{
+ static const struct {
+ enum rcar_du_plane_source source;
+ unsigned int planes;
+ } sources[] = {
+ { RCAR_DU_PLANE_VSPD0, BIT(RCAR_DU_NUM_KMS_PLANES - 1) },
+ { RCAR_DU_PLANE_VSPD1, BIT(RCAR_DU_NUM_KMS_PLANES - 2) |
+ BIT(2 * RCAR_DU_NUM_KMS_PLANES - 1) },
+ };
+ unsigned int planes_mask;
+ unsigned int num_planes;
+ unsigned int i;
+
+ num_planes = RCAR_DU_NUM_KMS_PLANES * DIV_ROUND_UP(rcdu->num_crtcs, 2);
+ planes_mask = (1 << num_planes) - 1;
+
+ for (i = 0; i < ARRAY_SIZE(sources); ++i) {
+ struct rcar_du_vsp1_source *src;
+ char name[6];
+ int ret;
+
+ src = devm_kzalloc(rcdu->dev, sizeof(*src), GFP_KERNEL);
+ if (src == NULL)
+ return -ENOMEM;
+
+ src->source = sources[i].source;
+
+ sprintf(name, "vspd%u", i);
+ ret = drm_live_source_init(rcdu->ddev, &src->base, name,
+ sources[i].planes & planes_mask,
+ source_formats,
+ ARRAY_SIZE(source_formats),
+ &rcar_du_live_source_funcs);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
}
+/* -----------------------------------------------------------------------------
+ * Planes
+ */
+
+#define RCAR_DU_COLORKEY_NONE (0 << 24)
+#define RCAR_DU_COLORKEY_SOURCE (1 << 24)
+#define RCAR_DU_COLORKEY_MASK (1 << 24)
+
static void rcar_du_plane_write(struct rcar_du_group *rgrp,
unsigned int index, u32 reg, u32 data)
{
@@ -42,34 +105,47 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
data);
}
-static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
+static void rcar_du_plane_setup_scanout(struct rcar_du_plane *plane)
{
struct rcar_du_plane_state *state =
to_rcar_du_plane_state(plane->plane.state);
- struct drm_framebuffer *fb = plane->plane.state->fb;
struct rcar_du_group *rgrp = plane->group;
unsigned int src_x = state->state.src_x >> 16;
unsigned int src_y = state->state.src_y >> 16;
unsigned int index = state->hwindex;
- struct drm_gem_cma_object *gem;
+ unsigned int pitch;
bool interlaced;
- u32 mwr;
+ u32 dma[2];
interlaced = state->state.crtc->state->adjusted_mode.flags
& DRM_MODE_FLAG_INTERLACE;
+ if (plane->plane.state->fb) {
+ struct drm_framebuffer *fb = state->state.fb;
+ struct drm_gem_cma_object *gem;
+ unsigned int i;
+
+ if (state->format->planes == 2)
+ pitch = fb->pitches[0];
+ else
+ pitch = fb->pitches[0] * 8 / state->format->bpp;
+
+ for (i = 0; i < state->format->planes; ++i) {
+ gem = drm_fb_cma_get_gem_obj(fb, i);
+ dma[i] = gem->paddr + fb->offsets[i];
+ }
+ } else {
+ pitch = state->state.src_w >> 16;
+ dma[0] = 0;
+ dma[1] = 0;
+ }
+
/* Memory pitch (expressed in pixels). Must be doubled for interlaced
* operation with 32bpp formats.
*/
- if (state->format->planes == 2)
- mwr = fb->pitches[0];
- else
- mwr = fb->pitches[0] * 8 / state->format->bpp;
-
- if (interlaced && state->format->bpp == 32)
- mwr *= 2;
-
- rcar_du_plane_write(rgrp, index, PnMWR, mwr);
+ rcar_du_plane_write(rgrp, index, PnMWR,
+ (interlaced && state->format->bpp == 32) ?
+ pitch * 2 : pitch);
/* The Y position is expressed in raster line units and must be doubled
* for 32bpp formats, according to the R8A7790 datasheet. No mention of
@@ -87,21 +163,18 @@ static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
(!interlaced && state->format->bpp == 32 ? 2 : 1));
- gem = drm_fb_cma_get_gem_obj(fb, 0);
- rcar_du_plane_write(rgrp, index, PnDSA0R, gem->paddr + fb->offsets[0]);
+ rcar_du_plane_write(rgrp, index, PnDSA0R, dma[0]);
if (state->format->planes == 2) {
index = (index + 1) % 8;
- rcar_du_plane_write(rgrp, index, PnMWR, fb->pitches[0]);
+ rcar_du_plane_write(rgrp, index, PnMWR, pitch);
rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
(state->format->bpp == 16 ? 2 : 1) / 2);
- gem = drm_fb_cma_get_gem_obj(fb, 1);
- rcar_du_plane_write(rgrp, index, PnDSA0R,
- gem->paddr + fb->offsets[1]);
+ rcar_du_plane_write(rgrp, index, PnDSA0R, dma[1]);
}
}
@@ -168,8 +241,8 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
}
}
-static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
- unsigned int index)
+static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
+ unsigned int index)
{
struct rcar_du_plane_state *state =
to_rcar_du_plane_state(plane->plane.state);
@@ -182,10 +255,6 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
* The data format is selected by the DDDF field in PnMR and the EDF
* field in DDCR4.
*/
- ddcr4 = rcar_du_plane_read(rgrp, index, PnDDCR4);
- ddcr4 &= ~PnDDCR4_EDF_MASK;
- ddcr4 |= state->format->edf | PnDDCR4_CODE;
-
rcar_du_plane_setup_mode(plane, index);
if (state->format->planes == 2) {
@@ -204,6 +273,11 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
}
rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
+
+ ddcr4 = state->format->edf | PnDDCR4_CODE;
+ if (state->source != RCAR_DU_PLANE_MEMORY)
+ ddcr4 |= PnDDCR4_VSPS;
+
rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
/* Destination position and size */
@@ -224,11 +298,21 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane)
struct rcar_du_plane_state *state =
to_rcar_du_plane_state(plane->plane.state);
- __rcar_du_plane_setup(plane, state->hwindex);
+ rcar_du_plane_setup_format(plane, state->hwindex);
if (state->format->planes == 2)
- __rcar_du_plane_setup(plane, (state->hwindex + 1) % 8);
+ rcar_du_plane_setup_format(plane, (state->hwindex + 1) % 8);
+
+ rcar_du_plane_setup_scanout(plane);
+
+ if (state->source == RCAR_DU_PLANE_VSPD1) {
+ unsigned int vspd1_sink = plane->group->index ? 2 : 0;
+ struct rcar_du_device *rcdu = plane->group->dev;
- rcar_du_plane_setup_fb(plane);
+ if (rcdu->vspd1_sink != vspd1_sink) {
+ rcdu->vspd1_sink = vspd1_sink;
+ rcar_du_set_dpad0_vsp1_routing(rcdu);
+ }
+ }
}
static int rcar_du_plane_atomic_check(struct drm_plane *plane,
@@ -237,8 +321,9 @@ static int rcar_du_plane_atomic_check(struct drm_plane *plane,
struct rcar_du_plane_state *rstate = to_rcar_du_plane_state(state);
struct rcar_du_plane *rplane = to_rcar_plane(plane);
struct rcar_du_device *rcdu = rplane->group->dev;
+ uint32_t pixel_format;
- if (!state->fb || !state->crtc) {
+ if ((!state->fb && !state->src) || !state->crtc) {
rstate->format = NULL;
return 0;
}
@@ -249,13 +334,25 @@ static int rcar_du_plane_atomic_check(struct drm_plane *plane,
return -EINVAL;
}
- rstate->format = rcar_du_format_info(state->fb->pixel_format);
+ pixel_format = state->fb ? state->fb->pixel_format
+ : state->src->pixel_format;
+ rstate->format = rcar_du_format_info(pixel_format);
if (rstate->format == NULL) {
dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__,
- state->fb->pixel_format);
+ pixel_format);
+ return -EINVAL;
+ }
+
+ if (state->src && rstate->format->planes > 1) {
+ dev_dbg(rcdu->dev,
+ "%s: unsupported format %08x for live source\n",
+ __func__, pixel_format);
return -EINVAL;
}
+ rstate->source = state->fb ? RCAR_DU_PLANE_MEMORY
+ : to_rcar_vsp1_source(state->src)->source;
+
return 0;
}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index 81c2d361a94f..9a6132899d59 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -17,6 +17,7 @@
#include <drm/drmP.h>
#include <drm/drm_crtc.h>
+struct rcar_du_device;
struct rcar_du_format_info;
struct rcar_du_group;
@@ -70,6 +71,8 @@ to_rcar_du_plane_state(struct drm_plane_state *state)
return container_of(state, struct rcar_du_plane_state, state);
}
+int rcar_du_vsp1_sources_init(struct rcar_du_device *rcdu);
+
int rcar_du_planes_init(struct rcar_du_group *rgrp);
void rcar_du_plane_setup(struct rcar_du_plane *plane);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
index 70fcbc471ebd..ac9c3e511e79 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h
@@ -389,6 +389,7 @@
#define PnDDCR4 0x00190
#define PnDDCR4_CODE (0x7766 << 16)
+#define PnDDCR4_VSPS (1 << 13)
#define PnDDCR4_SDFS_RGB (0 << 4)
#define PnDDCR4_SDFS_YC (5 << 4)
#define PnDDCR4_SDFS_MASK (7 << 4)
--
2.0.5
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [RFC/PATCH 3/5] drm/rcar-du: Add VSP1 support to the planes allocator
From: Laurent Pinchart @ 2015-03-15 21:55 UTC (permalink / raw)
To: dri-devel
Cc: linux-media, linux-sh, linux-api, Daniel Vetter, Rob Clark,
Thierry Reding, Magnus Damm
In-Reply-To: <1426456540-21006-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com>
The R8A7790 DU can source frames directly from the VSP1 devices VSPD0
and VSPD1. VSPD0 feeds DU0/1 plane 0, and VSPD1 feeds either DU2 plane 0
or DU0/1 plane 1.
Allocate the correct fixed plane when sourcing frames from VSPD0 or
VSPD1, and allocate planes in reverse index order otherwise to ensure
maximum availability of planes 0 and 1.
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 40 ++++++++++++++++++++++++++++-----
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 1 +
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 7 ++++++
3 files changed, 43 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index fb052bca574f..17f89bfca8f8 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -244,11 +244,41 @@ static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
return mask;
}
-static int rcar_du_plane_hwalloc(unsigned int num_planes, unsigned int free)
+/*
+ * The R8A7790 DU can source frames directly from the VSP1 devices VSPD0 and
+ * VSPD1. VSPD0 feeds DU0/1 plane 0, and VSPD1 feeds either DU2 plane 0 or
+ * DU0/1 plane 1.
+ *
+ * Allocate the correct fixed plane when sourcing frames from VSPD0 or VSPD1,
+ * and allocate planes in reverse index order otherwise to ensure maximum
+ * availability of planes 0 and 1.
+ *
+ * The caller is responsible for ensuring that the requested source is
+ * compatible with the DU revision.
+ */
+static int rcar_du_plane_hwalloc(struct rcar_du_plane *plane,
+ struct rcar_du_plane_state *state,
+ unsigned int free)
{
- unsigned int i;
+ unsigned int num_planes = state->format->planes;
+ int fixed = -1;
+ int i;
+
+ if (state->source == RCAR_DU_PLANE_VSPD0) {
+ /* VSPD0 feeds plane 0 on DU0/1. */
+ if (plane->group->index != 0)
+ return -EINVAL;
+
+ fixed = 0;
+ } else if (state->source == RCAR_DU_PLANE_VSPD1) {
+ /* VSPD1 feeds plane 1 on DU0/1 or plane 0 on DU2. */
+ fixed = plane->group->index == 0 ? 1 : 0;
+ }
+
+ if (fixed >= 0)
+ return free & (1 << fixed) ? fixed : -EBUSY;
- for (i = 0; i < RCAR_DU_NUM_HW_PLANES; ++i) {
+ for (i = RCAR_DU_NUM_HW_PLANES - 1; i >= 0; --i) {
if (!(free & (1 << i)))
continue;
@@ -256,7 +286,7 @@ static int rcar_du_plane_hwalloc(unsigned int num_planes, unsigned int free)
break;
}
- return i == RCAR_DU_NUM_HW_PLANES ? -EBUSY : i;
+ return i < 0 ? -EBUSY : i;
}
static int rcar_du_atomic_check(struct drm_device *dev,
@@ -372,7 +402,7 @@ static int rcar_du_atomic_check(struct drm_device *dev,
!rcar_du_plane_needs_realloc(plane, plane_state))
continue;
- idx = rcar_du_plane_hwalloc(plane_state->format->planes,
+ idx = rcar_du_plane_hwalloc(plane, plane_state,
group_free_planes[plane->group->index]);
if (idx < 0) {
dev_dbg(rcdu->dev, "%s: no available hardware plane\n",
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 210e5c3fd982..80e4dba78aef 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -288,6 +288,7 @@ static void rcar_du_plane_reset(struct drm_plane *plane)
return;
state->hwindex = -1;
+ state->source = RCAR_DU_PLANE_MEMORY;
state->alpha = 255;
state->colorkey = RCAR_DU_COLORKEY_NONE;
state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index abff0ebeb195..81c2d361a94f 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -28,6 +28,12 @@ struct rcar_du_group;
#define RCAR_DU_NUM_KMS_PLANES 9
#define RCAR_DU_NUM_HW_PLANES 8
+enum rcar_du_plane_source {
+ RCAR_DU_PLANE_MEMORY,
+ RCAR_DU_PLANE_VSPD0,
+ RCAR_DU_PLANE_VSPD1,
+};
+
struct rcar_du_plane {
struct drm_plane plane;
struct rcar_du_group *group;
@@ -51,6 +57,7 @@ struct rcar_du_plane_state {
const struct rcar_du_format_info *format;
int hwindex; /* 0-based, -1 means unused */
+ enum rcar_du_plane_source source;
unsigned int alpha;
unsigned int colorkey;
--
2.0.5
^ permalink raw reply related
* [RFC/PATCH 2/5] drm: Connect live source to plane
From: Laurent Pinchart @ 2015-03-15 21:55 UTC (permalink / raw)
To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
Cc: linux-media-u79uwXL29TY76Z2rM5mHXA,
linux-sh-u79uwXL29TY76Z2rM5mHXA, linux-api-u79uwXL29TY76Z2rM5mHXA,
Daniel Vetter, Rob Clark, Thierry Reding, Magnus Damm
In-Reply-To: <1426456540-21006-1-git-send-email-laurent.pinchart+renesas-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas-ryLnwIuWjnjg/C1BVhZhaw@public.gmane.org>
---
drivers/gpu/drm/armada/armada_overlay.c | 2 +-
drivers/gpu/drm/drm_atomic.c | 7 ++
drivers/gpu/drm/drm_atomic_helper.c | 4 +
drivers/gpu/drm/drm_crtc.c | 134 +++++++++++++++++++++++-----
drivers/gpu/drm/drm_fops.c | 6 +-
drivers/gpu/drm/drm_plane_helper.c | 1 +
drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 +-
drivers/gpu/drm/exynos/exynos_drm_plane.c | 3 +-
drivers/gpu/drm/exynos/exynos_drm_plane.h | 3 +-
drivers/gpu/drm/i915/intel_display.c | 4 +-
drivers/gpu/drm/i915/intel_sprite.c | 2 +-
drivers/gpu/drm/imx/ipuv3-plane.c | 3 +-
drivers/gpu/drm/nouveau/dispnv04/overlay.c | 6 +-
drivers/gpu/drm/omapdrm/omap_plane.c | 1 +
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +-
drivers/gpu/drm/shmobile/shmob_drm_plane.c | 3 +-
drivers/gpu/drm/sti/sti_drm_plane.c | 3 +-
drivers/gpu/drm/sti/sti_hqvdp.c | 2 +-
include/drm/drmP.h | 3 +
include/drm/drm_atomic_helper.h | 1 +
include/drm/drm_crtc.h | 6 ++
include/drm/drm_plane_helper.h | 1 +
22 files changed, 165 insertions(+), 39 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c
index c5b06fdb459c..4d5708bbee6e 100644
--- a/drivers/gpu/drm/armada/armada_overlay.c
+++ b/drivers/gpu/drm/armada/armada_overlay.c
@@ -99,7 +99,7 @@ static unsigned armada_limit(int start, unsigned size, unsigned max)
static int
armada_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
int crtc_x, int crtc_y, unsigned crtc_w, unsigned crtc_h,
uint32_t src_x, uint32_t src_y, uint32_t src_w, uint32_t src_h)
{
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index a6caaae40b9e..0be059be2d58 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -384,6 +384,11 @@ int drm_atomic_plane_set_property(struct drm_plane *plane,
drm_atomic_set_fb_for_plane(state, fb);
if (fb)
drm_framebuffer_unreference(fb);
+ } else if (property == config->prop_src_id) {
+ struct drm_mode_object *obj;
+ obj = drm_mode_object_find(dev, val,
+ DRM_MODE_OBJECT_LIVE_SOURCE);
+ state->src = obj ? obj_to_live_source(obj) : NULL;
} else if (property == config->prop_crtc_id) {
struct drm_crtc *crtc = drm_crtc_find(dev, val);
return drm_atomic_set_crtc_for_plane(state, crtc);
@@ -432,6 +437,8 @@ drm_atomic_plane_get_property(struct drm_plane *plane,
if (property == config->prop_fb_id) {
*val = (state->fb) ? state->fb->base.id : 0;
+ } else if (property == config->prop_src_id) {
+ *val = (state->src) ? state->src->base.id : 0;
} else if (property == config->prop_crtc_id) {
*val = (state->crtc) ? state->crtc->base.id : 0;
} else if (property == config->prop_crtc_x) {
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index a7458813af2b..b182d9e6abba 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -1342,6 +1342,7 @@ EXPORT_SYMBOL(drm_atomic_helper_swap_state);
* @plane: plane object to update
* @crtc: owning CRTC of owning plane
* @fb: framebuffer to flip onto plane
+ * @src: live source to connect to the plane
* @crtc_x: x offset of primary plane on crtc
* @crtc_y: y offset of primary plane on crtc
* @crtc_w: width of primary plane rectangle on crtc
@@ -1359,6 +1360,7 @@ EXPORT_SYMBOL(drm_atomic_helper_swap_state);
int drm_atomic_helper_update_plane(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
@@ -1384,6 +1386,7 @@ retry:
if (ret != 0)
goto fail;
drm_atomic_set_fb_for_plane(plane_state, fb);
+ plane_state->src = src;
plane_state->crtc_x = crtc_x;
plane_state->crtc_y = crtc_y;
plane_state->crtc_h = crtc_h;
@@ -1466,6 +1469,7 @@ retry:
if (ret != 0)
goto fail;
drm_atomic_set_fb_for_plane(plane_state, NULL);
+ plane_state->src = NULL;
plane_state->crtc_x = 0;
plane_state->crtc_y = 0;
plane_state->crtc_h = 0;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index a510c9742a16..f11960372307 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1183,6 +1183,7 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane,
if (drm_core_check_feature(dev, DRIVER_ATOMIC)) {
drm_object_attach_property(&plane->base, config->prop_fb_id, 0);
+ drm_object_attach_property(&plane->base, config->prop_src_id, 0);
drm_object_attach_property(&plane->base, config->prop_crtc_id, 0);
drm_object_attach_property(&plane->base, config->prop_crtc_x, 0);
drm_object_attach_property(&plane->base, config->prop_crtc_y, 0);
@@ -1315,6 +1316,31 @@ void drm_live_source_cleanup(struct drm_live_source *src)
}
EXPORT_SYMBOL(drm_live_source_cleanup);
+void drm_live_sources_release(struct drm_file *priv)
+{
+ struct drm_device *dev = priv->minor->dev;
+ struct drm_live_source *src, *next;
+ int ret;
+
+ drm_modeset_lock_all(dev);
+ mutex_lock(&priv->sources_lock);
+
+ list_for_each_entry_safe(src, next, &priv->sources, filp_head) {
+ list_del_init(&src->filp_head);
+ if (src->plane) {
+ ret = src->plane->funcs->disable_plane(src->plane);
+ if (ret)
+ DRM_ERROR("failed to disable plane with busy source\n");
+ src->plane->src = NULL;
+ src->plane->crtc = NULL;
+ src->plane = NULL;
+ }
+ }
+
+ mutex_unlock(&priv->sources_lock);
+ drm_modeset_unlock_all(dev);
+}
+
/**
* drm_plane_index - find the index of a registered plane
* @plane: plane to find index for
@@ -1468,6 +1494,12 @@ static int drm_mode_create_standard_properties(struct drm_device *dev)
dev->mode_config.prop_fb_id = prop;
prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
+ "SRC_ID", DRM_MODE_OBJECT_FB);
+ if (!prop)
+ return -ENOMEM;
+ dev->mode_config.prop_src_id = prop;
+
+ prop = drm_property_create_object(dev, DRM_MODE_PROP_ATOMIC,
"CRTC_ID", DRM_MODE_OBJECT_CRTC);
if (!prop)
return -ENOMEM;
@@ -2436,6 +2468,8 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
if (plane->fb)
plane_resp->fb_id = plane->fb->base.id;
+ else if (plane->src)
+ plane_resp->fb_id = plane->src->base.id;
else
plane_resp->fb_id = 0;
drm_modeset_unlock(&plane->mutex);
@@ -2492,25 +2526,29 @@ int drm_plane_check_pixel_format(const struct drm_plane *plane, u32 format)
*
* src_{x,y,w,h} are provided in 16.16 fixed point format
*/
-static int __setplane_internal(struct drm_plane *plane,
+static int __setplane_internal(struct drm_file *file_priv,
+ struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int32_t crtc_x, int32_t crtc_y,
uint32_t crtc_w, uint32_t crtc_h,
/* src_{x,y,w,h} values are 16.16 fixed point */
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
{
+ unsigned int width, height;
+ uint32_t pixel_format;
int ret = 0;
- unsigned int fb_width, fb_height;
- /* No fb means shut it down */
- if (!fb) {
+ /* No fb and src means shut it down */
+ if (!fb && !src) {
plane->old_fb = plane->fb;
ret = plane->funcs->disable_plane(plane);
if (!ret) {
plane->crtc = NULL;
plane->fb = NULL;
+ plane->src = NULL;
} else {
plane->old_fb = NULL;
}
@@ -2524,22 +2562,50 @@ static int __setplane_internal(struct drm_plane *plane,
goto out;
}
- /* Check whether this plane supports the fb pixel format. */
- ret = drm_plane_check_pixel_format(plane, fb->pixel_format);
+ /* Check whether this plane supports the pixel format. */
+ pixel_format = fb ? fb->pixel_format : src->pixel_format;
+ ret = drm_plane_check_pixel_format(plane, pixel_format);
if (ret) {
DRM_DEBUG_KMS("Invalid pixel format %s\n",
- drm_get_format_name(fb->pixel_format));
+ drm_get_format_name(pixel_format));
goto out;
}
- fb_width = fb->width << 16;
- fb_height = fb->height << 16;
+ /* Check whether the source can be associated with the plane. */
+ if (src) {
+ struct drm_device *dev = plane->dev;
+ unsigned int plane_mask = 1;
+ struct drm_plane *p;
+
+ if (src->plane && src->plane != plane) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ list_for_each_entry(p, &dev->mode_config.plane_list, head) {
+ if (p == plane)
+ break;
+ plane_mask <<= 1;
+ }
+
+ if (!(src->possible_planes & plane_mask)) {
+ DRM_DEBUG_KMS("Invalid source for plane\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ }
+
+ /* Make sure source coordinates are inside the source. */
+ if (fb) {
+ width = fb->width << 16;
+ height = fb->height << 16;
+ } else {
+ width = src->width << 16;
+ height = src->height << 16;
+ }
- /* Make sure source coordinates are inside the fb. */
- if (src_w > fb_width ||
- src_x > fb_width - src_w ||
- src_h > fb_height ||
- src_y > fb_height - src_h) {
+ if (src_w > width || src_x > width - src_w ||
+ src_h > height || src_y > height - src_h) {
DRM_DEBUG_KMS("Invalid source coordinates "
"%u.%06ux%u.%06u+%u.%06u+%u.%06u\n",
src_w >> 16, ((src_w & 0xffff) * 15625) >> 10,
@@ -2551,12 +2617,24 @@ static int __setplane_internal(struct drm_plane *plane,
}
plane->old_fb = plane->fb;
- ret = plane->funcs->update_plane(plane, crtc, fb,
+ ret = plane->funcs->update_plane(plane, crtc, fb, src,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h);
if (!ret) {
+ mutex_lock(&file_priv->sources_lock);
+ if (src) {
+ list_add_tail(&src->filp_head, &file_priv->sources);
+ src->plane = plane;
+ }
+ if (plane->src) {
+ list_del(&plane->src->filp_head);
+ plane->src->plane = NULL;
+ }
+ mutex_unlock(&file_priv->sources_lock);
+
plane->crtc = crtc;
plane->fb = fb;
+ plane->src = src;
fb = NULL;
} else {
plane->old_fb = NULL;
@@ -2572,9 +2650,11 @@ out:
return ret;
}
-static int setplane_internal(struct drm_plane *plane,
+static int setplane_internal(struct drm_file *file_priv,
+ struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int32_t crtc_x, int32_t crtc_y,
uint32_t crtc_w, uint32_t crtc_h,
/* src_{x,y,w,h} values are 16.16 fixed point */
@@ -2584,7 +2664,7 @@ static int setplane_internal(struct drm_plane *plane,
int ret;
drm_modeset_lock_all(plane->dev);
- ret = __setplane_internal(plane, crtc, fb,
+ ret = __setplane_internal(file_priv, plane, crtc, fb, src,
crtc_x, crtc_y, crtc_w, crtc_h,
src_x, src_y, src_w, src_h);
drm_modeset_unlock_all(plane->dev);
@@ -2612,6 +2692,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
struct drm_plane *plane;
struct drm_crtc *crtc = NULL;
struct drm_framebuffer *fb = NULL;
+ struct drm_live_source *src = NULL;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
@@ -2628,8 +2709,8 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
}
/*
- * First, find the plane, crtc, and fb objects. If not available,
- * we don't bother to call the driver.
+ * First, find the plane, crtc, and fb or source objects. If not
+ * available, we don't bother to call the driver.
*/
plane = drm_plane_find(dev, plane_req->plane_id);
if (!plane) {
@@ -2641,7 +2722,16 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
if (plane_req->fb_id) {
fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
if (!fb) {
- DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
+ struct drm_mode_object *obj;
+
+ obj = drm_mode_object_find(dev, plane_req->fb_id,
+ DRM_MODE_OBJECT_LIVE_SOURCE);
+ if (obj)
+ src = obj_to_live_source(obj);
+ }
+
+ if (!fb && !src) {
+ DRM_DEBUG_KMS("Unknown framebuffer or live source ID %d\n",
plane_req->fb_id);
return -ENOENT;
}
@@ -2658,7 +2748,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
* setplane_internal will take care of deref'ing either the old or new
* framebuffer depending on success.
*/
- return setplane_internal(plane, crtc, fb,
+ return setplane_internal(file_priv, plane, crtc, fb, src,
plane_req->crtc_x, plane_req->crtc_y,
plane_req->crtc_w, plane_req->crtc_h,
plane_req->src_x, plane_req->src_y,
@@ -3199,7 +3289,7 @@ static int drm_mode_cursor_universal(struct drm_crtc *crtc,
* setplane_internal will take care of deref'ing either the old or new
* framebuffer depending on success.
*/
- ret = __setplane_internal(crtc->cursor, crtc, fb,
+ ret = __setplane_internal(file_priv, crtc->cursor, crtc, fb, NULL,
crtc_x, crtc_y, crtc_w, crtc_h,
0, 0, src_w, src_h);
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 076dd606b580..28591acf7e7a 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -167,6 +167,8 @@ static int drm_open_helper(struct file *filp, struct drm_minor *minor)
INIT_LIST_HEAD(&priv->lhead);
INIT_LIST_HEAD(&priv->fbs);
mutex_init(&priv->fbs_lock);
+ INIT_LIST_HEAD(&priv->sources);
+ mutex_init(&priv->sources_lock);
INIT_LIST_HEAD(&priv->event_list);
init_waitqueue_head(&priv->event_wait);
priv->event_space = 4096; /* set aside 4k for event buffer */
@@ -408,8 +410,10 @@ int drm_release(struct inode *inode, struct file *filp)
drm_events_release(file_priv);
- if (drm_core_check_feature(dev, DRIVER_MODESET))
+ if (drm_core_check_feature(dev, DRIVER_MODESET)) {
drm_fb_release(file_priv);
+ drm_live_sources_release(file_priv);
+ }
if (drm_core_check_feature(dev, DRIVER_GEM))
drm_gem_release(dev, file_priv);
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index b62b03635050..09bf8d9ba580 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -222,6 +222,7 @@ EXPORT_SYMBOL(drm_plane_helper_check_update);
*/
int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
struct drm_framebuffer *fb,
+ struct drm_live_source *lsrc,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 48ccab7fdf63..95ded0286eb9 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -127,7 +127,7 @@ static int exynos_drm_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
crtc_w = fb->width - x;
crtc_h = fb->height - y;
- return exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
+ return exynos_update_plane(crtc->primary, crtc, fb, NULL, 0, 0,
crtc_w, crtc_h, x, y, crtc_w, crtc_h);
}
@@ -201,7 +201,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
crtc->primary->fb = fb;
crtc_w = fb->width - crtc->x;
crtc_h = fb->height - crtc->y;
- ret = exynos_update_plane(crtc->primary, crtc, fb, 0, 0,
+ ret = exynos_update_plane(crtc->primary, crtc, fb, NULL, 0, 0,
crtc_w, crtc_h, crtc->x, crtc->y,
crtc_w, crtc_h);
if (ret) {
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.c b/drivers/gpu/drm/exynos/exynos_drm_plane.c
index a5616872eee7..693bfbf6b868 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.c
@@ -146,7 +146,8 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
int
exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
+ int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_plane.h b/drivers/gpu/drm/exynos/exynos_drm_plane.h
index 9d3c374e7b3e..bffb282c4860 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_plane.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_plane.h
@@ -16,7 +16,8 @@ void exynos_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h);
int exynos_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
+ int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 1aa1cbd16c19..3b72dc9a5676 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -11242,7 +11242,7 @@ static int __intel_set_mode(struct drm_crtc *crtc,
drm_crtc_get_hv_timing(mode, &hdisplay, &vdisplay);
ret = primary->funcs->update_plane(primary, &intel_crtc->base,
- fb, 0, 0,
+ fb, NULL, 0, 0,
hdisplay, vdisplay,
x << 16, y << 16,
hdisplay << 16, vdisplay << 16);
@@ -11717,7 +11717,7 @@ static int intel_crtc_set_config(struct drm_mode_set *set)
drm_crtc_get_hv_timing(set->mode, &hdisplay, &vdisplay);
ret = primary->funcs->update_plane(primary, set->crtc, set->fb,
- 0, 0, hdisplay, vdisplay,
+ NULL, 0, 0, hdisplay, vdisplay,
set->x << 16, set->y << 16,
hdisplay << 16, vdisplay << 16);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 7051da7015d3..be382d02ce14 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -1364,7 +1364,7 @@ int intel_plane_restore(struct drm_plane *plane)
if (!plane->crtc || !plane->fb)
return 0;
- return plane->funcs->update_plane(plane, plane->crtc, plane->fb,
+ return plane->funcs->update_plane(plane, plane->crtc, plane->fb, NULL,
plane->state->crtc_x, plane->state->crtc_y,
plane->state->crtc_w, plane->state->crtc_h,
plane->state->src_x, plane->state->src_y,
diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c
index 6987e16fe99b..a26d969fab0e 100644
--- a/drivers/gpu/drm/imx/ipuv3-plane.c
+++ b/drivers/gpu/drm/imx/ipuv3-plane.c
@@ -295,7 +295,8 @@ void ipu_plane_disable(struct ipu_plane *ipu_plane)
*/
static int ipu_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb,
+ struct drm_live_source *src, int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
diff --git a/drivers/gpu/drm/nouveau/dispnv04/overlay.c b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
index 9f2498571d09..485d1de72460 100644
--- a/drivers/gpu/drm/nouveau/dispnv04/overlay.c
+++ b/drivers/gpu/drm/nouveau/dispnv04/overlay.c
@@ -91,7 +91,8 @@ cos_mul(int degrees, int factor)
static int
nv10_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
+ int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
@@ -341,7 +342,8 @@ err:
static int
nv04_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
+ int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c
index ee8e2b3a117e..953707c8a795 100644
--- a/drivers/gpu/drm/omapdrm/omap_plane.c
+++ b/drivers/gpu/drm/omapdrm/omap_plane.c
@@ -238,6 +238,7 @@ int omap_plane_mode_set(struct drm_plane *plane,
static int omap_plane_update(struct drm_plane *plane,
struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 9a5c571b95fc..6c0767a03ad8 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -504,8 +504,9 @@ static int vop_win_queue_fb(struct vop_win *vop_win,
static int vop_update_plane_event(struct drm_plane *plane,
struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x,
- int crtc_y, unsigned int crtc_w,
+ struct drm_framebuffer *fb,
+ struct drm_live_source *src,
+ int crtc_x, int crtc_y, unsigned int crtc_w,
unsigned int crtc_h, uint32_t src_x,
uint32_t src_y, uint32_t src_w,
uint32_t src_h,
diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c
index 1805bb23b113..236613bcd571 100644
--- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c
+++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c
@@ -174,7 +174,8 @@ void shmob_drm_plane_setup(struct drm_plane *plane)
static int
shmob_drm_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
+ int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
diff --git a/drivers/gpu/drm/sti/sti_drm_plane.c b/drivers/gpu/drm/sti/sti_drm_plane.c
index bb6a29339e10..f43a4341e59c 100644
--- a/drivers/gpu/drm/sti/sti_drm_plane.c
+++ b/drivers/gpu/drm/sti/sti_drm_plane.c
@@ -24,7 +24,8 @@ enum sti_layer_desc sti_layer_default_zorder[] = {
static int
sti_drm_update_plane(struct drm_plane *plane, struct drm_crtc *crtc,
- struct drm_framebuffer *fb, int crtc_x, int crtc_y,
+ struct drm_framebuffer *fb, struct drm_live_source *src,
+ int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h)
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index b0eb62de1b2e..4ec096e62d9e 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -533,7 +533,7 @@ static int sti_hqvdp_prepare_layer(struct sti_layer *layer, bool first_prepare)
/* prepare and commit VID plane */
hqvdp->vid_plane->funcs->update_plane(hqvdp->vid_plane,
- layer->crtc, layer->fb,
+ layer->crtc, layer->fb, NULL,
layer->dst_x, layer->dst_y,
layer->dst_w, layer->dst_h,
layer->src_x, layer->src_y,
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 63c0b0131f61..6adcdb99482a 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -322,6 +322,9 @@ struct drm_file {
struct list_head fbs;
struct mutex fbs_lock;
+ struct list_head sources;
+ struct mutex sources_lock;
+
wait_queue_head_t event_wait;
struct list_head event_list;
int event_space;
diff --git a/include/drm/drm_atomic_helper.h b/include/drm/drm_atomic_helper.h
index 829280b56874..68b9bb68d015 100644
--- a/include/drm/drm_atomic_helper.h
+++ b/include/drm/drm_atomic_helper.h
@@ -62,6 +62,7 @@ void drm_atomic_helper_swap_state(struct drm_device *dev,
int drm_atomic_helper_update_plane(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 775a9a84c5bf..c66e23a60f75 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -759,6 +759,7 @@ struct drm_plane_state {
struct drm_crtc *crtc; /* do not write directly, use drm_atomic_set_crtc_for_plane() */
struct drm_framebuffer *fb; /* do not write directly, use drm_atomic_set_fb_for_plane() */
+ struct drm_live_source *src;
struct fence *fence;
/* Signed dest location allows it to be partially off screen */
@@ -793,6 +794,7 @@ struct drm_plane_state {
struct drm_plane_funcs {
int (*update_plane)(struct drm_plane *plane,
struct drm_crtc *crtc, struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
@@ -857,6 +859,7 @@ struct drm_plane {
struct drm_crtc *crtc;
struct drm_framebuffer *fb;
+ struct drm_live_source *src;
struct drm_framebuffer *old_fb;
@@ -878,6 +881,7 @@ struct drm_live_source_funcs {
struct drm_live_source {
struct drm_device *dev;
struct list_head head;
+ struct list_head filp_head;
struct drm_mode_object base;
@@ -1149,6 +1153,7 @@ struct drm_mode_config {
struct drm_property *prop_crtc_w;
struct drm_property *prop_crtc_h;
struct drm_property *prop_fb_id;
+ struct drm_property *prop_src_id;
struct drm_property *prop_crtc_id;
struct drm_property *prop_active;
@@ -1311,6 +1316,7 @@ extern int drm_live_source_init(struct drm_device *dev,
const uint32_t *formats, uint32_t format_count,
const struct drm_live_source_funcs *funcs);
extern void drm_live_source_cleanup(struct drm_live_source *src);
+extern void drm_live_sources_release(struct drm_file *priv);
extern const char *drm_get_connector_status_name(enum drm_connector_status status);
extern const char *drm_get_subpixel_order_name(enum subpixel_order order);
diff --git a/include/drm/drm_plane_helper.h b/include/drm/drm_plane_helper.h
index e48157a5a59c..441cd55e094c 100644
--- a/include/drm/drm_plane_helper.h
+++ b/include/drm/drm_plane_helper.h
@@ -93,6 +93,7 @@ extern int drm_plane_helper_check_update(struct drm_plane *plane,
extern int drm_primary_helper_update(struct drm_plane *plane,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
+ struct drm_live_source *src,
int crtc_x, int crtc_y,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
--
2.0.5
^ permalink raw reply related
* [RFC/PATCH 1/5] drm: Add live source object
From: Laurent Pinchart @ 2015-03-15 21:55 UTC (permalink / raw)
To: dri-devel
Cc: linux-media, linux-sh, linux-api, Daniel Vetter, Rob Clark,
Thierry Reding, Magnus Damm
In-Reply-To: <1426456540-21006-1-git-send-email-laurent.pinchart+renesas@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
drivers/gpu/drm/drm_crtc.c | 231 ++++++++++++++++++++++++++++++++++++++++++++
drivers/gpu/drm/drm_ioctl.c | 3 +
include/drm/drm_crtc.h | 42 ++++++++
include/uapi/drm/drm.h | 4 +
include/uapi/drm/drm_mode.h | 32 ++++++
5 files changed, 312 insertions(+)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 5785336695ca..a510c9742a16 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1261,6 +1261,60 @@ void drm_plane_cleanup(struct drm_plane *plane)
}
EXPORT_SYMBOL(drm_plane_cleanup);
+int drm_live_source_init(struct drm_device *dev, struct drm_live_source *src,
+ const char *name, unsigned long possible_planes,
+ const uint32_t *formats, uint32_t format_count,
+ const struct drm_live_source_funcs *funcs)
+{
+ int ret;
+
+ drm_modeset_lock_all(dev);
+
+ ret = drm_mode_object_get(dev, &src->base, DRM_MODE_OBJECT_LIVE_SOURCE);
+ if (ret)
+ goto out;
+
+ src->dev = dev;
+ src->funcs = funcs;
+ if (name)
+ strlcpy(src->name, name, DRM_SOURCE_NAME_LEN);
+ src->possible_planes = possible_planes;
+
+ src->format_types = kmalloc(format_count * sizeof(*src->format_types),
+ GFP_KERNEL);
+ if (!src->format_types) {
+ DRM_DEBUG_KMS("out of memory when allocating source foramts\n");
+ drm_mode_object_put(dev, &src->base);
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ memcpy(src->format_types, formats,
+ format_count * sizeof(*src->format_types));
+ src->format_count = format_count;
+
+ list_add_tail(&src->head, &dev->mode_config.live_source_list);
+ dev->mode_config.num_live_source++;
+
+ out:
+ drm_modeset_unlock_all(dev);
+
+ return ret;
+}
+EXPORT_SYMBOL(drm_live_source_init);
+
+void drm_live_source_cleanup(struct drm_live_source *src)
+{
+ struct drm_device *dev = src->dev;
+
+ drm_modeset_lock_all(dev);
+ drm_mode_object_put(dev, &src->base);
+ list_del(&src->head);
+ dev->mode_config.num_live_source--;
+ drm_modeset_unlock_all(dev);
+}
+EXPORT_SYMBOL(drm_live_source_cleanup);
+
/**
* drm_plane_index - find the index of a registered plane
* @plane: plane to find index for
@@ -2612,6 +2666,176 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
}
/**
+ * drm_mode_getsource_res - get live source info
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * Return a live source and set of IDs.
+ */
+int drm_mode_getsource_res(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_mode_get_live_source_res *src_resp = data;
+ struct drm_mode_config *config;
+ struct drm_live_source *src;
+ uint32_t __user *src_ptr;
+ int copied = 0, ret = 0;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return -EINVAL;
+
+ drm_modeset_lock_all(dev);
+ config = &dev->mode_config;
+
+ /*
+ * This ioctl is called twice, once to determine how much space is
+ * needed, and the 2nd time to fill it.
+ */
+ if (config->num_live_source &&
+ (src_resp->count_sources >= config->num_live_source)) {
+ src_ptr = (uint32_t __user *)(unsigned long)src_resp->source_id_ptr;
+
+ list_for_each_entry(src, &config->live_source_list, head) {
+ if (put_user(src->base.id, src_ptr + copied)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ copied++;
+ }
+ }
+ src_resp->count_sources = config->num_live_source;
+
+out:
+ drm_modeset_unlock_all(dev);
+ return ret;
+}
+
+/**
+ * drm_mode_getsource - get live source info
+ * @dev: DRM device
+ * @data: ioctl data
+ * @file_priv: DRM file info
+ *
+ * Return live source info, including formats supported, ...
+ */
+int drm_mode_getsource(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_mode_get_live_source *src_resp = data;
+ struct drm_mode_object *obj;
+ struct drm_live_source *src;
+ int ret = 0;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return -EINVAL;
+
+ obj = drm_mode_object_find(dev, src_resp->source_id,
+ DRM_MODE_OBJECT_LIVE_SOURCE);
+ if (!obj)
+ return -ENOENT;
+ src = obj_to_live_source(obj);
+
+ src_resp->source_id = src->base.id;
+ strlcpy(src_resp->name, src->name, DRM_SOURCE_NAME_LEN);
+ src_resp->possible_planes = src->possible_planes;
+
+ drm_modeset_lock_all(dev);
+
+ if (src->plane)
+ src_resp->plane_id = src->plane->base.id;
+ else
+ src_resp->plane_id = 0;
+
+ src_resp->width = src->width;
+ src_resp->height = src->height;
+ src_resp->pixel_format = src->pixel_format;
+
+ /*
+ * This ioctl is called twice, once to determine how much space is
+ * needed, and the 2nd time to fill it.
+ */
+ if (src->format_count &&
+ (src_resp->count_format_types >= src->format_count)) {
+ uint32_t __user *format_ptr;
+
+ format_ptr = (uint32_t __user *)(unsigned long)src_resp->format_type_ptr;
+ if (copy_to_user(format_ptr, src->format_types,
+ sizeof(uint32_t) * src->format_count)) {
+ ret = -EFAULT;
+ goto out;
+ }
+ }
+ src_resp->count_format_types = src->format_count;
+
+out:
+ drm_modeset_unlock_all(dev);
+ return ret;
+}
+
+/**
+ * drm_mode_setsource - set up or tear down a live source
+ * @dev: DRM device
+ * @data: ioctl data*
+ * @file_priv: DRM file info
+ *
+ * Set live source info, including plane, and other factors.
+ * Or pass a NULL plane to disable.
+ */
+int drm_mode_setsource(struct drm_device *dev, void *data,
+ struct drm_file *file_priv)
+{
+ struct drm_mode_set_live_source *src_req = data;
+ struct drm_mode_object *obj;
+ struct drm_live_source *src;
+ unsigned int i;
+ int ret = 0;
+
+ if (!drm_core_check_feature(dev, DRIVER_MODESET))
+ return -EINVAL;
+
+ /*
+ * First, find the live source and plane objects. If not available, we
+ * don't bother to call the driver.
+ */
+ obj = drm_mode_object_find(dev, src_req->source_id,
+ DRM_MODE_OBJECT_LIVE_SOURCE);
+ if (!obj) {
+ DRM_DEBUG_KMS("Unknown live source ID %d\n",
+ src_req->source_id);
+ return -ENOENT;
+ }
+ src = obj_to_live_source(obj);
+
+ drm_modeset_lock_all(dev);
+
+ if (src->plane) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* Check whether this source supports the pixel format. */
+ for (i = 0; i < src->format_count; i++)
+ if (src_req->pixel_format == src->format_types[i])
+ break;
+
+ if (i == src->format_count) {
+ DRM_DEBUG_KMS("Invalid pixel format 0x%08x for source %u\n",
+ src_req->pixel_format, src->base.id);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ src->width = src_req->width;
+ src->height = src_req->height;
+ src->pixel_format = src_req->pixel_format;
+
+out:
+ drm_modeset_unlock_all(dev);
+ return ret;
+}
+
+/**
* drm_mode_set_config_internal - helper to call ->set_config
* @set: modeset config to set
*
@@ -5429,6 +5653,7 @@ void drm_mode_config_init(struct drm_device *dev)
INIT_LIST_HEAD(&dev->mode_config.property_list);
INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
INIT_LIST_HEAD(&dev->mode_config.plane_list);
+ INIT_LIST_HEAD(&dev->mode_config.live_source_list);
idr_init(&dev->mode_config.crtc_idr);
idr_init(&dev->mode_config.tile_idr);
@@ -5468,6 +5693,7 @@ void drm_mode_config_cleanup(struct drm_device *dev)
struct drm_property *property, *pt;
struct drm_property_blob *blob, *bt;
struct drm_plane *plane, *plt;
+ struct drm_live_source *src, *psrc;
list_for_each_entry_safe(encoder, enct, &dev->mode_config.encoder_list,
head) {
@@ -5507,6 +5733,11 @@ void drm_mode_config_cleanup(struct drm_device *dev)
plane->funcs->destroy(plane);
}
+ list_for_each_entry_safe(src, psrc, &dev->mode_config.live_source_list,
+ head) {
+ src->funcs->destroy(src);
+ }
+
list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) {
crtc->funcs->destroy(crtc);
}
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index a6d773a61c2d..2cb400a8bc8d 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -609,10 +609,13 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETSOURCERESOURCES, drm_mode_getsource_res, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETSOURCE, drm_mode_getsource, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETSOURCE, drm_mode_setsource, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index adc9ea5acf02..775a9a84c5bf 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -54,6 +54,7 @@ struct fence;
#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb
#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee
#define DRM_MODE_OBJECT_BRIDGE 0xbdbdbdbd
+#define DRM_MODE_OBJECT_LIVE_SOURCE 0xe1e1e1e1
#define DRM_MODE_OBJECT_ANY 0
struct drm_mode_object {
@@ -247,6 +248,7 @@ struct drm_pending_vblank_event;
struct drm_plane;
struct drm_bridge;
struct drm_atomic_state;
+struct drm_live_source;
/**
* struct drm_crtc_state - mutable CRTC state
@@ -869,6 +871,30 @@ struct drm_plane {
struct drm_plane_state *state;
};
+struct drm_live_source_funcs {
+ void (*destroy)(struct drm_live_source *src);
+};
+
+struct drm_live_source {
+ struct drm_device *dev;
+ struct list_head head;
+
+ struct drm_mode_object base;
+
+ char name[DRM_SOURCE_NAME_LEN];
+
+ uint32_t possible_planes;
+ uint32_t *format_types;
+ uint32_t format_count;
+
+ struct drm_plane *plane;
+ unsigned int width;
+ unsigned int height;
+ uint32_t pixel_format;
+
+ const struct drm_live_source_funcs *funcs;
+};
+
/**
* struct drm_bridge_funcs - drm_bridge control functions
* @attach: Called during drm_bridge_attach
@@ -1087,6 +1113,8 @@ struct drm_mode_config {
int num_overlay_plane;
int num_total_plane;
struct list_head plane_list;
+ int num_live_source;
+ struct list_head live_source_list;
int num_crtc;
struct list_head crtc_list;
@@ -1186,6 +1214,7 @@ struct drm_mode_config {
#define obj_to_property(x) container_of(x, struct drm_property, base)
#define obj_to_blob(x) container_of(x, struct drm_property_blob, base)
#define obj_to_plane(x) container_of(x, struct drm_plane, base)
+#define obj_to_live_source(x) container_of(x, struct drm_live_source, base)
struct drm_prop_enum_list {
int type;
@@ -1276,6 +1305,13 @@ extern int drm_crtc_check_viewport(const struct drm_crtc *crtc,
extern void drm_encoder_cleanup(struct drm_encoder *encoder);
+extern int drm_live_source_init(struct drm_device *dev,
+ struct drm_live_source *src, const char *name,
+ unsigned long possible_planes,
+ const uint32_t *formats, uint32_t format_count,
+ const struct drm_live_source_funcs *funcs);
+extern void drm_live_source_cleanup(struct drm_live_source *src);
+
extern const char *drm_get_connector_status_name(enum drm_connector_status status);
extern const char *drm_get_subpixel_order_name(enum subpixel_order order);
extern const char *drm_get_dpms_name(int val);
@@ -1391,6 +1427,8 @@ extern int drm_mode_getresources(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_getplane_res(struct drm_device *dev, void *data,
struct drm_file *file_priv);
+extern int drm_mode_getsource_res(struct drm_device *dev, void *data,
+ struct drm_file *file_priv);
extern int drm_mode_getcrtc(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_getconnector(struct drm_device *dev,
@@ -1402,6 +1440,10 @@ extern int drm_mode_getplane(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_setplane(struct drm_device *dev,
void *data, struct drm_file *file_priv);
+extern int drm_mode_getsource(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
+extern int drm_mode_setsource(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
extern int drm_mode_cursor_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
extern int drm_mode_cursor2_ioctl(struct drm_device *dev,
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index ff6ef62d084b..d60cb8fa034c 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -787,6 +787,10 @@ struct drm_prime_handle {
#define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2)
#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic)
+#define DRM_IOCTL_MODE_GETSOURCERESOURCES DRM_IOWR(0xBC, struct drm_mode_get_live_source_res)
+#define DRM_IOCTL_MODE_GETSOURCE DRM_IOWR(0xBD, struct drm_mode_get_live_source)
+#define DRM_IOCTL_MODE_SETSOURCE DRM_IOWR(0xBE, struct drm_mode_set_live_source)
+
/**
* Device specific ioctls should only be in their respective headers
* The device specific ioctl range is from 0x40 to 0x9f.
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index dbeba949462a..ecc1fa3000f4 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -33,6 +33,7 @@
#define DRM_CONNECTOR_NAME_LEN 32
#define DRM_DISPLAY_MODE_LEN 32
#define DRM_PROP_NAME_LEN 32
+#define DRM_SOURCE_NAME_LEN 32
#define DRM_MODE_TYPE_BUILTIN (1<<0)
#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN)
@@ -179,6 +180,37 @@ struct drm_mode_get_plane_res {
__u32 count_planes;
};
+struct drm_mode_set_live_source {
+ __u32 source_id;
+
+ __u32 plane_id;
+
+ __u32 width;
+ __u32 height;
+ __u32 pixel_format;
+};
+
+struct drm_mode_get_live_source {
+ __u32 source_id;
+ char name[DRM_SOURCE_NAME_LEN];
+
+ __u32 plane_id;
+
+ __u32 possible_planes;
+
+ __u32 count_format_types;
+ __u64 format_type_ptr;
+
+ __u32 width;
+ __u32 height;
+ __u32 pixel_format;
+};
+
+struct drm_mode_get_live_source_res {
+ __u64 source_id_ptr;
+ __u32 count_sources;
+};
+
#define DRM_MODE_ENCODER_NONE 0
#define DRM_MODE_ENCODER_DAC 1
#define DRM_MODE_ENCODER_TMDS 2
--
2.0.5
^ permalink raw reply related
* [RFC/PATCH 0/5] Add live source objects to DRM
From: Laurent Pinchart @ 2015-03-15 21:55 UTC (permalink / raw)
To: dri-devel-PD4FTy7X32lNgt0PjOBp9y5qC8QIuHrW
Cc: linux-media-u79uwXL29TY76Z2rM5mHXA,
linux-sh-u79uwXL29TY76Z2rM5mHXA, linux-api-u79uwXL29TY76Z2rM5mHXA,
Daniel Vetter, Rob Clark, Thierry Reding, Magnus Damm
Hello,
I have a feeling that RFC/PATCH will work better than just RFC, so here's a
patch set that adds a new object named live source to DRM.
The need comes from the Renesas R-Car SoCs in which a video processing engine
(named VSP1) that operates from memory to memory has one output directly
connected to a plane of the display engine (DU) without going through memory.
The VSP1 is supported by a V4L2 driver. While it could be argued that it
should instead be supported directly by the DRM rcar-du driver, this wouldn't
be a good idea for at least two reasons. First, the R-Car SoCs contain several
VSP1 instances, of which only a subset have a direct DU connection. The only
other instances operate solely in memory to memory mode. Then, the VSP1 is a
video processing engine and not a display engine. Its features are easily
supported by the V4L2 API, but don't map to the DRM/KMS API. Significant
changes to DRM/KMS would be required, beyond what is in my opinion an
acceptable scope for a display API.
Now that the need to interface two separate devices supported by two different
drivers in two separate subsystems has been established, we need an API to do
so. It should be noted that while that API doesn't exist in the mainline
kernel, the need isn't limited to Renesas SoCs.
This patch set proposes one possible solution for the problem in the form of a
new DRM object named live source. Live sources are created by drivers to model
hardware connections between a plane input and an external source, and are
attached to planes through the KMS userspace API.
Patch 1/5 adds live source objects to DRM, with an in-kernel API for drivers
to register the sources, and a userspace API to enumerate and configure them.
Configuring a live source sets the width, height and pixel format of the
video stream. This should ideally be queried directly from the driver that
supports the live source device, but I've decided not to implement such
communication between V4L2 and DRM/KMS at the moment to keep the proposal
simple.
Patch 2/2 implements connection between live sources and planes. This takes
different forms depending on whether drivers use the setplane or the atomic
updates API:
- For setplane, the fb field can now contain a live source ID in addition to
a framebuffer ID. As DRM allocates object IDs from a single ID space, the
type can be inferred from the ID. This makes specifying both a framebuffer
and a live source impossible, which isn't an issue given that such a
configuration would be invalid.
The live source is looked up by the DRM core and passed as a pointer to the
.update_plane() operation. Unlike framebuffers live sources are not
refcounted as they're created statically at driver initialization time.
- For atomic update, a new SRC_ID property has been added to planes. The live
source is looked up from the source ID and stored into the plane state.
Patches 3/5 to 5/5 then implement support for live sources in the R-Car DU
driver.
Nothing here is set in stone. One point I'm not sure about is whether live
sources support should be enabled for setplane or only for atomic updates.
Other parts of the API can certainly be modified as well, and I'm open for
totally different implementations as well.
Laurent Pinchart (5):
drm: Add live source object
drm: Connect live source to plane
drm/rcar-du: Add VSP1 support to the planes allocator
drm/rcar-du: Add VSP1 live source support
drm/rcar-du: Restart the DU group when a plane source changes
drivers/gpu/drm/armada/armada_overlay.c | 2 +-
drivers/gpu/drm/drm_atomic.c | 7 +
drivers/gpu/drm/drm_atomic_helper.c | 4 +
drivers/gpu/drm/drm_crtc.c | 365 ++++++++++++++++++++++++++--
drivers/gpu/drm/drm_fops.c | 6 +-
drivers/gpu/drm/drm_ioctl.c | 3 +
drivers/gpu/drm/drm_plane_helper.c | 1 +
drivers/gpu/drm/exynos/exynos_drm_crtc.c | 4 +-
drivers/gpu/drm/exynos/exynos_drm_plane.c | 3 +-
drivers/gpu/drm/exynos/exynos_drm_plane.h | 3 +-
drivers/gpu/drm/i915/intel_display.c | 4 +-
drivers/gpu/drm/i915/intel_sprite.c | 2 +-
drivers/gpu/drm/imx/ipuv3-plane.c | 3 +-
drivers/gpu/drm/nouveau/dispnv04/overlay.c | 6 +-
drivers/gpu/drm/omapdrm/omap_plane.c | 1 +
drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 10 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.c | 6 +-
drivers/gpu/drm/rcar-du/rcar_du_drv.h | 3 +
drivers/gpu/drm/rcar-du/rcar_du_group.c | 21 +-
drivers/gpu/drm/rcar-du/rcar_du_group.h | 2 +
drivers/gpu/drm/rcar-du/rcar_du_kms.c | 62 ++++-
drivers/gpu/drm/rcar-du/rcar_du_plane.c | 196 ++++++++++++---
drivers/gpu/drm/rcar-du/rcar_du_plane.h | 11 +
drivers/gpu/drm/rcar-du/rcar_du_regs.h | 1 +
drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 5 +-
drivers/gpu/drm/shmobile/shmob_drm_plane.c | 3 +-
drivers/gpu/drm/sti/sti_drm_plane.c | 3 +-
drivers/gpu/drm/sti/sti_hqvdp.c | 2 +-
include/drm/drmP.h | 3 +
include/drm/drm_atomic_helper.h | 1 +
include/drm/drm_crtc.h | 48 ++++
include/drm/drm_plane_helper.h | 1 +
include/uapi/drm/drm.h | 4 +
include/uapi/drm/drm_mode.h | 32 +++
34 files changed, 728 insertions(+), 100 deletions(-)
--
Regards,
Laurent Pinchart
^ permalink raw reply
* Re: [PATCH v2 5/7] clone4: Add a CLONE_AUTOREAP flag to automatically reap the child process
From: Oleg Nesterov @ 2015-03-15 19:55 UTC (permalink / raw)
To: Josh Triplett
Cc: Al Viro, Andrew Morton, Andy Lutomirski, Ingo Molnar, Kees Cook,
Paul E. McKenney, H. Peter Anvin, Rik van Riel, Thomas Gleixner,
Michael Kerrisk, Thiago Macieira,
linux-kernel-u79uwXL29TY76Z2rM5mHXA,
linux-api-u79uwXL29TY76Z2rM5mHXA,
linux-fsdevel-u79uwXL29TY76Z2rM5mHXA, x86-DgEjT+Ai2ygdnm+yROfE0A
In-Reply-To: <20150315171855.GA30620@thin>
On 03/15, Josh Triplett wrote:
>
> On Sun, Mar 15, 2015 at 03:52:23PM +0100, Oleg Nesterov wrote:
> > On 03/15, Josh Triplett wrote:
> > > Add a CLONE_AUTOREAP flag to request this behavior unconditionally,
> >
> > Yes, CLONE_AUTOREAP is much better. And I agree (mostly) with that
> > we should rely on do_notify_parent().
> >
> > Howver the patch still doesn't look right. First of all, ->autoreap
> > should be per-process, not per-thread.
>
> Ah, you're thinking of the case where the parent process launches a
> ...
Not really, although we probably need more sanity checks.
It should be per-process simply because this "autoreap" affects the whole
process. And the sub-threads are already "autoreap". And these 2 autoreap's
semantics differ, we should not confuse them.
> (As an aside, what *is* the use case for CLONE_PARENT without
> CLONE_THREAD?)
To me CLONE_PARENT is another historical mistake and the source of misc
problems ;)
> > And there are ptrace/mt issues,
> > it seems. Just for example, we should avoid EXIT_TRACE if autoreap in
> > wait_task_zombie() even if we are going to re-notify parent.
>
> I don't see how EXIT_TRACE can happen in wait_task_zombie if autoreap is
> set. wait_task_zombie does a cmpxchg with exit_state and doesn't
> proceed unless exit_state was EXIT_ZOMBIE, and I don't see how we can
> ever reach the EXIT_ZOMBIE state if autoreap.
Because you again forgot about ptrace ;)
Josh. Let me try to summarise this later when I have time. Again, I am
not sure, perhaps this is even simpler than I currently think. And let
me apologize in advance, most probably I will be busy tomorrow.
> > EXCEPT: do we really want SIGCHLD from the exiting child? I think we
> > do not. I won't really argue though, but this should be discussed and
> > documented. IIUC, with your patch it is still sent.
>
> I think we do, yes. The caller of clone can already specify what signal
> they want, including no signal at all. If they specify a signal
> (SIGCHLD or otherwise) along with CLONE_AUTOREAP, we can send that
> signal.
OK. Agreed.
Oleg.
^ permalink raw reply
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