Linux userland API discussions
 help / color / mirror / Atom feed
* 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

* Re: [PATCH -next v2 0/4] mm: replace mmap_sem for mm->exe_file serialization
From: Davidlohr Bueso @ 2015-03-15 17:34 UTC (permalink / raw)
  To: Cyrill Gorcunov
  Cc: Oleg Nesterov, akpm-de/tnXTf+JLsfHDXvbKv3WD2FQJk+8+b,
	viro-RmSDqhL/yNMiFSDQTTA3OLVCufUGDwFn,
	koct9i-Re5JQEeQqe8AvxtiuMwx3w, linux-mm-Bw31MaZKKs3YtjvyW6yDsg,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Kees Cook,
	Michael Kerrisk (man-pages), Linux API
In-Reply-To: <20150315170521.GA2278@moon>

On Sun, 2015-03-15 at 20:05 +0300, Cyrill Gorcunov wrote:
> On Sun, Mar 15, 2015 at 08:42:05AM -0700, Davidlohr Bueso wrote:
> > > > > Yes, this code needs cleanups, I agree. Does this series makes it better?
> > > > > To me it doesn't, and the diffstat below shows that it blows the code.
> > > >
> > > > Looking at some of the caller paths now, I have to disagree.
> > > 
> > > And I believe you are wrong. But let me repeat, I leave this to Cyrill
> > > and Konstantin. Cleanups are always subjective.
> > > 
> > > > > In fact, to me it complicates this code. For example. Personally I think
> > > > > that MMF_EXE_FILE_CHANGED should die. And currently we can just remove it.
> > > >
> > > > How could you remove this?
> > > 
> > > Just remove this flag and the test_and_set_bit(MMF_EXE_FILE_CHANGED) check.
> > > Again, this is subjective, but to me it looks ugly. Why do we allow to
> > > change ->exe_file but only once?
> 
> This came from very first versions of the functionality implemented
> in prctl. It supposed to help sysadmins to notice if there exe
> transition happened. As to me it doesn't bring much security, if I
> would be a virus I would simply replace executing code with ptrace
> or via other ways without telling outside world that i've changed
> exe path. That said I would happily rip off this MMF_EXE_FILE_CHANGED
> bit but I fear security guys won't be that happy about it.
> (CC'ing Kees)

Also adding Michael for any prctl manpage and api changes.

^ 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 17:18 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: <20150315145223.GA21887-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>

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
child with CLONE_AUTOREAP, that child process launches siblings with
CLONE_THREAD and without CLONE_AUTOREAP, and one of those siblings is
the last to exit?  That seems easy enough to handle: instead of setting
->autoreap unconditionally in copy_process, I can set it only in the
non-CLONE_THREAD case, and otherwise let it inherit.  Then every task in
the group will have the same value for autoreap.

(As an aside, what *is* the use case for CLONE_PARENT without
CLONE_THREAD?)

> 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.

> 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.  I don't think that causes any particular problem.

That's the same semantic you'd get if you have a SIGCHLD handler with
SA_NOCLDWAIT: you'd still get the signal, even though you don't need to
(and can't) wait on the child process.

> Josh, please give me some time to think and re-check, I'll write another
> email next week. I am not sure this is really needed, but it seems to
> me that we need the preparation patch to make this change clear/simple.

I'd appreciate any feedback you can offer on this series, including any
potential subtle interactions with ptrace.

- Josh Triplett

^ 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 14:52 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: <6d002995485d446e659105f6931307f3e532ce89.1426376419.git.josh-iaAMLnmF4UmaiuxdJuQwMA@public.gmane.org>

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. 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.

Yes... and other problems with ptrace. So let me nack this patch for
the moment ;) But let me repeat that personally I agree with this
change "in general".

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.

Josh, please give me some time to think and re-check, I'll write another
email next week. I am not sure this is really needed, but it seems to
me that we need the preparation patch to make this change clear/simple.

Oleg.

^ permalink raw reply

* Re: [PATCH 0/6] CLONE_FD: Task exit notification via file descriptor
From: Josh Triplett @ 2015-03-15 10:59 UTC (permalink / raw)
  To: David Drysdale
  Cc: Thiago Macieira, Andy Lutomirski, Al Viro, Andrew Morton,
	Ingo Molnar, Kees Cook, Oleg Nesterov, Paul E. McKenney,
	H. Peter Anvin, Rik van Riel, Thomas Gleixner, Michael Kerrisk,
	linux-kernel@vger.kernel.org, Linux API, Linux FS Devel, X86 ML
In-Reply-To: <CAHse=S9OLvyXCpbNSzA-qxYOm8VscFkKV0d2oyexM9gUjomN3g@mail.gmail.com>

On Sun, Mar 15, 2015 at 10:18:05AM +0000, David Drysdale wrote:
> On Sat, Mar 14, 2015 at 7:29 PM, Josh Triplett <josh@joshtriplett.org> wrote:
> > On Sat, Mar 14, 2015 at 12:03:12PM -0700, Thiago Macieira wrote:
> >> On Friday 13 March 2015 18:11:32 Thiago Macieira wrote:
> >> > On Friday 13 March 2015 14:51:47 Andy Lutomirski wrote:
> >> > > In any event, we should find out what FreeBSD does in response to
> >> > > read(2) on the fd.
> >> >
> >> > I've just successfully installed FreeBSD and compiled qtbase (main package
> >> > of Qt 5) on it.
> >> >
> >> > I'll test pdfork during the weekend and report its behaviour.
> >>
> >> Here are my findings about pdfork.
> >>
> >> Source: http://fxr.watson.org/fxr/source/kern/sys_procdesc.c?v=FREEBSD10
> >> Qt adaptations: https://codereview.qt-project.org/108561
> >>
> >> Processes created with pdfork() are normal processes that still send SIGCHLD
> >> to their parents. The only difference is that you get the extra file descriptor
> >> that can be passed to the pdgetpid() system call and works on select()/poll().
> >> Trying to read from that file descriptor will result in EOPNOTSUPP.
> >
> > OK, since read() doesn't work on a pdfork() file descriptor, we don't
> > have to worry about compatibility with pdfork()'s read result.
> >
> > However, if the expectation is that pdfork()ed child processes still
> > send SIGCHLD, then I don't see how we can be compatible there, nor do I
> > think we want to; as you mention below, that breaks the ability to
> > encapsulate management of the created process entirely within a library.
> 
> I didn't think that was the case -- my understanding was that pdfork()ed
> children would not generate SIGCHLD (and that does seem to be the
> case with a quick test program).

Well, either way, v2 of this series is capable of producing either
behavior.  You can have a clonefd and still receive SIGCHLD or any other
signal, or none at all, and you can decide independently from that if
you want autoreaping or waiting.

> As an aside, I do think there are some aspects of FreeBSD's process
> descriptors that aren't quite right yet, particularly their interaction with
> waitpid(-1, ...) -- IIRC pdfork()ed children are visible to it, but I'd expect
> them not to be (to allow libraries to use sub-processes invisibly to the
> programs using them). There's a thread at:
> https://lists.cam.ac.uk/pipermail/cl-capsicum-discuss/2014-March/thread.html
> but I'm not sure that anything came of that discussion.

As long as you don't use the Linux-specific flags __WALL or __WCLONE, a
process created with clone will be invisible to wait if it has an exit
signal other than SIGCHLD.  That's true independent of this patch
series.  So you can decide if you want processes visible to wait or not.

> As it happens, I'm meeting Robert Watson (one of the progenitors
> of Capsicum/process descriptors) tomorrow, so I'll chase further.

Sounds good.

> >> Since they've never implemented pdwait4() (it's not even declared in the
> >> headers), the only way to reap a child if you only have the file descriptor is
> >> to first pdgetpid() and then call wait4() or wait6().
> >
> > Which suggests that we shouldn't try to implement pdwait4() in glibc
> > until FreeBSD implements it in their kernel, since we won't know the
> > exact semantics they expect.
> 
> By the way, I should point out one part of the FreeBSD design
> which might help explain some of the semantics.
> 
> Process descriptors are particularly designed to be used with
> Capsicum, which is a security framework where file descriptors
> get extra rights associated with them, and the kernel polices
> the use of those rights (e.g. you need CAP_READ for read(2)
> operations; normal file descriptors implicitly have all of the
> rights for back-compatibility).
>   https://www.freebsd.org/cgi/man.cgi?query=capsicum&sektion=4
> 
> Capsicum also includes 'capability mode', where system calls
> that access global namespaces are disabled -- including the
> pid namespace.
> 
> So process descriptors are the only way to manipulate child
> processes when a program is in capability mode -- and this
> means that pdkill() is then genuinely needed over and above
> kill(pdgetpid(),...).

Thanks for the explanation.  I've seen some details about Capsicum, and
I found it quite interesting.  I'm particularly interested in the notion
of getting rid of global namespaces in favor of descriptors or similar
mechanisms that you need specific rights to.

Does Capsicum do anything to eliminate the global namespace of UIDs and
GIDs?

> >> If you don't pass PD_DAEMON, the child process gets killed with SIGKILL when
> >> the file closes.
> >
> > OK, that makes sense.  We could certainly implement a
> > CLONE_FD_KILL_ON_CLOSE flag with those semantics, if we want one in the
> > future.
> >
> >> Conclusion:
> >> Pros: this is the bare minimum that we'd need to disentangle the SIGCHLD mess.
> >> As long as all child process activations use this feature, the problem is
> >> solved.
> >>
> >> Cons: it requires cooperation from all child starters. If some other library
> >> or the application installs a global SIGCHLD handler that waits on all child
> >> processes, like libvlc used to do and Glib and Ecore still do, you won't be
> >> able to get the child exit status.
> >>
> >> I have not tested what happens if you try to pass the file descriptor to other
> >> processes (can you even do that on FreeBSD?). But even if you could and got
> >> notifications, you couldn't wait on the child to get its exit status -- unless
> >> they implement pdwait4.
> >
> > Even if they do implement pdwait4, they might not bypass the "must be
> > the parent process" restriction.  Let's wait to see what semantics they
> > go with.
> 
> Hmm, interesting point.  FreeBSD certainly allows FD passing, but
> I'm not sure what the interactions are when it's a process descriptor
> that's passed.
> 
> Given the object-capability background to Capsicum, I'd assume that a
> holder of the process descriptor should be able to do whatever operations
> are allowed by the rights associated with the descriptor (CAP_PDGETPID,
> CAP_PDKILL and CAP_PDWAIT exist as specific rights allowing those
> operations, and a non-restricted descriptor will have all of them by default).

Possibly, but given that pdwait4 isn't actually implemented yet, it
wouldn't surprise me if the future implementation looks up the process
and then calls the same internal function that wait4 does, with the same
"must be the parent process" restriction.

> But I'll add some test cases for this to the Capsicum test suite to check
> whether theory matches practice...
>   https://github.com/google/capsicum-test/blob/dev/procdesc.cc

Excellent; that seems like a good way to make sure the current and
future behavior matches expectations.

- Josh Triplett

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox