* [v4.14-rc3 bug] scheduling while atomic in generic/451 test on extN
From: Eryu Guan @ 2017-10-05 6:07 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, lczerner
Hi all,
I hit "scheduling while atomic" bug by running fstests generic/451 on
extN filesystems in v4.14-rc3 testing, but it didn't reproduce for me on
every host I tried, but I've seen it multiple times on multiple hosts. A
test vm of mine with 4 vcpus and 8G memory reproduced the bug reliably,
while a bare metal host with 8 cpus and 8G mem couldn't.
This is due to commit 332391a9935d ("fs: Fix page cache inconsistency
when mixing buffered and AIO DIO"), which defers AIO DIO io completion
to a workqueue if the inode has mapped pages and does page cache
invalidation in process context. I think that the problem is that the
pages can be mapped after the dio->inode->i_mapping->nrpages check, so
we're doing page cache invalidation, which could sleep, in interrupt
context, thus "scheduling while atomic" bug happens.
Defering all AIO DIO completion to workqueue unconditionally (as what
the iomap based path does) fixed the problem for me. But there're
performance concerns to do so in the original discussions.
https://www.spinics.net/lists/linux-fsdevel/msg112669.html
Thanks,
Eryu
[17087.868644] BUG: scheduling while atomic: swapper/0/0/0x00000100
[17087.875363] Modules linked in: dm_thin_pool dm_persistent_data dm_bio_prison dm_snapshot dm_bufio loop dm_flakey dm_mod ses enclosure ext4 mbcache jbd2 intel_rapl sb_edac x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul mpt3sas ghash_clmulni_intel raid_class sg scsi_transport_sas pcbc ipmi_ssif shpchp aesni_intel crypto_simd iTCO_wdt glue_helper ipmi_si cryptd iTCO_vendor_support cdc_ether ipmi_devintf ipmi_msghandler usbnet mii pcspkr acpi_pad wmi dcdbas joydev acpi_power_meter lpc_ich mei_me mei nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables xfs libcrc32c mgag200 drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops sd_mod igb ttm ahci ptp libahci drm libata pps_core crc32c_intel dca megaraid_sas i2c_algo_bit i2c_core [
last unloaded: scsi_debug]
[17087.955757] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 4.14.0-rc3 #1
[17087.964110] Hardware name: Dell Inc. PowerEdge R620/01W23F, BIOS 2.5.4 01/22/2016
[17087.972460] Call Trace:
[17087.975189] <IRQ>
[17087.977441] dump_stack+0x63/0x89
[17087.981143] __schedule_bug+0x62/0x70
[17087.985232] __schedule+0x7bb/0x890
[17087.989125] schedule+0x36/0x80
[17087.992629] io_schedule+0x16/0x40
[17087.996429] __lock_page+0x10a/0x150
[17088.000420] ? page_cache_tree_insert+0xb0/0xb0
[17088.005470] invalidate_inode_pages2_range+0x240/0x500
[17088.011208] ? kmem_cache_free+0x1ad/0x1c0
[17088.015778] ? mempool_free_slab+0x17/0x20
[17088.020347] ? mempool_free+0x2b/0x80
[17088.024438] dio_complete+0x14f/0x1d0
[17088.028526] dio_bio_end_aio+0xcb/0x120
[17088.032800] bio_endio+0xa1/0x120
[17088.036501] blk_update_request+0xb7/0x310
[17088.041076] scsi_end_request+0x34/0x200
[17088.045454] scsi_io_completion+0x133/0x5f0
[17088.050123] scsi_finish_command+0xd9/0x120
[17088.054782] scsi_softirq_done+0x145/0x170
[17088.059355] blk_done_softirq+0xa1/0xd0
[17088.063627] __do_softirq+0xc9/0x269
[17088.067619] irq_exit+0xd9/0xf0
[17088.071123] do_IRQ+0x51/0xd0
[17088.074434] common_interrupt+0x9d/0x9d
[17088.078713] </IRQ>
^ permalink raw reply
* [v4.14-rc3 bug] scheduling while atomic in generic/451 test on extN
From: Eryu Guan @ 2017-10-05 6:07 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, lczerner
Hi all,
I hit "scheduling while atomic" bug by running fstests generic/451 on
extN filesystems in v4.14-rc3 testing, but it didn't reproduce for me on
every host I tried, but I've seen it multiple times on multiple hosts. A
test vm of mine with 4 vcpus and 8G memory reproduced the bug reliably,
while a bare metal host with 8 cpus and 8G mem couldn't.
This is due to commit 332391a9935d ("fs: Fix page cache inconsistency
when mixing buffered and AIO DIO"), which defers AIO DIO io completion
to a workqueue if the inode has mapped pages and does page cache
invalidation in process context. I think that the problem is that the
pages can be mapped after the dio->inode->i_mapping->nrpages check, so
we're doing page cache invalidation, which could sleep, in interrupt
context, thus "scheduling while atomic" bug happens.
Defering all AIO DIO completion to workqueue unconditionally (as what
the iomap based path does) fixed the problem for me. But there're
performance concerns to do so in the original discussions.
https://www.spinics.net/lists/linux-fsdevel/msg112669.html
Thanks,
Eryu
[17087.868644] BUG: scheduling while atomic: swapper/0/0/0x00000100
[17087.875363] Modules linked in: dm_thin_pool dm_persistent_data dm_bio_prison dm_snapshot dm_bufio loop dm_flakey dm_mod ses enclosure ext4 mbcache jbd2 intel_rapl sb_edac x86_pkg_temp_thermal intel_powerclamp coretemp kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul mpt3sas ghash_clmulni_intel raid_class sg scsi_transport_sas pcbc ipmi_ssif shpchp aesni_intel crypto_simd iTCO_wdt glue_helper ipmi_si cryptd iTCO_vendor_support cdc_ether ipmi_devintf ipmi_msghandler usbnet mii pcspkr acpi_pad wmi dcdbas joydev acpi_power_meter lpc_ich mei_me mei nfsd auth_rpcgss nfs_acl lockd grace sunrpc ip_tables xfs libcrc32c mgag200 drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops sd_mod igb ttm ahci ptp libahci drm libata pps_core crc32c_intel dca megaraid_sas i2c_algo_bit i2c_core [last unloaded: scsi_debug]
[17087.955757] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W 4.14.0-rc3 #1
[17087.964110] Hardware name: Dell Inc. PowerEdge R620/01W23F, BIOS 2.5.4 01/22/2016
[17087.972460] Call Trace:
[17087.975189] <IRQ>
[17087.977441] dump_stack+0x63/0x89
[17087.981143] __schedule_bug+0x62/0x70
[17087.985232] __schedule+0x7bb/0x890
[17087.989125] schedule+0x36/0x80
[17087.992629] io_schedule+0x16/0x40
[17087.996429] __lock_page+0x10a/0x150
[17088.000420] ? page_cache_tree_insert+0xb0/0xb0
[17088.005470] invalidate_inode_pages2_range+0x240/0x500
[17088.011208] ? kmem_cache_free+0x1ad/0x1c0
[17088.015778] ? mempool_free_slab+0x17/0x20
[17088.020347] ? mempool_free+0x2b/0x80
[17088.024438] dio_complete+0x14f/0x1d0
[17088.028526] dio_bio_end_aio+0xcb/0x120
[17088.032800] bio_endio+0xa1/0x120
[17088.036501] blk_update_request+0xb7/0x310
[17088.041076] scsi_end_request+0x34/0x200
[17088.045454] scsi_io_completion+0x133/0x5f0
[17088.050123] scsi_finish_command+0xd9/0x120
[17088.054782] scsi_softirq_done+0x145/0x170
[17088.059355] blk_done_softirq+0xa1/0xd0
[17088.063627] __do_softirq+0xc9/0x269
[17088.067619] irq_exit+0xd9/0xf0
[17088.071123] do_IRQ+0x51/0xd0
[17088.074434] common_interrupt+0x9d/0x9d
[17088.078713] </IRQ>
^ permalink raw reply
* Re: [ANNOUNCE] Git v2.15.0-rc0
From: Jeff King @ 2017-10-05 6:09 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <xmqq7ewa87fw.fsf@gitster.mtv.corp.google.com>
On Thu, Oct 05, 2017 at 02:55:31PM +0900, Junio C Hamano wrote:
> Git 2.15 Release Notes (draft)
> ==============================
>
> Backward compatibility notes and other notable changes.
>
> * Use of an empty string as a pathspec element that is used for
> 'everything matches' is still warned and Git asks users to use a
> more explicit '.' for that instead. The hope is that existing
> users will not mind this change, and eventually the warning can be
> turned into a hard error, upgrading the deprecation into removal of
> this (mis)feature. That is now scheduled to happen in the upcoming
> release.
I wasn't sure if this "upcoming" meant v2.15 ("the upcoming release that
we're about to tag") or v2.16. Judging from "What's cooking" it's the
latter, but perhaps we should be more explicit. I don't know if you are
hesitant to name it "v2.16" at this point, but maybe:
...in the upcoming release (i.e., the one after v2.15).
would help.
> * Git now avoids blindly falling back to ".git" when the setup
> sequence said we are _not_ in Git repository. A corner case that
> happens to work right now may be broken by a call to die("BUG").
An even more minor nit. This is now BUG(). :)
I don't think it matters for our purposes here, of course. But I did
wonder how long we'd want to carry this warning in the notes. I think it
goes back to v2.13. Of course people sometimes jump several versions
without necessarily reading the interim release notes, so it makes sense
to carry it for a while.
-Peff
^ permalink raw reply
* [PATCH] ath10k: fix sending wmi cmd during the tdls teardown
From: akolli @ 2017-10-05 6:12 UTC (permalink / raw)
To: ath10k; +Cc: akolli, linux-wireless, Anilkumar Kolli
From: Anilkumar Kolli <akolli@codeaurora.org>
The current firmware 10.4-3.5.1-00035 on QCA9888 supports
TDLS explicit mode, it expects WMI_TDLS_ENABLE_PASSIVE
for tdls setup and WMI_TDLS_DISABLE for tdls teardown.
Signed-off-by: Anilkumar Kolli <akolli@qti.qualcomm.com>
---
drivers/net/wireless/ath/ath10k/wmi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 38a97086708b..cad2e42dcef6 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -7870,7 +7870,8 @@ static int ath10k_wmi_10_4_op_get_vdev_subtype(struct ath10k *ar,
if (!skb)
return ERR_PTR(-ENOMEM);
- if (test_bit(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, ar->wmi.svc_map))
+ if (test_bit(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, ar->wmi.svc_map) &&
+ state == WMI_TDLS_ENABLE_ACTIVE)
state = WMI_TDLS_ENABLE_PASSIVE;
if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
--
1.7.9.5
^ permalink raw reply related
* Re: Some questions
From: Sitsofe Wheeler @ 2017-10-05 6:09 UTC (permalink / raw)
To: Никита Горбунов
Cc: fio@vger.kernel.org
In-Reply-To: <CAGEeD9ajaBeqZvXnP+wn3Cc48sL+O_jF1p6RavLQzFn0vX8SvA@mail.gmail.com>
Hi,
On 4 October 2017 at 07:58, Никита Горбунов <tshiva@promobit.ru> wrote:
> I write my ioengine and have some questions about how work fio.
>
> 1. What to do if function "getevents" transmitted pointer (const
> struct timespec *t) which indicated garbage?
> I want to paused my ioengine on some msec(sec,nsec) when ioengine
> wants get answer about recording of write. I don't understand how can
> get time for waiting if time pointer indicated garbage. Why does he
> pass the pointer to the garbage?
You need to check if it is not null before you use it. Off the top of
my head I think this is the only place I've seen it being used
https://github.com/axboe/fio/blob/fio-3.1/engines/libaio.c#L145 and
it's only usuable in certain conditions. If you chase your way up the
code to https://github.com/axboe/fio/blob/fio-3.1/io_u.c#L2001 you can
see you only get a non-NULL timespec when you don't require a minimum
number of events before returning (i.e. the case where you're using
the libaio ioengine with userspace_reap=1 - see
http://fio.readthedocs.io/en/latest/fio_doc.html#cmdoption-arg-userspace-reap
). If you need to just wait for an amount of time you can grab/check
time with fio_gettime/mtime_since_now as in
https://github.com/axboe/fio/blob/fio-3.1/engines/libaio.c#L284 .
> 2. What is the call queue function of ioengine? Can you write minimal
> viable call chain? (init->open->queue->commit->getevents->cleanup)
It's going to depend. The comments in the skeleton ioengine
(https://github.com/axboe/fio/blob/fio-3.1/engines/skeleton_external.c
actually state which callbacks must be present (e.g. commit is
optional because your ioengine might be synchrnous). Even open/close
may not be required if the ioengine is somehow synthetic or
connectionless. There are also additional optional callbacks that can
be added that are not mentioned in the skeleton ioengine...
Your suggested chain looks OK if all those are callbacks are defined
but you may find queue is called multiple times successively (since it
seems your theoretical ioengine is async), getevents may be called
multiple times etc.
> 3. Are the function of ioengine can be called in several threads
> without indicated numjobs?
Each numjob gets its own ioengine - you don't know if a job is going
to be run as a process or a thread. If your ioengine is using
something that's not thread safe then your ioengine is responsible for
serializing access to it...
> 4. Why in null-ioengine when iodepth=1 we indicate this flag:
> "td->io_ops->flags |= FIO_SYNCIO;" (sorry for my english)
(I think this setting is informal enough you don't need to worry too
much about your English so long as people know what you mean :-) That
ioengine "wants" to behave like a synchronous ioengine when the depth
is 1 and like an asynchronous ioengine when the depth is greater than
1. I'm guessing wildly but perhaps being an asynchronous ioengine
induces a bit of extra overhead? If you're writing a "throw everything
away" ioengine that is going as fast as possible for benchmarking the
other parts of fio itself, every little counts...
--
Sitsofe | http://sucs.org/~sits/
^ permalink raw reply
* [PATCH] ath10k: fix sending wmi cmd during the tdls teardown
From: akolli @ 2017-10-05 6:12 UTC (permalink / raw)
To: ath10k; +Cc: Anilkumar Kolli, akolli, linux-wireless
From: Anilkumar Kolli <akolli@codeaurora.org>
The current firmware 10.4-3.5.1-00035 on QCA9888 supports
TDLS explicit mode, it expects WMI_TDLS_ENABLE_PASSIVE
for tdls setup and WMI_TDLS_DISABLE for tdls teardown.
Signed-off-by: Anilkumar Kolli <akolli@qti.qualcomm.com>
---
drivers/net/wireless/ath/ath10k/wmi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index 38a97086708b..cad2e42dcef6 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -7870,7 +7870,8 @@ static int ath10k_wmi_10_4_op_get_vdev_subtype(struct ath10k *ar,
if (!skb)
return ERR_PTR(-ENOMEM);
- if (test_bit(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, ar->wmi.svc_map))
+ if (test_bit(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, ar->wmi.svc_map) &&
+ state == WMI_TDLS_ENABLE_ACTIVE)
state = WMI_TDLS_ENABLE_PASSIVE;
if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map))
--
1.7.9.5
_______________________________________________
ath10k mailing list
ath10k@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/ath10k
^ permalink raw reply related
* Re: [PATCH 0/2] kprobes: improve error handling when arming/disarming kprobes
From: Masami Hiramatsu @ 2017-10-05 6:09 UTC (permalink / raw)
To: Steven Rostedt, Jessica Yu
Cc: Petr Mladek, Ananth N Mavinakayanahalli, Anil S Keshavamurthy,
David S . Miller, Ingo Molnar, Josh Poimboeuf, Joe Lawrence,
Jiri Kosina, Miroslav Benes, live-patching, linux-kernel
In-Reply-To: <20171004154413.30daa238@gandalf.local.home>
On Wed, 4 Oct 2017 15:44:13 -0400
Steven Rostedt <rostedt@goodmis.org> wrote:
> Masami,
>
> Can you review these patches?
Yes, of course :)
>
> -- Steve
>
>
> On Wed, 4 Oct 2017 21:14:12 +0200
> Jessica Yu <jeyu@kernel.org> wrote:
>
> > Hi,
> >
> > This patchset attempts to improve error handling when arming or disarming
> > ftrace-based kprobes. The current behavior is to simply WARN when ftrace
> > (un-)registration fails, without propagating the error code. This can lead
> > to confusing situations where, for example, register_kprobe()/enable_kprobe()
> > would return 0 indicating success even if arming via ftrace had failed. In
> > this scenario we'd end up with a non-functioning kprobe even though kprobe
> > registration (or enablement) returned success. In this patchset, we take
> > errors from ftrace into account and propagate the error when we cannot arm
> > or disarm a kprobe.
> >
> > Below is an example that illustrates the problem using livepatch and
> > systemtap (which uses kprobes underneath). Both livepatch and kprobes use
> > ftrace ops with the IPMODIFY flag set, so registration at the same
> > function entry is limited to only one ftrace user.
> >
> > Before
> > ------
> > # modprobe livepatch-sample # patches cmdline_proc_show, ftrace ops has IPMODIFY set
> > # stap -e 'probe kernel.function("cmdline_proc_show").call { printf ("cmdline_proc_show\n"); }'
> >
> > .. (nothing prints after reading /proc/cmdline) ..
> >
> > The systemtap handler doesn't execute due to a kprobe arming failure caused
> > by a ftrace IPMODIFY conflict with livepatch, and there isn't an obvious
> > indication of error from systemtap (because register_kprobe() returned
> > success) unless the user inspects dmesg.
Ah, right. It should be handled.
> >
> > After
> > -----
> > # modprobe livepatch-sample
> > # stap -e 'probe kernel.function("cmdline_proc_show").call { printf ("cmdline_proc_show\n"); }'
> > WARNING: probe kernel.function("cmdline_proc_show@/home/jeyu/work/linux-next/fs/proc/cmdline.c:6").call (address 0xffffffffa82fe910) registration error (rc -16)
> >
> > Although the systemtap handler doesn't execute (as it shouldn't), the
> > ftrace error is propagated and now systemtap prints a visible error message
> > stating that (kprobe) registration had failed (because register_kprobe()
> > returned an error), along with the propagated error code.
Would you have any test-case for this livepatch-kprobes combination?
Thank you,
> >
> > This patchset was based on Petr Mladek's original patchset (patches 2 and 3)
> > back in 2015, which improved kprobes error handling, found here:
> >
> > https://lkml.org/lkml/2015/2/26/452
> >
> > However, further work on this had been paused since then and the patches
> > were not upstreamed.
> >
> > This patchset has been lightly sanity-tested (on linux-next) with kprobes,
> > kretprobes, jprobes, and optimized kprobes. It passes the kprobes smoke
> > test, but more testing is greatly appreciated.
> >
> > Thanks,
> >
> > Jessica
> >
> > ---
> > Jessica Yu (2):
> > kprobes: propagate error from arm_kprobe_ftrace()
> > kprobes: propagate error from disarm_kprobe_ftrace()
> >
> > kernel/kprobes.c | 163 ++++++++++++++++++++++++++++++++++++++-----------------
> > 1 file changed, 112 insertions(+), 51 deletions(-)
> >
>
--
Masami Hiramatsu <mhiramat@kernel.org>
^ permalink raw reply
* Re: [PATCH v3] drm/i915/mst: Use MST sideband message transactions for dpms control
From: Jani Nikula @ 2017-10-05 6:10 UTC (permalink / raw)
To: Lyude Paul, Dhinakaran Pandiyan, intel-gfx
In-Reply-To: <1507143802.8401.5.camel@redhat.com>
On Wed, 04 Oct 2017, Lyude Paul <lyude@redhat.com> wrote:
> On Wed, 2017-10-04 at 11:47 +0300, Jani Nikula wrote:
>> On Tue, 03 Oct 2017, Jani Nikula <jani.nikula@intel.com> wrote:
>> > From: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
>> >
>> > Use the POWER_DOWN_PHY and POWER_UP_PHY sideband message transactions to
>> > set power states for downstream sinks. Apart from giving us the ability
>> > to set power state for individual sinks, this fixes the below test for
>> > me.
>> >
>> > $ xrandr --display :0 --output DP-2-2-8 --off
>> > $ xrandr --display :0 --output DP-2-2-1 --off
>> > $ xrandr --display :0 --output DP-2-2-8 --auto #Black screen
>> > $ xrandr --display :0 --output DP-2-2-1 --auto
>> >
>> > v2: Modify and document the dpms and port disable order (Ville)
>> > Add comment explaining is_mst = !crtc_state equivalence(Ville,
>> > Maarten)
>> >
>> > v3 by Jani: rebase
>> >
>> > References: https://bugs.freedesktop.org/show_bug.cgi?id=90963
>> > References: https://bugs.freedesktop.org/show_bug.cgi?id=88124
>> > Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
>> > Cc: Lyude <lyude@redhat.com>
>> > Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>> > Reviewed-by: Lyude Paul <lyude@redhat.com>
>> > Acked-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
>>
>> Lyude, Maarten, can you confirm your rb/ack on my rebase please?
> Looks good to me
Thanks Maarten and Lyude, pushed to dinq.
BR,
Jani.
>>
>> BR,
>> Jani.
>>
>>
>> > Signed-off-by: Dhinakaran Pandiyan <dhinakaran.pandiyan@intel.com>
>> > Signed-off-by: Jani Nikula <jani.nikula@intel.com>
>> > ---
>> > drivers/gpu/drm/i915/intel_ddi.c | 18 ++++++++++++++----
>> > drivers/gpu/drm/i915/intel_dp_mst.c | 10 ++++++++--
>> > 2 files changed, 22 insertions(+), 6 deletions(-)
>> >
>> > diff --git a/drivers/gpu/drm/i915/intel_ddi.c
>> > b/drivers/gpu/drm/i915/intel_ddi.c
>> > index 65f4b6786791..511aa60e0176 100644
>> > --- a/drivers/gpu/drm/i915/intel_ddi.c
>> > +++ b/drivers/gpu/drm/i915/intel_ddi.c
>> > @@ -2162,7 +2162,8 @@ static void intel_ddi_pre_enable_dp(struct
>> > intel_encoder *encoder,
>> > intel_prepare_dp_ddi_buffers(encoder);
>> >
>> > intel_ddi_init_dp_buf_reg(encoder);
>> > - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
>> > + if (!link_mst)
>> > + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON);
>> > intel_dp_start_link_train(intel_dp);
>> > if (port != PORT_A || INTEL_GEN(dev_priv) >= 9)
>> > intel_dp_stop_link_train(intel_dp);
>> > @@ -2236,12 +2237,21 @@ static void intel_ddi_post_disable(struct
>> > intel_encoder *intel_encoder,
>> > uint32_t val;
>> > bool wait = false;
>> >
>> > - /* old_crtc_state and old_conn_state are NULL when called from
>> > DP_MST */
>> > -
>> > if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) {
>> > + /*
>> > + * old_crtc_state and old_conn_state are NULL when called
>> > from
>> > + * DP_MST. The main connector associated with this port
>> > is never
>> > + * bound to a crtc for MST.
>> > + */
>> > + bool is_mst = !old_crtc_state;
>> > struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>> >
>> > - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
>> > + /*
>> > + * Power down sink before disabling the port, otherwise
>> > we end
>> > + * up getting interrupts from the sink on detecting link
>> > loss.
>> > + */
>> > + if (!is_mst)
>> > + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
>> > }
>> >
>> > val = I915_READ(DDI_BUF_CTL(port));
>> > diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c
>> > b/drivers/gpu/drm/i915/intel_dp_mst.c
>> > index 9a396f483f8b..3c131e2544cf 100644
>> > --- a/drivers/gpu/drm/i915/intel_dp_mst.c
>> > +++ b/drivers/gpu/drm/i915/intel_dp_mst.c
>> > @@ -162,14 +162,19 @@ static void intel_mst_post_disable_dp(struct
>> > intel_encoder *encoder,
>> >
>> > drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port);
>> >
>> > + /*
>> > + * Power down mst path before disabling the port, otherwise we
>> > end
>> > + * up getting interrupts from the sink upon detecting link loss.
>> > + */
>> > + drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port,
>> > + false);
>> > +
>> > intel_dp->active_mst_links--;
>> >
>> > intel_mst->connector = NULL;
>> > if (intel_dp->active_mst_links == 0) {
>> > intel_dig_port->base.post_disable(&intel_dig_port->base,
>> > NULL, NULL);
>> > -
>> > - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF);
>> > }
>> > DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links);
>> > }
>> > @@ -196,6 +201,7 @@ static void intel_mst_pre_enable_dp(struct
>> > intel_encoder *encoder,
>> >
>> > DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links);
>> >
>> > + drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port,
>> > true);
>> > if (intel_dp->active_mst_links == 0)
>> > intel_dig_port->base.pre_enable(&intel_dig_port->base,
>> > pipe_config, NULL);
>>
>>
--
Jani Nikula, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
^ permalink raw reply
* Re: [PATCH] docs: Specify V3 of the mbox protocol
From: Andrew Jeffery @ 2017-10-05 6:10 UTC (permalink / raw)
To: Suraj Jitindar Singh, skiboot, openbmc; +Cc: wak, cyrilbur, stewart
In-Reply-To: <20171004004520.18593-1-sjitindarsingh@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 17143 bytes --]
On Wed, 2017-10-04 at 11:45 +1100, Suraj Jitindar Singh wrote:
> Version 3 of the mbox protocol makes four protocol changes:
> - Add a requested block size argument to GET_MBOX_INFO
> - Add a no erase argument to MARK_DIRTY
> - Add a GET_FLASH_NAME command and support multiple flash devices
> - Add a MARK_LOCKED command
>
> Requested Block Size:
> The requested block size argument has been added to the GET_MBOX_INFO
> command to allow the host to request a specified block size which might
> be required to allow data manipulation at a finer granularity. The
> daemon should take this into account when choosing a block size for use
> which it will specify in the response as before. The daemon has final
> say and the host must use the block size the daemon chooses.
>
> No Erase:
> The no erase argument to the mark dirty command allows a host to specify
> that an area of flash should not be erased before being written to, as is
> the default behaviour. This can be used when a host has already erased a
> large area and then performs many small writes which would normally mean
> many erases due to the implicit erase before write, making this slow.
>
> Add GET_FLASH_NAME command:
> The ability to support multiple flash devices has been added so that the
> mbox protocol can be used to arbitrate access from the host to a number
> of flash devices which the daemon has access to. To facilitate this the
> GET_FLASH_INFO, CREATE_{READ/WRITE}_WINDOW, and MARK_LOCKED commands now
> take a flash ID, with the number of flash IDs allocated returned by the
> GET_MBOX_INFO commands. There is also a new command GET_FLASH_NAME used
> to convert a flash ID to a flash name.
>
> Add MARK_LOCKED command:
> The MARK_LOCKED command has been added to allow an area(s) of flash to be
> locked, that is that area must be treated as read only and the host is
> not allowed to dirty or erase any windows which map that area of flash.
> Additionally another error code LOCKED_ERROR was added to be returned
> when the host does try to dirty or erase a locked area.
>
> The host cannot lock a currently dirty or erased area of the current
> write window as it is not defined if the clean/dirty/erased value is
> what should actually be "locked".
>
> A locked area of flash remains so until the daemon receives an
> mboxctl --clear-locked command and the locked areas are stored in a file
> on the BMC filesystem to ensure persistence across BMC reboots/daemon
> crashes.
>
> Multiple flash device support proposed and defined by:
> > William A. Kennington III <wak@google.com>
>
> Change-Id: I898698840dec221ae20e33943bb28e65abc4fe37
> Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
Reviewed-by: Andrew Jeffery <andrew@aj.id.au>
But everyone else: please chime in.
Cheers,
Andrew
> ---
> Documentation/mbox_protocol.md | 163 ++++++++++++++++++++++++++++++++---------
> 1 file changed, 127 insertions(+), 36 deletions(-)
>
> diff --git a/Documentation/mbox_protocol.md b/Documentation/mbox_protocol.md
> index bcd70a8..797ac7b 100644
> --- a/Documentation/mbox_protocol.md
> +++ b/Documentation/mbox_protocol.md
> @@ -17,19 +17,22 @@ limitations under the License.
> This document describes a protocol for host to BMC communication via the
> mailbox registers present on the Aspeed 2400 and 2500 chips.
> This protocol is specifically designed to allow a host to request and manage
> -access to the flash with the specifics of how the host is required to control
> -this described below.
> +access to a flash device(s) with the specifics of how the host is required to
> +control this described below.
>
> ## Version
>
> -Both version 1 and version 2 of the protocol are described below with version 2
> -specificities represented with V2 in brackets - (V2).
> +Version specific protocol functionalities are represented by the version number
> +in brackets next to the definition of the functionality. (e.g. (V2) for version
> +2 specific funtionality). All version specific functionality must also be
> +implemented by proceeding versions up to and not including the version a command
> +was removed.
>
> ## Problem Overview
>
> "mbox" is the name we use to represent a protocol we have established between
> the host and the BMC via the Aspeed mailbox registers. This protocol is used
> -for the host to control the flash.
> +for the host to control access to the flash device(s).
>
> Prior to the mbox protocol, the host uses a backdoor into the BMC address space
> (the iLPC-to-AHB bridge) to directly manipulate the BMCs own flash controller.
> @@ -215,9 +218,11 @@ communicate a change in state.
> Given that a majority of command and response arguments are specified as a
> multiple of block size it is necessary for the host and BMC to agree on a
> protocol version as this determines the block size. In V1 it is hard coded at
> -4K and in V2 the BMC chooses and specifies this to the host as a response
> -argument to `MBOX_GET_INFO`. Thus the host must always call `MBOX_GET_INFO`
> -before any other command which specifies an argument in block size.
> +4K, in V2 the BMC chooses and in V3 the host is allowed to request a specific
> +block size with the actual size chosen communicated back to the host as a
> +response argument to `MBOX_GET_INFO`. Thus the host must always call
> +`MBOX_GET_INFO` before any other command which specifies an argument in block
> +size.
>
> When invoking `MBOX_GET_INFO` the host must provide the BMC its highest
> supported version of the protocol. The BMC must respond with a protocol version
> @@ -231,10 +236,13 @@ version by issuing a subsequent `MBOX_GET_INFO` command.
> ### Window Management
>
> In order to access flash contents, the host must request a window be opened at
> -the flash offset it would like to access. The host may give a hint as to how
> -much data it would like to access or otherwise set this argument to zero. The
> -BMC must respond with the LPC bus address to access this window and the
> -window size. The host must not access past the end of the active window.
> +the flash offset it would like to access with the CREATE_{READ,WRITE}_WINDOW
> +commands. The host may give a hint as to how much data it would like to access
> +or otherwise set this argument to zero. The BMC must respond with the LPC bus
> +address to access this window and the window size. The host must not access
> +past the end of the active window. On returning success to either of the create
> +window commands the BMC must guarantee that the window provided contains data
> +which correctly represents the state of flash at the time the response is given.
>
> There is only ever one active window which is the window created by the most
> recent CREATE_READ_WINDOW or CREATE_WRITE_WINDOW call which succeeded. Even
> @@ -278,7 +286,19 @@ contents cannot be guaranteed.
>
> The host is not required to perform an erase before a write command and the
> BMC must ensure that a write performs as expected - that is if an erase is
> -required before a write then the BMC must perform this itself.
> +required before a write then the BMC must perform this itself (unless the
> +no_erase flag is set in the MARK_WRITE_DIRTY command in which case the BMC will
> +blindly write without a prior erase (V3)).
> +
> +The host may lock an area of flash using the MARK_LOCKED command. Any attempt
> +to mark dirty or erased this area of flash must fail with the LOCKED_ERROR
> +response code. The host may open a write window which contains a locked area
> +of flash however changes to a locked area of flash must never be written back
> +to the backing data source (i.e. that area of flash must be treated as read
> +only with respect to the backing store at all times). An attempt to lock an area
> +of flash which is not clean in the current window must fail with PARAM_ERROR.
> +Locked flash regions must persist across a BMC reboot or daemon restart. It is
> +only possible to clear the lock state through a clear_locked dbus command. (V3)
>
> ### BMC Events
>
> @@ -316,6 +336,8 @@ MARK_WRITE_DIRTY 0x07
> WRITE_FLUSH 0x08
> BMC_EVENT_ACK 0x09
> > MARK_WRITE_ERASED 0x0a (V2)
> > +GET_FLASH_NAME 0x0b (V3)
> > +MARK_LOCKED 0x0c (V3)
> ```
>
> ### Responses
> > @@ -329,13 +351,14 @@ TIMEOUT 5
> > > BUSY 6 (V2)
> > > WINDOW_ERROR 7 (V2)
> > > SEQ_ERROR 8 (V2)
> > > +LOCKED_ERROR 9 (V3)
> ```
>
> ### Sequence Numbers
>
> Sequence numbers are included in messages for correlation of commands and
> -responses. V1 and V2 of the protocol permit either zero or one commands to be
> -in progress (yet to receive a response).
> +responses. V1, V2 and V3 of the protocol permit either zero or one commands to
> +be in progress (yet to receive a response).
>
> For generality, the host must generate a sequence number that is unique with
> respect to the previous command (one that has received a response) and any
> > @@ -368,6 +391,10 @@ BUSY - Daemon in suspended state (currently unable to access flash)
> > WINDOW_ERROR - Command not valid for active window or no active window
> > - Try opening an appropriate window and retrying the command
>
> > +SEQ_ERROR - Invalid sequence number supplied with command
> +
> > +LOCKED_ERROR - Tried to mark dirty or erased locked area of flash
> +
> ### Information
> - All multibyte messages are LSB first (little endian)
> - All responses must have a valid return code in byte 13
> @@ -381,6 +408,12 @@ allows us to specify larger values with fewer command and response fields.
>
> In V1 block size is hard coded to 4K.
> In V2 it is variable and must be queried with the GET_MBOX_INFO command.
> +In V3 the host can request a given block size however it is ultimately up to
> +the daemon to choose a block size which is returned as part of the GET_MBOX_INFO
> +command response. The host must respect the daemons choice. The ability for the
> +host to request a block size is provided such that it can choose an appropriate
> +size to be able to utilise commands which only operate at the block level.
> +
> Note that for simplicity block size must always be a power-of-2.
> Block size must also be greater than or equal to 4K. This is due to the
> fact that we have a 28-bit LPC address space and commands which return an
> @@ -395,8 +428,7 @@ multiplying by the block size.
> ```
> Command:
> > RESET_STATE
> > - Implemented in Versions:
> > - V1, V2
> > > + Added in: V1
> > Arguments:
> > -
> > Response:
> @@ -409,8 +441,7 @@ Command:
>
> Command:
> > GET_MBOX_INFO
> > - Implemented in Versions:
> > - V1, V2
> > > + Added in: V1
> > Arguments:
> > V1:
> > Args 0: API version
> @@ -418,6 +449,10 @@ Command:
> > V2:
> > Args 0: API version
>
> > + V3:
> > + Args 0: API version
> > + Args 1: Requested block size (shift)
> +
> > Response:
> > V1:
> > Args 0: API version
> @@ -430,6 +465,14 @@ Command:
> > Args 3-4: reserved
> > Args 5: Block size as power of two (encoded as a shift)
> > Args 6-7: Suggested Timeout (seconds)
> +
> > + V3:
> > + Args 0: API version
> > + Args 1-2: reserved
> > + Args 3-4: reserved
> > + Args 5: Block size as power of two (encoded as a shift)
> > + Args 6-7: Suggested Timeout (seconds)
> > + Args 8: Num Allocated Flash IDs
> > Notes:
> > The suggested timeout is a hint to the host as to how long
> > it should wait after issuing a command to the BMC before it
> @@ -439,25 +482,34 @@ Command:
> > > the BMC does not wish to provide a hint in which case the host
> > must choose some reasonable value.
>
> > + The host may desire a specific block size and thus can request
> > + this by giving a hint to the daemon (may be zero). The daemon
> > + may use this to select the block size which it will use however
> > + is free to ignore it. The value in the response is the block
> > + size which must be used for all further requests until a new
> > > + size is negotiated by another call to GET_MBOX_INFO. (V3)
> +
> Command:
> > GET_FLASH_INFO
> > - Implemented in Versions:
> > - V1, V2
> > > + Added in: V1
> > Arguments:
> > + V1, V2:
> > -
> +
> > + V3:
> > + Args 0: Flash ID
> > Response:
> > V1:
> > Args 0-3: Flash size (bytes)
> > Args 4-7: Erase granule (bytes)
>
> > - V2:
> > + V2, V3:
> > Args 0-1: Flash size (blocks)
> > Args 2-3: Erase granule (blocks)
>
> Command:
> > CREATE_{READ/WRITE}_WINDOW
> > - Implemented in Versions:
> > - V1, V2
> > > + Added in: V1
> > Arguments:
> > V1:
> > Args 0-1: Requested flash offset (blocks)
> @@ -466,11 +518,15 @@ Command:
> > Args 0-1: Requested flash offset (blocks)
> > Args 2-3: Requested flash size to access (blocks)
>
> > + V3:
> > + Args 0-1: Requested flash offset (blocks)
> > + Args 2-3: Requested flash size to access (blocks)
> > + Args 4: Flash ID
> > Response:
> > V1:
> > Args 0-1: LPC bus address of window (blocks)
>
> > - V2:
> > + V2, V3:
> > Args 0-1: LPC bus address of window (blocks)
> > Args 2-3: Window size (blocks)
> > Args 4-5: Flash offset mapped by window (blocks)
> @@ -505,8 +561,7 @@ Command:
>
> Command:
> > CLOSE_WINDOW
> > - Implemented in Versions:
> > - V1, V2
> > > + Added in: V1
> > Arguments:
> > V1:
> > -
> @@ -534,8 +589,7 @@ Command:
>
> Command:
> > MARK_WRITE_DIRTY
> > - Implemented in Versions:
> > - V1, V2
> > > + Added in: V1
> > Arguments:
> > V1:
> > Args 0-1: Flash offset to mark from base of flash (blocks)
> @@ -544,6 +598,7 @@ Command:
> > V2:
> > Args 0-1: Window offset to mark (blocks)
> > Args 2-3: Number to mark dirty at offset (blocks)
> > + Args 4 : Don't Erase Before Write (V3)
>
> > Response:
> > -
> @@ -558,10 +613,16 @@ Command:
> > block. If the offset + number exceeds the size of the active
> > window then the command must not succeed.
>
> > + The host can give a hint to the daemon that is doesn't have to
> > + erase a flash area before writing to it by setting ARG[4]. This
> > + means that the daemon will blindly perform a write to that area
> > + and will not try to erase it before hand. This can be used if
> > + the host knows that a large area has already been erased for
> > + example but then wants to perform many small writes.
> +
> Command
> > WRITE_FLUSH
> > - Implemented in Versions:
> > - V1, V2
> > > + Added in: V1
> > Arguments:
> > V1:
> > Args 0-1: Flash offset to mark from base of flash (blocks)
> @@ -586,8 +647,7 @@ Command
>
> Command:
> > BMC_EVENT_ACK
> > - Implemented in Versions:
> > - V1, V2
> > > + Added in: V1
> > Arguments:
> > > Args 0: Bits in the BMC status byte (mailbox data
> > register 15) to ack
> @@ -599,8 +659,7 @@ Command:
>
> Command:
> > MARK_WRITE_ERASED
> > - Implemented in Versions:
> > - V2
> > > + Added in: V2
> > Arguments:
> > V2:
> > Args 0-1: Window offset to erase (blocks)
> @@ -617,6 +676,38 @@ Command:
> > number is the number of blocks of the active window to erase
> > starting at offset. If the offset + number exceeds the size of
> > the active window then the command must not succeed.
> +
> +Command:
> > + GET_FLASH_NAME
> > > + Added in: V3
> > + Arguments:
> > + Args 0: Flash ID
> > + Response:
> > + Args 0 : Flash Name Length (bytes)
> > + Args 1-10: Flash Name / UID
> > + Notes:
> > + Describes a flash with some kind of identifier useful to the
> > + host system. This is typically a null-padded string.
> +
> > + The length in the response is the number of response arguments
> > + as part of the flash name field which the host should expect to
> > + have been populated.
> +
> +Command:
> > + MARK_LOCKED
> > > + Added in: V3
> > + Arguments:
> > + Args 0-1: Flash offset to lock (blocks)
> > + Args 2-3: Number to lock at offset (blocks)
> > + Args 4: Flash ID
> > + Response:
> > + -
> > + Notes:
> > + Lock an area of flash so that the host can't mark it dirty or
> > + erased. If the requested area is within the current window and
> > + that area is currently marked dirty or erased then this command
> > + must fail with PARAM_ERROR.
> +
> ```
>
> ### BMC Events in Detail:
> @@ -627,7 +718,7 @@ on that register, or otherwise be polling it.
>
> #### Bit Definitions:
>
> -Events which should be ACKed:
> +Events which must be ACKed:
> ```
> 0x01: BMC Reboot
> 0x02: BMC Windows Reset (V2)
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH v15 00/32] Unified fwnode endpoint parser, async sub-device notifier support, N9 flash DTS
From: Sakari Ailus @ 2017-10-05 6:11 UTC (permalink / raw)
To: Sakari Ailus
Cc: linux-media, niklas.soderlund, maxime.ripard, hverkuil,
laurent.pinchart, pavel, sre, devicetree, linux-acpi,
marc.herbert, hyungwoo.yang, rajmohan.mani, yong.zhi
In-Reply-To: <20171004215051.13385-1-sakari.ailus@linux.intel.com>
On Thu, Oct 05, 2017 at 12:50:19AM +0300, Sakari Ailus wrote:
> Hi folks,
>
> I've dropped the full set from devicetree and linux-acpi lists;
> let me know if you want it back. The entire set is posted to
> linux-media list.
Here's the diff between v14 and v15. The patches can be found here, with
the dependencies:
<URL:https://git.linuxtv.org/sailus/media_tree.git/log/?h=fwnode-parse>
diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
index 5aae5cb38b81..ae026eee3d03 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -248,18 +248,20 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
list_move(&sd->async_list, ¬ifier->done);
/*
- * See if the sub-device has a notifier. If it does, proceed
- * with checking for its async sub-devices.
+ * See if the sub-device has a notifier. If not, return here.
*/
subdev_notifier = v4l2_async_find_subdev_notifier(sd);
- if (subdev_notifier && !subdev_notifier->parent) {
- subdev_notifier->parent = notifier;
- ret = v4l2_async_notifier_try_all_subdevs(subdev_notifier);
- if (ret)
- return ret;
- }
+ if (!subdev_notifier || subdev_notifier->parent)
+ return 0;
- return 0;
+ /*
+ * Proceed with checking for the sub-device notifier's async
+ * sub-devices, and return the result. The error will be handled by the
+ * caller.
+ */
+ subdev_notifier->parent = notifier;
+
+ return v4l2_async_notifier_try_all_subdevs(subdev_notifier);
}
/* Test all async sub-devices in a notifier for a match. */
@@ -304,7 +306,28 @@ static void v4l2_async_cleanup(struct v4l2_subdev *sd)
/* Subdevice driver will reprobe and put the subdev back onto the list */
list_del_init(&sd->async_list);
sd->asd = NULL;
- sd->dev = NULL;
+}
+
+/* Unbind all sub-devices in the notifier tree. */
+static void v4l2_async_notifier_unbind_all_subdevs(
+ struct v4l2_async_notifier *notifier)
+{
+ struct v4l2_subdev *sd, *tmp;
+
+ list_for_each_entry_safe(sd, tmp, ¬ifier->done, async_list) {
+ struct v4l2_async_notifier *subdev_notifier =
+ v4l2_async_find_subdev_notifier(sd);
+
+ if (subdev_notifier)
+ v4l2_async_notifier_unbind_all_subdevs(subdev_notifier);
+
+ v4l2_async_notifier_call_unbind(notifier, sd, sd->asd);
+ v4l2_async_cleanup(sd);
+
+ list_move(&sd->async_list, &subdev_list);
+ }
+
+ notifier->parent = NULL;
}
/* See if an fwnode can be found in a notifier's lists. */
@@ -412,9 +435,11 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
ret = v4l2_async_notifier_try_all_subdevs(notifier);
if (ret)
- goto out_unlock;
+ goto err_unbind;
ret = v4l2_async_notifier_try_complete(notifier);
+ if (ret)
+ goto err_unbind;
/* Keep also completed notifiers on the list */
list_add(¬ifier->list, ¬ifier_list);
@@ -422,69 +447,74 @@ static int __v4l2_async_notifier_register(struct v4l2_async_notifier *notifier)
out_unlock:
mutex_unlock(&list_lock);
+ return 0;
+
+err_unbind:
+ /*
+ * On failure, unbind all sub-devices registered through this notifier.
+ */
+ v4l2_async_notifier_unbind_all_subdevs(notifier);
+
+ mutex_unlock(&list_lock);
+
return ret;
}
int v4l2_async_notifier_register(struct v4l2_device *v4l2_dev,
struct v4l2_async_notifier *notifier)
{
+ int ret;
+
if (WARN_ON(!v4l2_dev || notifier->sd))
return -EINVAL;
notifier->v4l2_dev = v4l2_dev;
- return __v4l2_async_notifier_register(notifier);
+ ret = __v4l2_async_notifier_register(notifier);
+ if (ret)
+ notifier->v4l2_dev = NULL;
+
+ return ret;
}
EXPORT_SYMBOL(v4l2_async_notifier_register);
int v4l2_async_subdev_notifier_register(struct v4l2_subdev *sd,
struct v4l2_async_notifier *notifier)
{
+ int ret;
+
if (WARN_ON(!sd || notifier->v4l2_dev))
return -EINVAL;
notifier->sd = sd;
- return __v4l2_async_notifier_register(notifier);
+ ret = __v4l2_async_notifier_register(notifier);
+ if (ret)
+ notifier->sd = NULL;
+
+ return ret;
}
EXPORT_SYMBOL(v4l2_async_subdev_notifier_register);
-/* Unbind all sub-devices in the notifier tree. */
-static void v4l2_async_notifier_unbind_all_subdevs(
+static void __v4l2_async_notifier_unregister(
struct v4l2_async_notifier *notifier)
{
- struct v4l2_subdev *sd, *tmp;
-
- list_for_each_entry_safe(sd, tmp, ¬ifier->done, async_list) {
- struct v4l2_async_notifier *subdev_notifier =
- v4l2_async_find_subdev_notifier(sd);
-
- if (subdev_notifier)
- v4l2_async_notifier_unbind_all_subdevs(subdev_notifier);
-
- v4l2_async_cleanup(sd);
+ if (!notifier || (!notifier->v4l2_dev && !notifier->sd))
+ return;
- v4l2_async_notifier_call_unbind(notifier, sd, sd->asd);
+ v4l2_async_notifier_unbind_all_subdevs(notifier);
- list_move(&sd->async_list, &subdev_list);
- }
+ notifier->sd = NULL;
+ notifier->v4l2_dev = NULL;
- notifier->parent = NULL;
+ list_del(¬ifier->list);
}
void v4l2_async_notifier_unregister(struct v4l2_async_notifier *notifier)
{
- if (!notifier->v4l2_dev && !notifier->sd)
- return;
-
mutex_lock(&list_lock);
- v4l2_async_notifier_unbind_all_subdevs(notifier);
-
- notifier->sd = NULL;
- notifier->v4l2_dev = NULL;
-
- list_del(¬ifier->list);
+ __v4l2_async_notifier_unregister(notifier);
mutex_unlock(&list_lock);
}
@@ -522,7 +552,9 @@ EXPORT_SYMBOL_GPL(v4l2_async_notifier_cleanup);
int v4l2_async_register_subdev(struct v4l2_subdev *sd)
{
+ struct v4l2_async_notifier *subdev_notifier;
struct v4l2_async_notifier *notifier;
+ int ret;
/*
* No reference taken. The reference is held by the device
@@ -549,47 +581,64 @@ int v4l2_async_register_subdev(struct v4l2_subdev *sd)
if (!asd)
continue;
- ret = v4l2_async_match_notify(notifier, v4l2_dev, sd, asd);
+ ret = v4l2_async_match_notify(notifier, notifier->v4l2_dev, sd,
+ asd);
+ if (ret)
+ goto err_unbind;
- if (!ret)
- ret = v4l2_async_notifier_try_complete(notifier);
+ ret = v4l2_async_notifier_try_complete(notifier);
+ if (ret)
+ goto err_unbind;
- mutex_unlock(&list_lock);
- return ret;
+ goto out_unlock;
}
/* None matched, wait for hot-plugging */
list_add(&sd->async_list, &subdev_list);
+out_unlock:
mutex_unlock(&list_lock);
return 0;
+
+err_unbind:
+ /*
+ * Complete failed. Unbind the sub-devices bound through registering
+ * this async sub-device.
+ */
+ subdev_notifier = v4l2_async_find_subdev_notifier(sd);
+ if (subdev_notifier)
+ v4l2_async_notifier_unbind_all_subdevs(subdev_notifier);
+
+ if (sd->asd)
+ v4l2_async_notifier_call_unbind(notifier, sd, sd->asd);
+ v4l2_async_cleanup(sd);
+
+ mutex_unlock(&list_lock);
+
+ return ret;
}
EXPORT_SYMBOL(v4l2_async_register_subdev);
void v4l2_async_unregister_subdev(struct v4l2_subdev *sd)
{
- struct v4l2_async_notifier *notifier = sd->notifier;
+ mutex_lock(&list_lock);
- if (sd->subdev_notifier)
- v4l2_async_notifier_unregister(sd->subdev_notifier);
+ __v4l2_async_notifier_unregister(sd->subdev_notifier);
v4l2_async_notifier_cleanup(sd->subdev_notifier);
kfree(sd->subdev_notifier);
+ sd->subdev_notifier = NULL;
- if (!sd->asd) {
- if (!list_empty(&sd->async_list))
- v4l2_async_cleanup(sd);
- return;
- }
+ if (sd->asd) {
+ struct v4l2_async_notifier *notifier = sd->notifier;
- mutex_lock(&list_lock);
+ list_add(&sd->asd->list, ¬ifier->waiting);
- list_add(&sd->asd->list, ¬ifier->waiting);
+ v4l2_async_notifier_call_unbind(notifier, sd, sd->asd);
+ }
v4l2_async_cleanup(sd);
- v4l2_async_notifier_call_unbind(notifier, sd, sd->asd);
-
mutex_unlock(&list_lock);
}
EXPORT_SYMBOL(v4l2_async_unregister_subdev);
diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h
index 74f2ea27d117..65f87e80081a 100644
--- a/include/media/v4l2-async.h
+++ b/include/media/v4l2-async.h
@@ -201,5 +201,4 @@ int __must_check v4l2_async_register_subdev_sensor_common(
* @sd: pointer to &struct v4l2_subdev
*/
void v4l2_async_unregister_subdev(struct v4l2_subdev *sd);
-
#endif
diff --git a/include/media/v4l2-fwnode.h b/include/media/v4l2-fwnode.h
index 834e74246412..43fd1a278bcc 100644
--- a/include/media/v4l2-fwnode.h
+++ b/include/media/v4l2-fwnode.h
@@ -137,7 +137,7 @@ struct v4l2_fwnode_link {
int v4l2_fwnode_endpoint_parse(struct fwnode_handle *fwnode,
struct v4l2_fwnode_endpoint *vep);
-/*
+/**
* v4l2_fwnode_endpoint_free() - free the V4L2 fwnode acquired by
* v4l2_fwnode_endpoint_alloc_parse()
* @vep - the V4L2 fwnode the resources of which are to be released
--
Sakari Ailus
e-mail: sakari.ailus@iki.fi
^ permalink raw reply related
* [PATCH 0/6] drm: Add leases [v4]
From: Keith Packard @ 2017-10-05 6:13 UTC (permalink / raw)
To: linux-kernel, Dave Airlie, Daniel Vetter; +Cc: Keith Packard, dri-devel
Here's another version of the DRM lease series. No changes in the code
at all:
[PATCH 4/6] drm: Add drm_object lease infrastructure [v4]
Changes in v4, suggested by Dave Airlie <airlied@gmail.com>
* Formatting and whitespace changes
[PATCH 6/6] drm: Add four ioctls for managing drm mode object leases
Changes for v3 suggested by Dave Airlie <airlied@gmail.com>
* Expand on the comment about the magic use of &drm_lease_idr_object
* Pad lease ioctl structures to align on 64-bit boundaries
Thanks much to Dave Airlie for his review.
-keith
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply
* [PATCH 2/6] drm: Allow render nodes to query display objects
From: Keith Packard @ 2017-10-05 6:13 UTC (permalink / raw)
To: linux-kernel, Dave Airlie, Daniel Vetter; +Cc: Keith Packard, dri-devel
In-Reply-To: <20171005061310.29919-1-keithp@keithp.com>
This allows an application to discover what display resources are
available before requesting a lease from the X server.
Signed-off-by: Keith Packard <keithp@keithp.com>
---
drivers/gpu/drm/drm_ioctl.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 8bfeb32f8a10..7d0e481c5729 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -613,27 +613,27 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
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_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_RENDER_ALLOW|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_GETPLANE, drm_mode_getplane, DRM_RENDER_ALLOW|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_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),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
@@ -642,7 +642,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
--
2.13.3
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH 3/6] drm: Add new LEASE debug level
From: Keith Packard @ 2017-10-05 6:13 UTC (permalink / raw)
To: linux-kernel, Dave Airlie, Daniel Vetter; +Cc: Keith Packard, dri-devel
In-Reply-To: <20171005061310.29919-1-keithp@keithp.com>
Separate out lease debugging from the core.
Signed-off-by: Keith Packard <keithp@keithp.com>
---
drivers/gpu/drm/drm_drv.c | 3 ++-
include/drm/drmP.h | 4 ++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 2ed2d919beae..f390b30f5906 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -57,7 +57,8 @@ MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug cat
"\t\tBit 2 (0x04) will enable KMS messages (modesetting code)\n"
"\t\tBit 3 (0x08) will enable PRIME messages (prime code)\n"
"\t\tBit 4 (0x10) will enable ATOMIC messages (atomic code)\n"
-"\t\tBit 5 (0x20) will enable VBL messages (vblank code)");
+"\t\tBit 5 (0x20) will enable VBL messages (vblank code)\n"
+"\t\tBit 7 (0x80) will enable LEASE messages (leasing code)");
module_param_named(debug, drm_debug, int, 0600);
static DEFINE_SPINLOCK(drm_minor_lock);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3aa3809ab524..2a54ccb16232 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -145,6 +145,7 @@ struct pci_controller;
#define DRM_UT_ATOMIC 0x10
#define DRM_UT_VBL 0x20
#define DRM_UT_STATE 0x40
+#define DRM_UT_LEASE 0x80
/***********************************************************************/
/** \name DRM template customization defaults */
@@ -259,6 +260,9 @@ struct pci_controller;
#define DRM_DEBUG_VBL(fmt, ...) \
drm_printk(KERN_DEBUG, DRM_UT_VBL, fmt, ##__VA_ARGS__)
+#define DRM_DEBUG_LEASE(fmt, ...) \
+ drm_printk(KERN_DEBUG, DRM_UT_LEASE, fmt, ##__VA_ARGS__)
+
#define _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, level, fmt, args...) \
({ \
static DEFINE_RATELIMIT_STATE(_rs, \
--
2.13.3
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH 4/6] drm: Add drm_object lease infrastructure [v4]
From: Keith Packard @ 2017-10-05 6:13 UTC (permalink / raw)
To: linux-kernel, Dave Airlie, Daniel Vetter; +Cc: Keith Packard, dri-devel
In-Reply-To: <20171005061310.29919-1-keithp@keithp.com>
This provides new data structures to hold "lease" information about
drm mode setting objects, and provides for creating new drm_masters
which have access to a subset of the available drm resources.
An 'owner' is a drm_master which is not leasing the objects from
another drm_master, and hence 'owns' them.
A 'lessee' is a drm_master which is leasing objects from some other
drm_master. Each lessee holds the set of objects which it is leasing
from the lessor.
A 'lessor' is a drm_master which is leasing objects to another
drm_master. This is the same as the owner in the current code.
The set of objects any drm_master 'controls' is limited to the set of
objects it leases (for lessees) or all objects (for owners).
Objects not controlled by a drm_master cannot be modified through the
various state manipulating ioctls, and any state reported back to user
space will be edited to make them appear idle and/or unusable. For
instance, connectors always report 'disconnected', while encoders
report no possible crtcs or clones.
The full list of lessees leasing objects from an owner (either
directly, or indirectly through another lessee), can be searched from
an idr in the drm_master of the owner.
Changes for v2 as suggested by Daniel Vetter <daniel.vetter@ffwll.ch>:
* Sub-leasing has been disabled.
* BUG_ON for lock checking replaced with lockdep_assert_held
* 'change' ioctl has been removed.
* Leased objects can always be controlled by the lessor; the
'mask_lease' flag has been removed
* Checking for leased status has been simplified, replacing
the drm_lease_check function with drm_lease_held.
Changes in v3, some suggested by Dave Airlie <airlied@gmail.com>
* Add revocation. This allows leases to be effectively revoked by
removing all of the objects they have access to. The lease itself
hangs around as it's hanging off a file.
* Free the leases IDR when the master is destroyed
* _drm_lease_held should look at lessees, not lessor
* Allow non-master files to check for lease status
Changes in v4, suggested by Dave Airlie <airlied@gmail.com>
* Formatting and whitespace changes
Signed-off-by: Keith Packard <keithp@keithp.com>
---
drivers/gpu/drm/Makefile | 2 +-
drivers/gpu/drm/drm_auth.c | 29 +++-
drivers/gpu/drm/drm_lease.c | 379 ++++++++++++++++++++++++++++++++++++++++++
include/drm/drm_auth.h | 20 +++
include/drm/drm_lease.h | 36 ++++
include/drm/drm_mode_object.h | 1 +
6 files changed, 465 insertions(+), 2 deletions(-)
create mode 100644 drivers/gpu/drm/drm_lease.c
create mode 100644 include/drm/drm_lease.h
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 24a066e1841c..3a47f5ae6f16 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -17,7 +17,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm_encoder.o drm_mode_object.o drm_property.o \
drm_plane.o drm_color_mgmt.o drm_print.o \
drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
- drm_syncobj.o
+ drm_syncobj.o drm_lease.o
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
drm-$(CONFIG_DRM_VM) += drm_vm.o
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index 7ff697389d74..541177c71d51 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -31,6 +31,7 @@
#include <drm/drmP.h>
#include "drm_internal.h"
#include "drm_legacy.h"
+#include <drm/drm_lease.h>
/**
* DOC: master and authentication
@@ -93,7 +94,7 @@ int drm_authmagic(struct drm_device *dev, void *data,
return file ? 0 : -EINVAL;
}
-static struct drm_master *drm_master_create(struct drm_device *dev)
+struct drm_master *drm_master_create(struct drm_device *dev)
{
struct drm_master *master;
@@ -107,6 +108,14 @@ static struct drm_master *drm_master_create(struct drm_device *dev)
idr_init(&master->magic_map);
master->dev = dev;
+ /* initialize the tree of output resource lessees */
+ master->lessor = NULL;
+ master->lessee_id = 0;
+ INIT_LIST_HEAD(&master->lessees);
+ INIT_LIST_HEAD(&master->lessee_list);
+ idr_init(&master->leases);
+ idr_init(&master->lessee_idr);
+
return master;
}
@@ -189,6 +198,12 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data,
goto out_unlock;
}
+ if (file_priv->master->lessor != NULL) {
+ DRM_DEBUG_LEASE("Attempt to set lessee %d as master\n", file_priv->master->lessee_id);
+ ret = -EINVAL;
+ goto out_unlock;
+ }
+
ret = drm_set_master(dev, file_priv, false);
out_unlock:
mutex_unlock(&dev->master_mutex);
@@ -270,6 +285,13 @@ void drm_master_release(struct drm_file *file_priv)
if (dev->master == file_priv->master)
drm_drop_master(dev, file_priv);
out:
+ if (file_priv->is_master) {
+ /* Revoke any leases held by this or lessees, but only if
+ * this is the "real" master
+ */
+ _drm_lease_revoke(master);
+ }
+
/* drop the master reference held by the file priv */
if (file_priv->master)
drm_master_put(&file_priv->master);
@@ -310,12 +332,17 @@ static void drm_master_destroy(struct kref *kref)
struct drm_master *master = container_of(kref, struct drm_master, refcount);
struct drm_device *dev = master->dev;
+ drm_lease_destroy(master);
+
if (dev->driver->master_destroy)
dev->driver->master_destroy(dev, master);
drm_legacy_master_rmmaps(dev, master);
idr_destroy(&master->magic_map);
+ idr_destroy(&master->leases);
+ idr_destroy(&master->lessee_idr);
+
kfree(master->unique);
kfree(master);
}
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
new file mode 100644
index 000000000000..2ac404264d75
--- /dev/null
+++ b/drivers/gpu/drm/drm_lease.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright © 2017 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#include <drm/drmP.h>
+#include "drm_internal.h"
+#include "drm_legacy.h"
+#include "drm_crtc_internal.h"
+#include <drm/drm_lease.h>
+#include <drm/drm_auth.h>
+#include <drm/drm_crtc_helper.h>
+
+#define drm_for_each_lessee(lessee, lessor) \
+ list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
+
+/**
+ * drm_lease_owner - return ancestor owner drm_master
+ * @master: drm_master somewhere within tree of lessees and lessors
+ *
+ * RETURN:
+ *
+ * drm_master at the top of the tree (i.e, with lessor NULL
+ */
+struct drm_master *drm_lease_owner(struct drm_master *master)
+{
+ while (master->lessor != NULL)
+ master = master->lessor;
+ return master;
+}
+EXPORT_SYMBOL(drm_lease_owner);
+
+/**
+ * _drm_find_lessee - find lessee by id
+ * @master: drm_master of lessor
+ * @id: lessee_id
+ *
+ * RETURN:
+ *
+ * drm_master of the lessee if valid, NULL otherwise
+ */
+
+static struct drm_master*
+_drm_find_lessee(struct drm_master *master, int lessee_id)
+{
+ return idr_find(&drm_lease_owner(master)->lessee_idr, lessee_id);
+}
+
+/**
+ * _drm_lease_held_master - check to see if an object is leased (or owned) by master
+ * @master: the master to check the lease status of
+ * @id: the id to check
+ *
+ * Checks if the specified master holds a lease on the object. Return
+ * value:
+ *
+ * true 'master' holds a lease on (or owns) the object
+ * false 'master' does not hold a lease.
+ */
+static int _drm_lease_held_master(struct drm_master *master, int id)
+{
+ lockdep_assert_held(&master->dev->mode_config.idr_mutex);
+ if (master->lessor)
+ return idr_find(&master->leases, id) != NULL;
+ return true;
+}
+
+/**
+ * _drm_has_leased - check to see if an object has been leased
+ * @master: the master to check the lease status of
+ * @id: the id to check
+ *
+ * Checks if any lessee of 'master' holds a lease on 'id'. Return
+ * value:
+ *
+ * true Some lessee holds a lease on the object.
+ * false No lessee has a lease on the object.
+ */
+static bool _drm_has_leased(struct drm_master *master, int id)
+{
+ struct drm_master *lessee;
+
+ drm_for_each_lessee(lessee, master)
+ if (_drm_lease_held_master(lessee, id))
+ return true;
+ return false;
+}
+
+/**
+ * _drm_lease_held - check drm_mode_object lease status (idr_mutex held)
+ * @master: the drm_master
+ * @id: the object id
+ *
+ * Checks if the specified master holds a lease on the object. Return
+ * value:
+ *
+ * true 'master' holds a lease on (or owns) the object
+ * false 'master' does not hold a lease.
+ */
+bool _drm_lease_held(struct drm_file *file_priv, int id)
+{
+ if (file_priv == NULL || file_priv->master == NULL)
+ return true;
+
+ return _drm_lease_held_master(file_priv->master, id);
+}
+EXPORT_SYMBOL(_drm_lease_held);
+
+/**
+ * drm_lease_held - check drm_mode_object lease status (idr_mutex not held)
+ * @master: the drm_master
+ * @id: the object id
+ *
+ * Checks if the specified master holds a lease on the object. Return
+ * value:
+ *
+ * true 'master' holds a lease on (or owns) the object
+ * false 'master' does not hold a lease.
+ */
+bool drm_lease_held(struct drm_file *file_priv, int id)
+{
+ struct drm_master *master;
+ bool ret;
+
+ if (file_priv == NULL || file_priv->master == NULL)
+ return true;
+
+ master = file_priv->master;
+ mutex_lock(&master->dev->mode_config.idr_mutex);
+ ret = _drm_lease_held_master(master, id);
+ mutex_unlock(&master->dev->mode_config.idr_mutex);
+ return ret;
+}
+EXPORT_SYMBOL(drm_lease_held);
+
+/**
+ * drm_lease_filter_crtcs - restricted crtc set to leased values
+ * @file_priv: requestor file
+ * @crtcs: bitmask of crtcs to check
+ *
+ * Reconstructs a crtc mask based on the crtcs which are visible
+ * through the specified file.
+ */
+uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs_in)
+{
+ struct drm_master *master;
+ struct drm_device *dev;
+ struct drm_crtc *crtc;
+ int count_in, count_out;
+ uint32_t crtcs_out = 0;
+
+ if (file_priv == NULL || file_priv->master == NULL)
+ return crtcs_in;
+
+ master = file_priv->master;
+ dev = master->dev;
+
+ count_in = count_out = 0;
+ mutex_lock(&master->dev->mode_config.idr_mutex);
+ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+ if (_drm_lease_held_master(master, crtc->base.id)) {
+ uint32_t mask_in = 1ul << count_in;
+ if ((crtcs_in & mask_in) != 0) {
+ uint32_t mask_out = 1ul << count_out;
+ crtcs_out |= mask_out;
+ }
+ count_out++;
+ }
+ count_in++;
+ }
+ mutex_unlock(&master->dev->mode_config.idr_mutex);
+ return crtcs_out;
+}
+EXPORT_SYMBOL(drm_lease_filter_crtcs);
+
+/**
+ * drm_lease_filter_encoders - restrict encoder set to leased values
+ * @file_priv: requestor file
+ * @encoders: bitmask of encoders to check
+ *
+ * Reconstructs an encoder mask based on the encoders which are
+ * visible through the specified file.
+ */
+uint32_t drm_lease_filter_encoders(struct drm_file *file_priv, uint32_t encoders_in)
+{
+ struct drm_master *master;
+ struct drm_device *dev;
+ struct drm_encoder *encoder;
+ int count_in, count_out;
+ uint32_t encoders_out = 0;
+
+ count_in = count_out = 0;
+ if (file_priv == NULL || file_priv->master == NULL)
+ return encoders_in;
+
+ master = file_priv->master;
+ dev = master->dev;
+
+ mutex_lock(&master->dev->mode_config.idr_mutex);
+ list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
+ if (_drm_lease_held_master(master, encoder->base.id)) {
+ uint32_t mask_in = 1ul << count_in;
+ if ((encoders_in & mask_in) != 0) {
+ uint32_t mask_out = 1ul << count_out;
+ encoders_out |= mask_out;
+ }
+ count_out++;
+ }
+ count_in++;
+ }
+ mutex_unlock(&master->dev->mode_config.idr_mutex);
+ return encoders_out;
+}
+EXPORT_SYMBOL(drm_lease_filter_encoders);
+
+/*
+ * drm_lease_create - create a new drm_master with leased objects
+ * @lessor: lease holder (or owner) of objects
+ * @leases: objects to lease to the new drm_master
+ *
+ * Uses drm_master_create to allocate a new drm_master, then checks to
+ * make sure all of the desired objects can be leased, atomically
+ * leasing them to the new drmmaster.
+ *
+ * ERR_PTR(-EACCESS) some other master holds the title to any object
+ * ERR_PTR(-ENOENT) some object is not a valid DRM object for this device
+ * ERR_PTR(-EBUSY) some other lessee holds title to this object
+ * ERR_PTR(-EEXIST) same object specified more than once in the provided list
+ * ERR_PTR(-ENOMEM) allocation failed
+ */
+static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr *leases)
+{
+ struct drm_device *dev = lessor->dev;
+ int error;
+ struct drm_master *lessee;
+ int object;
+ int id;
+ void *entry;
+
+ DRM_DEBUG_LEASE("lessor %d\n", lessor->lessee_id);
+
+ lockdep_assert_held(&lessor->dev->master_mutex);
+
+ lessee = drm_master_create(lessor->dev);
+ if (!lessee) {
+ DRM_DEBUG_LEASE("drm_master_create failed\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* Insert the new lessee into the tree */
+ id = idr_alloc(&(drm_lease_owner(lessor)->lessee_idr), lessee, 1, 0, GFP_KERNEL);
+ if (id < 0) {
+ error = id;
+ goto out_lessee;
+ }
+
+ lessee->lessee_id = id;
+ lessee->lessor = drm_master_get(lessor);
+ list_add_tail(&lessee->lessee_list, &lessor->lessees);
+
+ /* Lock the mode object mutex to make the check and allocation atomic */
+ mutex_lock(&lessor->dev->mode_config.idr_mutex);
+ idr_for_each_entry(leases, entry, object) {
+ error = 0;
+ if (!idr_find(&dev->mode_config.crtc_idr, object))
+ error = -ENOENT;
+ else if (!_drm_lease_held_master(lessor, object))
+ error = -EACCES;
+ else if (_drm_has_leased(lessor, object))
+ error = -EBUSY;
+
+ if (error != 0) {
+ DRM_DEBUG_LEASE("object %d failed %d\n", object, error);
+ goto out_unlock;
+ }
+ }
+
+ /* Move the leases over */
+ lessee->leases = *leases;
+ mutex_unlock(&lessor->dev->mode_config.idr_mutex);
+ DRM_DEBUG_LEASE("new lessee %d %p, lessor %d %p\n", lessee->lessee_id, lessee, lessor->lessee_id, lessor);
+ return lessee;
+
+out_unlock:
+ mutex_unlock(&lessor->dev->mode_config.idr_mutex);
+
+out_lessee:
+ drm_master_put(&lessee);
+ return ERR_PTR(error);
+}
+
+/**
+ * drm_lease_destroy - a master is going away
+ * @master: the drm_master being destroyed
+ *
+ * All lessees will have been destroyed as they
+ * hold a reference on their lessor. Notify any
+ * lessor for this master so that it can check
+ * the list of lessees.
+ */
+void drm_lease_destroy(struct drm_master *master)
+{
+ struct drm_device *dev = master->dev;
+
+ lockdep_assert_held(&dev->master_mutex);
+
+ DRM_DEBUG_LEASE("drm_lease_destroy %d\n", master->lessee_id);
+
+ /* This master is referenced by all lessees, hence it cannot be destroyed
+ * until all of them have been
+ */
+ WARN_ON(!list_empty(&master->lessees));
+
+ /* Remove this master from the lessee idr in the owner */
+ if (master->lessee_id != 0) {
+ DRM_DEBUG_LEASE("remove master %d from device list of lessees\n", master->lessee_id);
+ idr_remove(&(drm_lease_owner(master)->lessee_idr), master->lessee_id);
+ }
+
+ /* Remove this master from any lessee list it may be on */
+ list_del(&master->lessee_list);
+ if (master->lessor) {
+ /* Tell the master to check the lessee list */
+ drm_sysfs_hotplug_event(dev);
+ drm_master_put(&master->lessor);
+ }
+
+ DRM_DEBUG_LEASE("drm_lease_destroy done %d\n", master->lessee_id);
+}
+
+/**
+ * _drm_lease_revoke - revoke access to all leased objects
+ * @master: the master losing its lease
+ */
+
+void _drm_lease_revoke(struct drm_master *top)
+{
+ int object;
+ void *entry;
+ struct drm_master *master = top;
+
+ /*
+ * Walk the tree starting at 'top' emptying all leases. Because
+ * the tree is fully connected, we can do this without recursing
+ */
+ for (;;) {
+ DRM_DEBUG_LEASE("revoke leases for %p %d\n", master, master->lessee_id);
+
+ /* Evacuate the lease */
+ idr_for_each_entry(&master->leases, entry, object)
+ idr_remove(&master->leases, object);
+
+ /* Depth-first list walk */
+
+ /* Down */
+ if (!list_empty(&master->lessees)) {
+ master = list_first_entry(&master->lessees, struct drm_master, lessee_list);
+ } else {
+ /* Up */
+ while (master != top && master == list_last_entry(&master->lessor->lessees, struct drm_master, lessee_list))
+ master = master->lessor;
+
+ if (master == top)
+ break;
+
+ /* Over */
+ master = list_entry(master->lessee_list.next, struct drm_master, lessee_list);
+ }
+ }
+}
diff --git a/include/drm/drm_auth.h b/include/drm/drm_auth.h
index 81a40c2a9a3e..4b7fc22d3fc9 100644
--- a/include/drm/drm_auth.h
+++ b/include/drm/drm_auth.h
@@ -52,6 +52,12 @@ struct drm_lock_data {
* @dev: Link back to the DRM device
* @lock: DRI1 lock information.
* @driver_priv: Pointer to driver-private information.
+ * @lessor: Lease holder
+ * @lessee_id: id for lessees. Owners always have id 0
+ * @lessee_list: other lessees of the same master
+ * @lessees: drm_masters leasing from this one
+ * @leases: Objects leased to this drm_master.
+ * @lessee_idr: All lessees under this owner (only used where lessor == NULL)
*
* Note that master structures are only relevant for the legacy/primary device
* nodes, hence there can only be one per device, not one per drm_minor.
@@ -76,10 +82,24 @@ struct drm_master {
struct idr magic_map;
struct drm_lock_data lock;
void *driver_priv;
+
+ /* Tree of display resource leases, each of which is a drm_master struct
+ * All of these get activated simultaneously, so drm_device master points
+ * at the top of the tree (for which lessor is NULL)
+ */
+
+ struct drm_master *lessor;
+ int lessee_id;
+ struct list_head lessee_list;
+ struct list_head lessees;
+ struct idr leases;
+ struct idr lessee_idr;
};
struct drm_master *drm_master_get(struct drm_master *master);
void drm_master_put(struct drm_master **master);
bool drm_is_current_master(struct drm_file *fpriv);
+struct drm_master *drm_master_create(struct drm_device *dev);
+
#endif
diff --git a/include/drm/drm_lease.h b/include/drm/drm_lease.h
new file mode 100644
index 000000000000..a49667db1d6d
--- /dev/null
+++ b/include/drm/drm_lease.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright © 2017 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef _DRM_LEASE_H_
+#define _DRM_LEASE_H_
+
+struct drm_file;
+struct drm_device;
+struct drm_master;
+
+struct drm_master *drm_lease_owner(struct drm_master *master);
+
+void drm_lease_destroy(struct drm_master *lessee);
+
+bool drm_lease_held(struct drm_file *file_priv, int id);
+
+bool _drm_lease_held(struct drm_file *file_priv, int id);
+
+void _drm_lease_revoke(struct drm_master *master);
+
+uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs);
+
+uint32_t drm_lease_filter_encoders(struct drm_file *file_priv, uint32_t encoders);
+
+#endif /* _DRM_LEASE_H_ */
diff --git a/include/drm/drm_mode_object.h b/include/drm/drm_mode_object.h
index b2f920b518e3..c8155cb5a932 100644
--- a/include/drm/drm_mode_object.h
+++ b/include/drm/drm_mode_object.h
@@ -24,6 +24,7 @@
#define __DRM_MODESET_H__
#include <linux/kref.h>
+#include <drm/drm_lease.h>
struct drm_object_properties;
struct drm_property;
struct drm_device;
--
2.13.3
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH 6/6] drm: Add four ioctls for managing drm mode object leases [v4]
From: Keith Packard @ 2017-10-05 6:13 UTC (permalink / raw)
To: linux-kernel, Dave Airlie, Daniel Vetter; +Cc: Keith Packard, dri-devel
In-Reply-To: <20171005061310.29919-1-keithp@keithp.com>
drm_mode_create_lease
Creates a lease for a list of drm mode objects, returning an
fd for the new drm_master and a 64-bit identifier for the lessee
drm_mode_list_lesees
List the identifiers of the lessees for a master file
drm_mode_get_lease
List the leased objects for a master file
drm_mode_revoke_lease
Erase the set of objects managed by a lease.
This should suffice to at least create and query leases.
Changes for v2 as suggested by Daniel Vetter <daniel.vetter@ffwll.ch>:
* query ioctls only query the master associated with
the provided file.
* 'mask_lease' value has been removed
* change ioctl has been removed.
Changes for v3 suggested in part by Dave Airlie <airlied@gmail.com>
* Add revoke ioctl.
Changes for v3 suggested by Dave Airlie <airlied@gmail.com>
* Expand on the comment about the magic use of &drm_lease_idr_object
* Pad lease ioctl structures to align on 64-bit boundaries
Signed-off-by: Keith Packard <keithp@keithp.com>
---
drivers/gpu/drm/drm_ioctl.c | 4 +
drivers/gpu/drm/drm_lease.c | 277 ++++++++++++++++++++++++++++++++++++++++++++
include/drm/drm_lease.h | 12 ++
include/uapi/drm/drm.h | 5 +
include/uapi/drm/drm_mode.h | 66 +++++++++++
5 files changed, 364 insertions(+)
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 7d0e481c5729..3ed76220b4b1 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -657,6 +657,10 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_UNLOCKED|DRM_RENDER_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, drm_syncobj_fd_to_handle_ioctl,
DRM_UNLOCKED|DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_LEASE, drm_mode_create_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_LIST_LESSEES, drm_mode_list_lessees_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GET_LEASE, drm_mode_get_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
};
#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c
index 2ac404264d75..e885ea76de8f 100644
--- a/drivers/gpu/drm/drm_lease.c
+++ b/drivers/gpu/drm/drm_lease.c
@@ -23,6 +23,8 @@
#define drm_for_each_lessee(lessee, lessor) \
list_for_each_entry((lessee), &(lessor)->lessees, lessee_list)
+static uint64_t drm_lease_idr_object;
+
/**
* drm_lease_owner - return ancestor owner drm_master
* @master: drm_master somewhere within tree of lessees and lessors
@@ -377,3 +379,278 @@ void _drm_lease_revoke(struct drm_master *top)
}
}
}
+
+/**
+ * drm_mode_create_lease_ioctl - create a new lease
+ * @dev: the drm device
+ * @data: pointer to struct drm_mode_create_lease
+ * @file_priv: the file being manipulated
+ *
+ * The master associated with the specified file will have a lease
+ * created containing the objects specified in the ioctl structure.
+ * A file descriptor will be allocated for that and returned to the
+ * application.
+ */
+int drm_mode_create_lease_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *lessor_priv)
+{
+ struct drm_mode_create_lease *cl = data;
+ size_t object_count;
+ size_t o;
+ int ret = 0;
+ struct idr leases;
+ struct drm_master *lessor = lessor_priv->master;
+ struct drm_master *lessee = NULL;
+ struct file *lessee_file = NULL;
+ struct file *lessor_file = lessor_priv->filp;
+ struct drm_file *lessee_priv;
+ int fd = -1;
+
+ /* Do not allow sub-leases */
+ if (lessor->lessor)
+ return -EINVAL;
+
+ object_count = cl->object_count;
+ idr_init(&leases);
+
+ /* Allocate a file descriptor for the lease */
+ fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK));
+
+ DRM_DEBUG_LEASE("Creating new lease\n");
+
+ /* Lookup the mode objects and add their IDs to the lease request */
+ for (o = 0; o < object_count; o++) {
+ __u32 object_id;
+
+ if (copy_from_user(&object_id,
+ u64_to_user_ptr(cl->object_ids) + o * sizeof (__u32),
+ sizeof (__u32))) {
+ ret = -EFAULT;
+ goto out_leases;
+ }
+ DRM_DEBUG_LEASE("Adding object %d to lease\n", object_id);
+
+ /*
+ * We're using an IDR to hold the set of leased
+ * objects, but we don't need to point at the object's
+ * data structure from the lease as the main crtc_idr
+ * will be used to actually find that. Instead, all we
+ * really want is a 'leased/not-leased' result, for
+ * which any non-NULL pointer will work fine.
+ */
+ ret = idr_alloc(&leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL);
+ if (ret < 0) {
+ DRM_DEBUG_LEASE("Object %d cannot be inserted into leases (%d)\n",
+ object_id, ret);
+ goto out_leases;
+ }
+ }
+
+ mutex_lock(&dev->master_mutex);
+
+ DRM_DEBUG_LEASE("Creating lease\n");
+ lessee = drm_lease_create(lessor, &leases);
+
+ if (IS_ERR(lessee)) {
+ ret = PTR_ERR(lessee);
+ mutex_unlock(&dev->master_mutex);
+ goto out_leases;
+ }
+
+ /* Clone the lessor file to create a new file for us */
+ DRM_DEBUG_LEASE("Allocating lease file\n");
+ path_get(&lessor_file->f_path);
+ lessee_file = alloc_file(&lessor_file->f_path,
+ lessor_file->f_mode,
+ fops_get(lessor_file->f_inode->i_fop));
+ mutex_unlock(&dev->master_mutex);
+
+ if (IS_ERR(lessee_file)) {
+ ret = PTR_ERR(lessee_file);
+ goto out_lessee;
+ }
+
+ /* Initialize the new file for DRM */
+ DRM_DEBUG_LEASE("Initializing the file with %p\n", lessee_file->f_op->open);
+ ret = lessee_file->f_op->open(lessee_file->f_inode, lessee_file);
+ if (ret)
+ goto out_lessee_file;
+
+ lessee_priv = lessee_file->private_data;
+
+ /* Change the file to a master one */
+ drm_master_put(&lessee_priv->master);
+ lessee_priv->master = lessee;
+ lessee_priv->is_master = 1;
+ lessee_priv->authenticated = 1;
+
+ /* Hook up the fd */
+ fd_install(fd, lessee_file);
+
+ /* Pass fd back to userspace */
+ DRM_DEBUG_LEASE("Returning fd %d id %d\n", fd, lessee->lessee_id);
+ cl->fd = fd;
+ cl->lessee_id = lessee->lessee_id;
+
+ DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n");
+ return 0;
+
+out_lessee_file:
+ fput(lessee_file);
+
+out_lessee:
+ drm_master_put(&lessee);
+
+out_leases:
+ idr_destroy(&leases);
+ put_unused_fd(fd);
+
+ DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl failed: %d\n", ret);
+ return ret;
+}
+
+/**
+ * drm_mode_list_lessees_ioctl - list lessee ids
+ * @dev: the drm device
+ * @data: pointer to struct drm_mode_list_lessees
+ * @lessor_priv: the file being manipulated
+ *
+ * Starting from the master associated with the specified file,
+ * the master with the provided lessee_id is found, and then
+ * an array of lessee ids associated with leases from that master
+ * are returned.
+ */
+
+int drm_mode_list_lessees_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *lessor_priv)
+{
+ struct drm_mode_list_lessees *arg = data;
+ __u32 __user *lessee_ids = (__u32 __user *) (uintptr_t) (arg->lessees_ptr);
+ __u32 count_lessees = arg->count_lessees;
+ struct drm_master *lessor = lessor_priv->master, *lessee;
+ int count;
+ int ret = 0;
+
+ DRM_DEBUG_LEASE("List lessees for %d\n", lessor->lessee_id);
+
+ mutex_lock(&dev->master_mutex);
+
+ count = 0;
+ drm_for_each_lessee(lessee, lessor) {
+ /* Only list un-revoked leases */
+ if (!idr_is_empty(&lessee->leases)) {
+ if (count_lessees > count) {
+ DRM_DEBUG_LEASE("Add lessee %d\n", lessee->lessee_id);
+ ret = put_user(lessee->lessee_id, lessee_ids + count);
+ if (ret)
+ break;
+ }
+ count++;
+ }
+ }
+
+ DRM_DEBUG_LEASE("Lessor leases to %d\n", count);
+ if (ret == 0)
+ arg->count_lessees = count;
+
+ mutex_unlock(&dev->master_mutex);
+
+ return ret;
+}
+
+/**
+ * drm_mode_get_lease_ioctl - list leased objects
+ * @dev: the drm device
+ * @data: pointer to struct drm_mode_get_lease
+ * @file_priv: the file being manipulated
+ *
+ * Return the list of leased objects for the specified lessee
+ */
+
+int drm_mode_get_lease_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *lessee_priv)
+{
+ struct drm_mode_get_lease *arg = data;
+ __u32 __user *object_ids = (__u32 __user *) (uintptr_t) (arg->objects_ptr);
+ __u32 count_objects = arg->count_objects;
+ struct drm_master *lessee = lessee_priv->master;
+ struct idr *object_idr;
+ int count;
+ void *entry;
+ int object;
+ int ret = 0;
+
+ DRM_DEBUG_LEASE("get lease for %d\n", lessee->lessee_id);
+
+ mutex_lock(&dev->master_mutex);
+
+ if (lessee->lessor == NULL)
+ /* owner can use all objects */
+ object_idr = &lessee->dev->mode_config.crtc_idr;
+ else
+ /* lessee can only use allowed object */
+ object_idr = &lessee->leases;
+
+ count = 0;
+ idr_for_each_entry(object_idr, entry, object) {
+ if (count_objects > count) {
+ DRM_DEBUG_LEASE("adding object %d\n", object);
+ ret = put_user(object, object_ids + count);
+ if (ret)
+ break;
+ }
+ count++;
+ }
+
+ DRM_DEBUG("lease holds %d objects\n", count);
+ if (ret == 0)
+ arg->count_objects = count;
+
+ mutex_unlock(&dev->master_mutex);
+
+ return ret;
+}
+
+/**
+ * drm_mode_revoke_lease_ioctl - revoke lease
+ * @dev: the drm device
+ * @data: pointer to struct drm_mode_revoke_lease
+ * @file_priv: the file being manipulated
+ *
+ * This removes all of the objects from the lease without
+ * actually getting rid of the lease itself; that way all
+ * references to it still work correctly
+ */
+int drm_mode_revoke_lease_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *lessor_priv)
+{
+ struct drm_mode_revoke_lease *arg = data;
+ struct drm_master *lessor = lessor_priv->master;
+ struct drm_master *lessee;
+ int ret = 0;
+
+ DRM_DEBUG_LEASE("revoke lease for %d\n", arg->lessee_id);
+
+ mutex_lock(&dev->master_mutex);
+
+ lessee = _drm_find_lessee(lessor, arg->lessee_id);
+
+ /* No such lessee */
+ if (!lessee) {
+ ret = -ENOENT;
+ goto fail;
+ }
+
+ /* Lease is not held by lessor */
+ if (lessee->lessor != lessor) {
+ ret = -EACCES;
+ goto fail;
+ }
+
+ _drm_lease_revoke(lessee);
+
+fail:
+ mutex_unlock(&dev->master_mutex);
+
+ return ret;
+}
diff --git a/include/drm/drm_lease.h b/include/drm/drm_lease.h
index a49667db1d6d..53ffcee2617e 100644
--- a/include/drm/drm_lease.h
+++ b/include/drm/drm_lease.h
@@ -33,4 +33,16 @@ uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs);
uint32_t drm_lease_filter_encoders(struct drm_file *file_priv, uint32_t encoders);
+int drm_mode_create_lease_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
+
+int drm_mode_list_lessees_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
+
+int drm_mode_get_lease_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
+
+int drm_mode_revoke_lease_ioctl(struct drm_device *dev,
+ void *data, struct drm_file *file_priv);
+
#endif /* _DRM_LEASE_H_ */
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index 101593ab10ac..dd350bf0ad75 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -841,6 +841,11 @@ extern "C" {
#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle)
#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle)
+#define DRM_IOCTL_MODE_CREATE_LEASE DRM_IOWR(0xC3, struct drm_mode_create_lease)
+#define DRM_IOCTL_MODE_LIST_LESSEES DRM_IOWR(0xC4, struct drm_mode_list_lessees)
+#define DRM_IOCTL_MODE_GET_LEASE DRM_IOWR(0xC5, struct drm_mode_get_lease)
+#define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC6, struct drm_mode_revoke_lease)
+
/**
* 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 403339f98a92..5964f25fa88e 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -732,6 +732,72 @@ struct drm_mode_destroy_blob {
__u32 blob_id;
};
+/**
+ * Lease mode resources, creating another drm_master.
+ */
+struct drm_mode_create_lease {
+ /** Pointer to array of object ids (__u32) */
+ __u64 object_ids;
+ /** Number of object ids */
+ __u32 object_count;
+ /** flags for new FD (O_CLOEXEC, etc) */
+ __u32 flags;
+
+ /** Return: unique identifier for lessee. */
+ __u32 lessee_id;
+ /** Return: file descriptor to new drm_master file */
+ __u32 fd;
+};
+
+/**
+ * List lesses from a drm_master
+ */
+struct drm_mode_list_lessees {
+ /** Number of lessees.
+ * On input, provides length of the array.
+ * On output, provides total number. No
+ * more than the input number will be written
+ * back, so two calls can be used to get
+ * the size and then the data.
+ */
+ __u32 count_lessees;
+ __u32 pad;
+
+ /** Pointer to lessees.
+ * pointer to __u64 array of lessee ids
+ */
+ __u64 lessees_ptr;
+};
+
+/**
+ * Get leased objects
+ */
+struct drm_mode_get_lease {
+ /** Number of leased objects.
+ * On input, provides length of the array.
+ * On output, provides total number. No
+ * more than the input number will be written
+ * back, so two calls can be used to get
+ * the size and then the data.
+ */
+ __u32 count_objects;
+ __u32 pad;
+
+ /** Pointer to objects.
+ * pointer to __u32 array of object ids
+ */
+ __u64 objects_ptr;
+};
+
+/**
+ * Revoke lease
+ */
+struct drm_mode_revoke_lease {
+ /** Unique ID of lessee
+ */
+ __u32 lessee_id;
+};
+
#if defined(__cplusplus)
}
#endif
--
2.13.3
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH 1/6] drm: Pass struct drm_file * to __drm_mode_object_find
From: Keith Packard @ 2017-10-05 6:13 UTC (permalink / raw)
To: linux-kernel, Dave Airlie, Daniel Vetter; +Cc: Keith Packard, dri-devel
In-Reply-To: <20171005061310.29919-1-keithp@keithp.com>
This will allow __drm_mode_object_file to be extended to perform
access control checks based on the file in use.
Suggested-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Keith Packard <keithp@keithp.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c | 16 ++++++++--------
drivers/gpu/drm/amd/amdgpu/dce_virtual.c | 4 ++--
drivers/gpu/drm/ast/ast_mode.c | 2 +-
drivers/gpu/drm/bochs/bochs_kms.c | 2 +-
drivers/gpu/drm/cirrus/cirrus_mode.c | 2 +-
drivers/gpu/drm/drm_atomic.c | 8 ++++----
drivers/gpu/drm/drm_atomic_helper.c | 2 +-
drivers/gpu/drm/drm_color_mgmt.c | 4 ++--
drivers/gpu/drm/drm_connector.c | 2 +-
drivers/gpu/drm/drm_crtc.c | 8 ++++----
drivers/gpu/drm/drm_crtc_internal.h | 1 +
drivers/gpu/drm/drm_encoder.c | 2 +-
drivers/gpu/drm/drm_framebuffer.c | 9 +++++----
drivers/gpu/drm/drm_mode_object.c | 10 ++++++----
drivers/gpu/drm/drm_plane.c | 14 +++++++-------
drivers/gpu/drm/drm_probe_helper.c | 2 +-
drivers/gpu/drm/drm_property.c | 6 +++---
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 2 +-
drivers/gpu/drm/i915/intel_display.c | 2 +-
drivers/gpu/drm/i915/intel_overlay.c | 2 +-
drivers/gpu/drm/i915/intel_sprite.c | 2 +-
drivers/gpu/drm/mgag200/mgag200_mode.c | 2 +-
drivers/gpu/drm/nouveau/nouveau_connector.c | 4 ++--
drivers/gpu/drm/radeon/r100.c | 2 +-
drivers/gpu/drm/radeon/r600_cs.c | 2 +-
drivers/gpu/drm/radeon/radeon_connectors.c | 16 ++++++++--------
drivers/gpu/drm/udl/udl_connector.c | 2 +-
drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 4 ++--
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 2 +-
include/drm/drm_connector.h | 3 ++-
include/drm/drm_crtc.h | 5 +++--
include/drm/drm_encoder.h | 3 ++-
include/drm/drm_framebuffer.h | 1 +
include/drm/drm_mode_object.h | 2 ++
include/drm/drm_plane.h | 3 ++-
include/drm/drm_property.h | 3 ++-
36 files changed, 84 insertions(+), 72 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
index 8d1cf2d3e663..a6c17353e57d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c
@@ -231,7 +231,7 @@ amdgpu_connector_update_scratch_regs(struct drm_connector *connector,
if (connector->encoder_ids[i] == 0)
break;
- encoder = drm_encoder_find(connector->dev,
+ encoder = drm_encoder_find(connector->dev, NULL,
connector->encoder_ids[i]);
if (!encoder)
continue;
@@ -256,7 +256,7 @@ amdgpu_connector_find_encoder(struct drm_connector *connector,
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
if (connector->encoder_ids[i] == 0)
break;
- encoder = drm_encoder_find(connector->dev,
+ encoder = drm_encoder_find(connector->dev, NULL,
connector->encoder_ids[i]);
if (!encoder)
continue;
@@ -374,7 +374,7 @@ amdgpu_connector_best_single_encoder(struct drm_connector *connector)
/* pick the encoder ids */
if (enc_id)
- return drm_encoder_find(connector->dev, enc_id);
+ return drm_encoder_find(connector->dev, NULL, enc_id);
return NULL;
}
@@ -1079,7 +1079,7 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force)
if (connector->encoder_ids[i] == 0)
break;
- encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+ encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]);
if (!encoder)
continue;
@@ -1136,7 +1136,7 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector)
if (connector->encoder_ids[i] == 0)
break;
- encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+ encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]);
if (!encoder)
continue;
@@ -1155,7 +1155,7 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector)
/* then check use digitial */
/* pick the first one */
if (enc_id)
- return drm_encoder_find(connector->dev, enc_id);
+ return drm_encoder_find(connector->dev, NULL, enc_id);
return NULL;
}
@@ -1296,7 +1296,7 @@ u16 amdgpu_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn
if (connector->encoder_ids[i] == 0)
break;
- encoder = drm_encoder_find(connector->dev,
+ encoder = drm_encoder_find(connector->dev, NULL,
connector->encoder_ids[i]);
if (!encoder)
continue;
@@ -1325,7 +1325,7 @@ static bool amdgpu_connector_encoder_is_hbr2(struct drm_connector *connector)
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
if (connector->encoder_ids[i] == 0)
break;
- encoder = drm_encoder_find(connector->dev,
+ encoder = drm_encoder_find(connector->dev, NULL,
connector->encoder_ids[i]);
if (!encoder)
continue;
diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
index 0d2f060206dc..89382ee3c401 100644
--- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
+++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c
@@ -311,7 +311,7 @@ dce_virtual_encoder(struct drm_connector *connector)
if (connector->encoder_ids[i] == 0)
break;
- encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+ encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]);
if (!encoder)
continue;
@@ -321,7 +321,7 @@ dce_virtual_encoder(struct drm_connector *connector)
/* pick the first one */
if (enc_id)
- return drm_encoder_find(connector->dev, enc_id);
+ return drm_encoder_find(connector->dev, NULL, enc_id);
return NULL;
}
diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c
index 3549a3356afe..987a89c21506 100644
--- a/drivers/gpu/drm/ast/ast_mode.c
+++ b/drivers/gpu/drm/ast/ast_mode.c
@@ -727,7 +727,7 @@ static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connect
int enc_id = connector->encoder_ids[0];
/* pick the encoder ids */
if (enc_id)
- return drm_encoder_find(connector->dev, enc_id);
+ return drm_encoder_find(connector->dev, NULL, enc_id);
return NULL;
}
diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c
index 6a91e62da2f4..a24a18fbd65a 100644
--- a/drivers/gpu/drm/bochs/bochs_kms.c
+++ b/drivers/gpu/drm/bochs/bochs_kms.c
@@ -213,7 +213,7 @@ bochs_connector_best_encoder(struct drm_connector *connector)
int enc_id = connector->encoder_ids[0];
/* pick the encoder ids */
if (enc_id)
- return drm_encoder_find(connector->dev, enc_id);
+ return drm_encoder_find(connector->dev, NULL, enc_id);
return NULL;
}
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
index 53f6f0f84206..74d63b874443 100644
--- a/drivers/gpu/drm/cirrus/cirrus_mode.c
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -496,7 +496,7 @@ static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
int enc_id = connector->encoder_ids[0];
/* pick the encoder ids */
if (enc_id)
- return drm_encoder_find(connector->dev, enc_id);
+ return drm_encoder_find(connector->dev, NULL, enc_id);
return NULL;
}
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 01192dd3ed79..e92343b677b0 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -721,7 +721,7 @@ int drm_atomic_plane_set_property(struct drm_plane *plane,
struct drm_mode_config *config = &dev->mode_config;
if (property == config->prop_fb_id) {
- struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, val);
+ struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val);
drm_atomic_set_fb_for_plane(state, fb);
if (fb)
drm_framebuffer_put(fb);
@@ -737,7 +737,7 @@ int drm_atomic_plane_set_property(struct drm_plane *plane,
return -EINVAL;
} else if (property == config->prop_crtc_id) {
- struct drm_crtc *crtc = drm_crtc_find(dev, val);
+ struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
return drm_atomic_set_crtc_for_plane(state, crtc);
} else if (property == config->prop_crtc_x) {
state->crtc_x = U642I64(val);
@@ -1153,7 +1153,7 @@ int drm_atomic_connector_set_property(struct drm_connector *connector,
struct drm_mode_config *config = &dev->mode_config;
if (property == config->prop_crtc_id) {
- struct drm_crtc *crtc = drm_crtc_find(dev, val);
+ struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val);
return drm_atomic_set_crtc_for_connector(state, crtc);
} else if (property == config->dpms_property) {
/* setting DPMS property requires special handling, which
@@ -2240,7 +2240,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
goto out;
}
- obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY);
+ obj = drm_mode_object_find(dev, file_priv, obj_id, DRM_MODE_OBJECT_ANY);
if (!obj) {
ret = -ENOENT;
goto out;
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 41f9d47d2bf6..8ecf639881d6 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -3348,7 +3348,7 @@ struct drm_encoder *
drm_atomic_helper_best_encoder(struct drm_connector *connector)
{
WARN_ON(connector->encoder_ids[1]);
- return drm_encoder_find(connector->dev, connector->encoder_ids[0]);
+ return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
}
EXPORT_SYMBOL(drm_atomic_helper_best_encoder);
diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c
index fe0982708e95..0d002b045bd2 100644
--- a/drivers/gpu/drm/drm_color_mgmt.c
+++ b/drivers/gpu/drm/drm_color_mgmt.c
@@ -230,7 +230,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
- crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
+ crtc = drm_crtc_find(dev, file_priv, crtc_lut->crtc_id);
if (!crtc)
return -ENOENT;
@@ -308,7 +308,7 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
- crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
+ crtc = drm_crtc_find(dev, file_priv, crtc_lut->crtc_id);
if (!crtc)
return -ENOENT;
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 8072e6e4c62c..f8feb2bf142a 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1289,7 +1289,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
- connector = drm_connector_lookup(dev, out_resp->connector_id);
+ connector = drm_connector_lookup(dev, file_priv, out_resp->connector_id);
if (!connector)
return -ENOENT;
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 5af25ce5bf7c..5dd2d28dd221 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -402,7 +402,7 @@ int drm_mode_getcrtc(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
- crtc = drm_crtc_find(dev, crtc_resp->crtc_id);
+ crtc = drm_crtc_find(dev, file_priv, crtc_resp->crtc_id);
if (!crtc)
return -ENOENT;
@@ -569,7 +569,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000)
return -ERANGE;
- crtc = drm_crtc_find(dev, crtc_req->crtc_id);
+ crtc = drm_crtc_find(dev, file_priv, crtc_req->crtc_id);
if (!crtc) {
DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
return -ENOENT;
@@ -595,7 +595,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
/* Make refcounting symmetric with the lookup path. */
drm_framebuffer_get(fb);
} else {
- fb = drm_framebuffer_lookup(dev, crtc_req->fb_id);
+ fb = drm_framebuffer_lookup(dev, file_priv, crtc_req->fb_id);
if (!fb) {
DRM_DEBUG_KMS("Unknown FB ID%d\n",
crtc_req->fb_id);
@@ -680,7 +680,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
goto out;
}
- connector = drm_connector_lookup(dev, out_id);
+ connector = drm_connector_lookup(dev, file_priv, out_id);
if (!connector) {
DRM_DEBUG_KMS("Connector id %d unknown\n",
out_id);
diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h
index d077c5490041..140752f13bc1 100644
--- a/drivers/gpu/drm/drm_crtc_internal.h
+++ b/drivers/gpu/drm/drm_crtc_internal.h
@@ -106,6 +106,7 @@ int drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj,
void drm_mode_object_register(struct drm_device *dev,
struct drm_mode_object *obj);
struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
+ struct drm_file *file_priv,
uint32_t id, uint32_t type);
void drm_mode_object_unregister(struct drm_device *dev,
struct drm_mode_object *object);
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index 0708779840d2..43f644844b83 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -220,7 +220,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
- encoder = drm_encoder_find(dev, enc_resp->encoder_id);
+ encoder = drm_encoder_find(dev, file_priv, enc_resp->encoder_id);
if (!encoder)
return -ENOENT;
diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c
index af279844d7ce..2affe53f3fda 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -381,7 +381,7 @@ int drm_mode_rmfb(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
- fb = drm_framebuffer_lookup(dev, *id);
+ fb = drm_framebuffer_lookup(dev, file_priv, *id);
if (!fb)
return -ENOENT;
@@ -450,7 +450,7 @@ int drm_mode_getfb(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
- fb = drm_framebuffer_lookup(dev, r->fb_id);
+ fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id);
if (!fb)
return -ENOENT;
@@ -515,7 +515,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
- fb = drm_framebuffer_lookup(dev, r->fb_id);
+ fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id);
if (!fb)
return -ENOENT;
@@ -688,12 +688,13 @@ EXPORT_SYMBOL(drm_framebuffer_init);
* again, using drm_framebuffer_put().
*/
struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
+ struct drm_file *file_priv,
uint32_t id)
{
struct drm_mode_object *obj;
struct drm_framebuffer *fb = NULL;
- obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_FB);
+ obj = __drm_mode_object_find(dev, file_priv, id, DRM_MODE_OBJECT_FB);
if (obj)
fb = obj_to_fb(obj);
return fb;
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index da9a9adbcc98..ccc3a35d2de2 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -105,6 +105,7 @@ void drm_mode_object_unregister(struct drm_device *dev,
}
struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
+ struct drm_file *file_priv,
uint32_t id, uint32_t type)
{
struct drm_mode_object *obj = NULL;
@@ -127,7 +128,7 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
/**
* drm_mode_object_find - look up a drm object with static lifetime
- * @dev: drm device
+ * @file_priv: drm file
* @id: id of the mode object
* @type: type of the mode object
*
@@ -136,11 +137,12 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
* by callind drm_mode_object_put().
*/
struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
+ struct drm_file *file_priv,
uint32_t id, uint32_t type)
{
struct drm_mode_object *obj = NULL;
- obj = __drm_mode_object_find(dev, id, type);
+ obj = __drm_mode_object_find(dev, file_priv, id, type);
return obj;
}
EXPORT_SYMBOL(drm_mode_object_find);
@@ -347,7 +349,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data,
drm_modeset_lock_all(dev);
- obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
+ obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type);
if (!obj) {
ret = -ENOENT;
goto out;
@@ -395,7 +397,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
drm_modeset_lock_all(dev);
- arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type);
+ arg_obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type);
if (!arg_obj) {
ret = -ENOENT;
goto out;
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 5dc8c4350602..462c244498e2 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -395,7 +395,7 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
- plane = drm_plane_find(dev, plane_resp->plane_id);
+ plane = drm_plane_find(dev, file_priv, plane_resp->plane_id);
if (!plane)
return -ENOENT;
@@ -584,7 +584,7 @@ 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.
*/
- plane = drm_plane_find(dev, plane_req->plane_id);
+ plane = drm_plane_find(dev, file_priv, plane_req->plane_id);
if (!plane) {
DRM_DEBUG_KMS("Unknown plane ID %d\n",
plane_req->plane_id);
@@ -592,14 +592,14 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
}
if (plane_req->fb_id) {
- fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
+ fb = drm_framebuffer_lookup(dev, file_priv, plane_req->fb_id);
if (!fb) {
DRM_DEBUG_KMS("Unknown framebuffer ID %d\n",
plane_req->fb_id);
return -ENOENT;
}
- crtc = drm_crtc_find(dev, plane_req->crtc_id);
+ crtc = drm_crtc_find(dev, file_priv, plane_req->crtc_id);
if (!crtc) {
DRM_DEBUG_KMS("Unknown crtc ID %d\n",
plane_req->crtc_id);
@@ -709,7 +709,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
return -EINVAL;
- crtc = drm_crtc_find(dev, req->crtc_id);
+ crtc = drm_crtc_find(dev, file_priv, req->crtc_id);
if (!crtc) {
DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
return -ENOENT;
@@ -823,7 +823,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
return -EINVAL;
- crtc = drm_crtc_find(dev, page_flip->crtc_id);
+ crtc = drm_crtc_find(dev, file_priv, page_flip->crtc_id);
if (!crtc)
return -ENOENT;
@@ -884,7 +884,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
goto out;
}
- fb = drm_framebuffer_lookup(dev, page_flip->fb_id);
+ fb = drm_framebuffer_lookup(dev, file_priv, page_flip->fb_id);
if (!fb) {
ret = -ENOENT;
goto out;
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index 904966cde32b..bc71660a32de 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -99,7 +99,7 @@ drm_mode_validate_pipeline(struct drm_display_mode *mode,
/* Step 2: Validate against encoders and crtcs */
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
- struct drm_encoder *encoder = drm_encoder_find(dev, ids[i]);
+ struct drm_encoder *encoder = drm_encoder_find(dev, NULL, ids[i]);
struct drm_crtc *crtc;
if (!encoder)
diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
index bc5128203056..bae50e6b819d 100644
--- a/drivers/gpu/drm/drm_property.c
+++ b/drivers/gpu/drm/drm_property.c
@@ -450,7 +450,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
- property = drm_property_find(dev, out_resp->prop_id);
+ property = drm_property_find(dev, file_priv, out_resp->prop_id);
if (!property)
return -ENOENT;
@@ -634,7 +634,7 @@ struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev,
struct drm_mode_object *obj;
struct drm_property_blob *blob = NULL;
- obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB);
+ obj = __drm_mode_object_find(dev, NULL, id, DRM_MODE_OBJECT_BLOB);
if (obj)
blob = obj_to_blob(obj);
return blob;
@@ -897,7 +897,7 @@ bool drm_property_change_valid_get(struct drm_property *property,
if (value == 0)
return true;
- *ref = __drm_mode_object_find(property->dev, value,
+ *ref = __drm_mode_object_find(property->dev, NULL, value,
property->values[0]);
return *ref != NULL;
}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
index 12a18557c5fd..ffb7a731572e 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -36,7 +36,7 @@ static int hibmc_connector_mode_valid(struct drm_connector *connector,
static struct drm_encoder *
hibmc_connector_best_encoder(struct drm_connector *connector)
{
- return drm_encoder_find(connector->dev, connector->encoder_ids[0]);
+ return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]);
}
static const struct drm_connector_helper_funcs
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index e92fd14c06c7..4d687d87109a 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -14055,7 +14055,7 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
struct drm_crtc *drmmode_crtc;
struct intel_crtc *crtc;
- drmmode_crtc = drm_crtc_find(dev, pipe_from_crtc_id->crtc_id);
+ drmmode_crtc = drm_crtc_find(dev, file, pipe_from_crtc_id->crtc_id);
if (!drmmode_crtc)
return -ENOENT;
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index b96aed941b97..559fbbcf7504 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -1127,7 +1127,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data,
if (!params)
return -ENOMEM;
- drmmode_crtc = drm_crtc_find(dev, put_image_rec->crtc_id);
+ drmmode_crtc = drm_crtc_find(dev, file_priv, put_image_rec->crtc_id);
if (!drmmode_crtc) {
ret = -ENOENT;
goto out_free;
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 94f9a1332dbf..b80f371f930f 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -995,7 +995,7 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data,
set->flags & I915_SET_COLORKEY_DESTINATION)
return -EINVAL;
- plane = drm_plane_find(dev, set->plane_id);
+ plane = drm_plane_find(dev, file_priv, set->plane_id);
if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY)
return -ENOENT;
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
index f4b53588e071..18db47ce96c1 100644
--- a/drivers/gpu/drm/mgag200/mgag200_mode.c
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -1702,7 +1702,7 @@ static struct drm_encoder *mga_connector_best_encoder(struct drm_connector
int enc_id = connector->encoder_ids[0];
/* pick the encoder ids */
if (enc_id)
- return drm_encoder_find(connector->dev, enc_id);
+ return drm_encoder_find(connector->dev, NULL, enc_id);
return NULL;
}
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index 147b22163f9f..0f58758c701f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -373,7 +373,7 @@ find_encoder(struct drm_connector *connector, int type)
if (!id)
break;
- enc = drm_encoder_find(dev, id);
+ enc = drm_encoder_find(dev, NULL, id);
if (!enc)
continue;
nv_encoder = nouveau_encoder(enc);
@@ -441,7 +441,7 @@ nouveau_connector_ddc_detect(struct drm_connector *connector)
if (id == 0)
break;
- encoder = drm_encoder_find(dev, id);
+ encoder = drm_encoder_find(dev, NULL, id);
if (!encoder)
continue;
nv_encoder = nouveau_encoder(encoder);
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c
index c31e660e35db..7d39ed63e5be 100644
--- a/drivers/gpu/drm/radeon/r100.c
+++ b/drivers/gpu/drm/radeon/r100.c
@@ -1456,7 +1456,7 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)
header = radeon_get_ib_value(p, h_idx);
crtc_id = radeon_get_ib_value(p, h_idx + 5);
reg = R100_CP_PACKET0_GET_REG(header);
- crtc = drm_crtc_find(p->rdev->ddev, crtc_id);
+ crtc = drm_crtc_find(p->rdev->ddev, p->filp, crtc_id);
if (!crtc) {
DRM_ERROR("cannot find crtc %d\n", crtc_id);
return -ENOENT;
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index 97fd58e97043..c96b31950ca7 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -887,7 +887,7 @@ int r600_cs_common_vline_parse(struct radeon_cs_parser *p,
crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
reg = R600_CP_PACKET0_GET_REG(header);
- crtc = drm_crtc_find(p->rdev->ddev, crtc_id);
+ crtc = drm_crtc_find(p->rdev->ddev, p->filp, crtc_id);
if (!crtc) {
DRM_ERROR("cannot find crtc %d\n", crtc_id);
return -ENOENT;
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index 27affbde058c..5d4b6d46575e 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -263,7 +263,7 @@ radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c
if (connector->encoder_ids[i] == 0)
break;
- encoder = drm_encoder_find(connector->dev,
+ encoder = drm_encoder_find(connector->dev, NULL,
connector->encoder_ids[i]);
if (!encoder)
continue;
@@ -290,7 +290,7 @@ static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector,
if (connector->encoder_ids[i] == 0)
break;
- encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+ encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]);
if (!encoder)
continue;
@@ -404,7 +404,7 @@ static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *conn
int enc_id = connector->encoder_ids[0];
/* pick the encoder ids */
if (enc_id)
- return drm_encoder_find(connector->dev, enc_id);
+ return drm_encoder_find(connector->dev, NULL, enc_id);
return NULL;
}
@@ -1365,7 +1365,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
if (connector->encoder_ids[i] == 0)
break;
- encoder = drm_encoder_find(connector->dev,
+ encoder = drm_encoder_find(connector->dev, NULL,
connector->encoder_ids[i]);
if (!encoder)
continue;
@@ -1451,7 +1451,7 @@ static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
if (connector->encoder_ids[i] == 0)
break;
- encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+ encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]);
if (!encoder)
continue;
@@ -1470,7 +1470,7 @@ static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector)
/* then check use digitial */
/* pick the first one */
if (enc_id)
- return drm_encoder_find(connector->dev, enc_id);
+ return drm_encoder_find(connector->dev, NULL, enc_id);
return NULL;
}
@@ -1617,7 +1617,7 @@ u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn
if (connector->encoder_ids[i] == 0)
break;
- encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+ encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]);
if (!encoder)
continue;
@@ -1646,7 +1646,7 @@ static bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector)
if (connector->encoder_ids[i] == 0)
break;
- encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]);
+ encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]);
if (!encoder)
continue;
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
index d2f57c52f7db..59de243e5ffc 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
@@ -105,7 +105,7 @@ static struct drm_encoder*
udl_best_single_encoder(struct drm_connector *connector)
{
int enc_id = connector->encoder_ids[0];
- return drm_encoder_find(connector->dev, enc_id);
+ return drm_encoder_find(connector->dev, NULL, enc_id);
}
static int udl_connector_set_property(struct drm_connector *connector,
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
index 5ec24fd801cd..01be355525e4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c
@@ -286,7 +286,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data,
drm_modeset_lock_all(dev);
- fb = drm_framebuffer_lookup(dev, arg->fb_id);
+ fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id);
if (!fb) {
DRM_ERROR("Invalid framebuffer id.\n");
ret = -ENOENT;
@@ -369,7 +369,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data,
drm_modeset_lock_all(dev);
- fb = drm_framebuffer_lookup(dev, arg->fb_id);
+ fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id);
if (!fb) {
DRM_ERROR("Invalid framebuffer id.\n");
ret = -ENOENT;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index 620180df1303..cc1d4f575795 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -1693,7 +1693,7 @@ int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data,
return 0;
}
- crtc = drm_crtc_find(dev, arg->crtc_id);
+ crtc = drm_crtc_find(dev, file_priv, arg->crtc_id);
if (!crtc) {
ret = -ENOENT;
goto out;
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index 4bc088269d05..49bbaf320f46 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -935,10 +935,11 @@ static inline unsigned drm_connector_index(struct drm_connector *connector)
* add takes a reference to it.
*/
static inline struct drm_connector *drm_connector_lookup(struct drm_device *dev,
+ struct drm_file *file_priv,
uint32_t id)
{
struct drm_mode_object *mo;
- mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CONNECTOR);
+ mo = drm_mode_object_find(dev, file_priv, id, DRM_MODE_OBJECT_CONNECTOR);
return mo ? obj_to_connector(mo) : NULL;
}
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 3a911a64c257..6520e81fffcb 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -954,10 +954,11 @@ struct drm_crtc *drm_crtc_from_index(struct drm_device *dev, int idx);
* userspace interface should be done using &drm_property.
*/
static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
- uint32_t id)
+ struct drm_file *file_priv,
+ uint32_t id)
{
struct drm_mode_object *mo;
- mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CRTC);
+ mo = drm_mode_object_find(dev, file_priv, id, DRM_MODE_OBJECT_CRTC);
return mo ? obj_to_crtc(mo) : NULL;
}
diff --git a/include/drm/drm_encoder.h b/include/drm/drm_encoder.h
index 8d8245ec0181..86db0da8bdcb 100644
--- a/include/drm/drm_encoder.h
+++ b/include/drm/drm_encoder.h
@@ -214,11 +214,12 @@ static inline bool drm_encoder_crtc_ok(struct drm_encoder *encoder,
* drm_mode_object_find().
*/
static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
+ struct drm_file *file_priv,
uint32_t id)
{
struct drm_mode_object *mo;
- mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_ENCODER);
+ mo = drm_mode_object_find(dev, file_priv, id, DRM_MODE_OBJECT_ENCODER);
return mo ? obj_to_encoder(mo) : NULL;
}
diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h
index 5244f059d23a..a7719e0029bd 100644
--- a/include/drm/drm_framebuffer.h
+++ b/include/drm/drm_framebuffer.h
@@ -198,6 +198,7 @@ int drm_framebuffer_init(struct drm_device *dev,
struct drm_framebuffer *fb,
const struct drm_framebuffer_funcs *funcs);
struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
+ struct drm_file *file_priv,
uint32_t id);
void drm_framebuffer_remove(struct drm_framebuffer *fb);
void drm_framebuffer_cleanup(struct drm_framebuffer *fb);
diff --git a/include/drm/drm_mode_object.h b/include/drm/drm_mode_object.h
index a767b4a30a6d..b2f920b518e3 100644
--- a/include/drm/drm_mode_object.h
+++ b/include/drm/drm_mode_object.h
@@ -27,6 +27,7 @@
struct drm_object_properties;
struct drm_property;
struct drm_device;
+struct drm_file;
/**
* struct drm_mode_object - base structure for modeset objects
@@ -113,6 +114,7 @@ struct drm_object_properties {
}
struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
+ struct drm_file *file_priv,
uint32_t id, uint32_t type);
void drm_mode_object_get(struct drm_mode_object *obj);
void drm_mode_object_put(struct drm_mode_object *obj);
diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h
index 9ab3e7044812..4a7c93b00e4f 100644
--- a/include/drm/drm_plane.h
+++ b/include/drm/drm_plane.h
@@ -571,10 +571,11 @@ int drm_mode_plane_set_obj_prop(struct drm_plane *plane,
* drm_mode_object_find().
*/
static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
+ struct drm_file *file_priv,
uint32_t id)
{
struct drm_mode_object *mo;
- mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PLANE);
+ mo = drm_mode_object_find(dev, file_priv, id, DRM_MODE_OBJECT_PLANE);
return mo ? obj_to_plane(mo) : NULL;
}
diff --git a/include/drm/drm_property.h b/include/drm/drm_property.h
index 37355c623e6c..429d8218f740 100644
--- a/include/drm/drm_property.h
+++ b/include/drm/drm_property.h
@@ -312,10 +312,11 @@ drm_property_unreference_blob(struct drm_property_blob *blob)
* This function looks up the property object specified by id and returns it.
*/
static inline struct drm_property *drm_property_find(struct drm_device *dev,
+ struct drm_file *file_priv,
uint32_t id)
{
struct drm_mode_object *mo;
- mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY);
+ mo = drm_mode_object_find(dev, file_priv, id, DRM_MODE_OBJECT_PROPERTY);
return mo ? obj_to_property(mo) : NULL;
}
--
2.13.3
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [mdadm PATCH] Move mdadm_env.sh out of /usr/lib/systemd
From: NeilBrown @ 2017-10-05 6:13 UTC (permalink / raw)
To: Jes.Sorensen; +Cc: Linux Raid
[-- Attachment #1: Type: text/plain, Size: 2012 bytes --]
The systemd developers like to keep control of the
lib/systemd namespace, and haven't approved of the use
of lib/systemd/scripts. So we should stop using it.
Move the mdadm_env.sh script, optionally sourced by
mdmonitor.service, to a new directory /usr/lib/mdadm.
Signed-off-by: NeilBrown <neilb@suse.com>
---
Makefile | 3 ++-
systemd/mdmonitor.service | 2 +-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index 0977f27d3750..188a21801fcc 100644
--- a/Makefile
+++ b/Makefile
@@ -85,6 +85,7 @@ MDMON_DIR = $(RUN_DIR)
# place for autoreplace cookies
FAILED_SLOTS_DIR = $(RUN_DIR)/failed-slots
SYSTEMD_DIR=/lib/systemd/system
+LIB_DIR=/usr/libexec/mdadm
COROSYNC:=$(shell [ -d /usr/include/corosync ] || echo -DNO_COROSYNC)
DLM:=$(shell [ -f /usr/include/libdlm.h ] || echo -DNO_DLM)
@@ -280,7 +281,7 @@ install-systemd: systemd/mdmon@.service
$(INSTALL) -D -m 755 .install.tmp.3 $(DESTDIR)$(SYSTEMD_DIR)-shutdown/$$file ; \
rm -f .install.tmp.3; \
done
- if [ -f /etc/SuSE-release -o -n "$(SUSE)" ] ;then $(INSTALL) -D -m 755 systemd/SUSE-mdadm_env.sh $(DESTDIR)$(SYSTEMD_DIR)/../scripts/mdadm_env.sh ;fi
+ if [ -f /etc/SuSE-release -o -n "$(SUSE)" ] ;then $(INSTALL) -D -m 755 systemd/SUSE-mdadm_env.sh $(DESTDIR)$(LIB_DIR)/mdadm_env.sh ;fi
uninstall:
rm -f $(DESTDIR)$(MAN8DIR)/mdadm.8 $(DESTDIR)$(MAN8DIR)/mdmon.8 $(DESTDIR)$(MAN4DIR)/md.4 $(DESTDIR)$(MAN5DIR)/mdadm.conf.5 $(DESTDIR)$(BINDIR)/mdadm
diff --git a/systemd/mdmonitor.service b/systemd/mdmonitor.service
index c7cff3e497ec..46f7b8801354 100644
--- a/systemd/mdmonitor.service
+++ b/systemd/mdmonitor.service
@@ -12,5 +12,5 @@ DefaultDependencies=no
[Service]
Environment= MDADM_MONITOR_ARGS=--scan
EnvironmentFile=-/run/sysconfig/mdadm
-ExecStartPre=-/usr/lib/systemd/scripts/mdadm_env.sh
+ExecStartPre=-/usr/lib/mdadm/mdadm_env.sh
ExecStart=BINDIR/mdadm --monitor $MDADM_MONITOR_ARGS
--
2.14.0.rc0.dirty
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]
^ permalink raw reply related
* [PATCH 5/6] drm: Check mode object lease status in all master ioctl paths [v2]
From: Keith Packard @ 2017-10-05 6:13 UTC (permalink / raw)
To: linux-kernel, Dave Airlie, Daniel Vetter; +Cc: Keith Packard, dri-devel
In-Reply-To: <20171005061310.29919-1-keithp@keithp.com>
Attempts to modify un-leased objects are rejected with an error.
Information returned about unleased objects is modified to make them
appear unusable and/or disconnected.
Changes for v2 as suggested by Daniel Vetter <daniel.vetter@ffwll.ch>:
With the change in the __drm_mode_object_find API to pass the
file_priv along, we can now centralize most of the lease-based access
checks in that function.
A few places skip that API and require in-line checks.
Signed-off-by: Keith Packard <keithp@keithp.com>
---
drivers/gpu/drm/drm_auth.c | 2 +-
drivers/gpu/drm/drm_connector.c | 5 +++--
drivers/gpu/drm/drm_encoder.c | 8 +++++---
drivers/gpu/drm/drm_mode_config.c | 32 +++++++++++++++++++-------------
drivers/gpu/drm/drm_mode_object.c | 22 ++++++++++++++++++++++
drivers/gpu/drm/drm_plane.c | 8 +++++---
drivers/gpu/drm/drm_vblank.c | 18 ++++++++++++++++--
7 files changed, 71 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index 541177c71d51..bab26b477738 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -310,7 +310,7 @@ void drm_master_release(struct drm_file *file_priv)
*/
bool drm_is_current_master(struct drm_file *fpriv)
{
- return fpriv->is_master && fpriv->master == fpriv->minor->dev->master;
+ return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master;
}
EXPORT_SYMBOL(drm_is_current_master);
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index f8feb2bf142a..65ecdd954a69 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1294,7 +1294,8 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
return -ENOENT;
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
- if (connector->encoder_ids[i] != 0)
+ if (connector->encoder_ids[i] != 0 &&
+ drm_lease_held(file_priv, connector->encoder_ids[i]))
encoders_count++;
if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
@@ -1361,7 +1362,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
encoder = drm_connector_get_encoder(connector);
- if (encoder)
+ if (encoder && drm_lease_held(file_priv, encoder->base.id))
out_resp->encoder_id = encoder->base.id;
else
out_resp->encoder_id = 0;
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index 43f644844b83..6ad6416f2ede 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -226,7 +226,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
crtc = drm_encoder_get_crtc(encoder);
- if (crtc)
+ if (crtc && drm_lease_held(file_priv, crtc->base.id))
enc_resp->crtc_id = crtc->base.id;
else
enc_resp->crtc_id = 0;
@@ -234,8 +234,10 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
enc_resp->encoder_type = encoder->encoder_type;
enc_resp->encoder_id = encoder->base.id;
- enc_resp->possible_crtcs = encoder->possible_crtcs;
- enc_resp->possible_clones = encoder->possible_clones;
+ enc_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
+ encoder->possible_crtcs);
+ enc_resp->possible_clones = drm_lease_filter_encoders(file_priv,
+ encoder->possible_clones);
return 0;
}
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
index d9862259a2a7..f7ceee2ae340 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -122,20 +122,24 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
count = 0;
crtc_id = u64_to_user_ptr(card_res->crtc_id_ptr);
drm_for_each_crtc(crtc, dev) {
- if (count < card_res->count_crtcs &&
- put_user(crtc->base.id, crtc_id + count))
- return -EFAULT;
- count++;
+ if (drm_lease_held(file_priv, crtc->base.id)) {
+ if (count < card_res->count_crtcs &&
+ put_user(crtc->base.id, crtc_id + count))
+ return -EFAULT;
+ count++;
+ }
}
card_res->count_crtcs = count;
count = 0;
encoder_id = u64_to_user_ptr(card_res->encoder_id_ptr);
drm_for_each_encoder(encoder, dev) {
- if (count < card_res->count_encoders &&
- put_user(encoder->base.id, encoder_id + count))
- return -EFAULT;
- count++;
+ if (drm_lease_held(file_priv, encoder->base.id)) {
+ if (count < card_res->count_encoders &&
+ put_user(encoder->base.id, encoder_id + count))
+ return -EFAULT;
+ count++;
+ }
}
card_res->count_encoders = count;
@@ -143,12 +147,14 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
count = 0;
connector_id = u64_to_user_ptr(card_res->connector_id_ptr);
drm_for_each_connector_iter(connector, &conn_iter) {
- if (count < card_res->count_connectors &&
- put_user(connector->base.id, connector_id + count)) {
- drm_connector_list_iter_end(&conn_iter);
- return -EFAULT;
+ if (drm_lease_held(file_priv, connector->base.id)) {
+ if (count < card_res->count_connectors &&
+ put_user(connector->base.id, connector_id + count)) {
+ drm_connector_list_iter_end(&conn_iter);
+ return -EFAULT;
+ }
+ count++;
}
- count++;
}
card_res->count_connectors = count;
drm_connector_list_iter_end(&conn_iter);
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index ccc3a35d2de2..dbc280ddef9b 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -104,6 +104,25 @@ void drm_mode_object_unregister(struct drm_device *dev,
mutex_unlock(&dev->mode_config.idr_mutex);
}
+/**
+ * drm_lease_required - check types which must be leased to be used
+ * @type: type of object
+ *
+ * Returns whether the provided type of drm_mode_object must
+ * be owned or leased to be used by a process.
+ */
+static bool drm_lease_required(uint32_t type)
+{
+ switch(type) {
+ case DRM_MODE_OBJECT_CRTC:
+ case DRM_MODE_OBJECT_CONNECTOR:
+ case DRM_MODE_OBJECT_ENCODER:
+ return true;
+ default:
+ return false;
+ }
+}
+
struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
struct drm_file *file_priv,
uint32_t id, uint32_t type)
@@ -117,6 +136,9 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
if (obj && obj->id != id)
obj = NULL;
+ if (obj && drm_lease_required(obj->type) && !_drm_lease_held(file_priv, obj->id))
+ obj = NULL;
+
if (obj && obj->free_cb) {
if (!kref_get_unless_zero(&obj->refcount))
obj = NULL;
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 462c244498e2..9a7306a912b6 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -400,9 +400,9 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
return -ENOENT;
drm_modeset_lock(&plane->mutex, NULL);
- if (plane->state && plane->state->crtc)
+ if (plane->state && plane->state->crtc && drm_lease_held(file_priv, plane->state->crtc->base.id))
plane_resp->crtc_id = plane->state->crtc->base.id;
- else if (!plane->state && plane->crtc)
+ else if (!plane->state && plane->crtc && drm_lease_held(file_priv, plane->crtc->base.id))
plane_resp->crtc_id = plane->crtc->base.id;
else
plane_resp->crtc_id = 0;
@@ -416,7 +416,9 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
drm_modeset_unlock(&plane->mutex);
plane_resp->plane_id = plane->base.id;
- plane_resp->possible_crtcs = plane->possible_crtcs;
+ plane_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
+ plane->possible_crtcs);
+
plane_resp->gamma_size = 0;
/*
diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 70f2b9593edc..47d5cfa0c167 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -1401,9 +1401,11 @@ static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait)
int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
+ struct drm_crtc *crtc;
struct drm_vblank_crtc *vblank;
union drm_wait_vblank *vblwait = data;
int ret;
+ unsigned int pipe_index;
unsigned int flags, seq, pipe, high_pipe;
if (!dev->irq_enabled)
@@ -1425,9 +1427,21 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
high_pipe = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
if (high_pipe)
- pipe = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
+ pipe_index = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
else
- pipe = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
+ pipe_index = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
+
+ /* Convert lease-relative crtc index into global crtc index */
+ pipe = 0;
+ drm_for_each_crtc(crtc, dev) {
+ if (drm_lease_held(file_priv, crtc->base.id)) {
+ if (pipe_index == 0)
+ break;
+ pipe_index--;
+ }
+ pipe++;
+ }
+
if (pipe >= dev->num_crtcs)
return -EINVAL;
--
2.13.3
_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply related
* [PATCH] selinux: check CAP_SETFCAP for a particular inode & mapped user
From: Lubomir Rintel @ 2017-10-05 6:16 UTC (permalink / raw)
To: linux-security-module
This allows setting "security.capability" xattr by a user that has
CAP_SETFCAP in an userns with SELinux. Namespaced capabilities are
supported, as of commit 8db6c34f1dbc ("Introduce v3 namespaced file
capabilities").
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
A casual warning: Please not assume I know what I'm really doing. I can now
install iputils and /bin/ping in a LXC container, which is great, but I
typically wouldn't be allowed anywhere near anything security related.
Thank you!
security/selinux/hooks.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f5d304736852..7bc5f4ffb4e0 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3127,11 +3127,12 @@ static int selinux_inode_getattr(const struct path *path)
static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
{
const struct cred *cred = current_cred();
+ struct inode *inode = d_backing_inode(dentry);
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof XATTR_SECURITY_PREFIX - 1)) {
if (!strcmp(name, XATTR_NAME_CAPS)) {
- if (!capable(CAP_SETFCAP))
+ if (!capable_wrt_inode_uidgid(inode, CAP_SETFCAP))
return -EPERM;
} else if (!capable(CAP_SYS_ADMIN)) {
/* A different attribute in the security namespace.
--
2.13.6
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related
* [PATCH] selinux: check CAP_SETFCAP for a particular inode & mapped user
From: Lubomir Rintel @ 2017-10-05 6:16 UTC (permalink / raw)
To: linux-security-module
Cc: Serge E . Hallyn, Eric W . Biederman, linux-kernel, Paul Moore,
Stephen Smalley, Eric Paris, Lubomir Rintel
This allows setting "security.capability" xattr by a user that has
CAP_SETFCAP in an userns with SELinux. Namespaced capabilities are
supported, as of commit 8db6c34f1dbc ("Introduce v3 namespaced file
capabilities").
Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
---
A casual warning: Please not assume I know what I'm really doing. I can now
install iputils and /bin/ping in a LXC container, which is great, but I
typically wouldn't be allowed anywhere near anything security related.
Thank you!
security/selinux/hooks.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f5d304736852..7bc5f4ffb4e0 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3127,11 +3127,12 @@ static int selinux_inode_getattr(const struct path *path)
static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
{
const struct cred *cred = current_cred();
+ struct inode *inode = d_backing_inode(dentry);
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof XATTR_SECURITY_PREFIX - 1)) {
if (!strcmp(name, XATTR_NAME_CAPS)) {
- if (!capable(CAP_SETFCAP))
+ if (!capable_wrt_inode_uidgid(inode, CAP_SETFCAP))
return -EPERM;
} else if (!capable(CAP_SYS_ADMIN)) {
/* A different attribute in the security namespace.
--
2.13.6
^ permalink raw reply related
* [U-Boot] [PATCH v2] drivers: mmc: Avoid memory leak in case of failure
From: sunil.m at techveda.org @ 2017-10-05 6:18 UTC (permalink / raw)
To: u-boot
In-Reply-To: <0f527c1c-4e01-c8bd-1e86-76ad1693ef16@samsung.com>
From: Suniel Mahesh <sunil.m@techveda.org>
priv pointer should be freed before returning with an error value
from exynos_dwmci_get_config().
Signed-off-by: Suniel Mahesh <sunil.m@techveda.org>
Signed-off-by: Raghu Bharadwaj <raghu@techveda.org>
---
Changes for v2:
- rebased on latest u-boot tree (2017.11.rc1)
- patch was accepted long time ago, but not applied to u-boot-mmc,
please apply.
---
Note:
Tested on latest u-boot mainline tree, no build issues.
---
drivers/mmc/exynos_dw_mmc.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/drivers/mmc/exynos_dw_mmc.c b/drivers/mmc/exynos_dw_mmc.c
index 40f7892..84ef2da 100644
--- a/drivers/mmc/exynos_dw_mmc.c
+++ b/drivers/mmc/exynos_dw_mmc.c
@@ -168,6 +168,7 @@ static int exynos_dwmci_get_config(const void *blob, int node,
if (host->dev_index > 4) {
printf("DWMMC%d: Can't get the dev index\n", host->dev_index);
+ free(priv);
return -EINVAL;
}
@@ -178,6 +179,7 @@ static int exynos_dwmci_get_config(const void *blob, int node,
base = fdtdec_get_addr(blob, node, "reg");
if (!base) {
printf("DWMMC%d: Can't get base address\n", host->dev_index);
+ free(priv);
return -EINVAL;
}
host->ioaddr = (void *)base;
@@ -187,6 +189,7 @@ static int exynos_dwmci_get_config(const void *blob, int node,
if (err) {
printf("DWMMC%d: Can't get sdr-timings for devider\n",
host->dev_index);
+ free(priv);
return -EINVAL;
}
--
1.9.1
^ permalink raw reply related
* [PATCH 0/6] drm: Add leases [v4]
From: Keith Packard @ 2017-10-05 6:13 UTC (permalink / raw)
To: linux-kernel, Dave Airlie, Daniel Vetter; +Cc: Keith Packard, dri-devel
Here's another version of the DRM lease series. No changes in the code
at all:
[PATCH 4/6] drm: Add drm_object lease infrastructure [v4]
Changes in v4, suggested by Dave Airlie <airlied@gmail.com>
* Formatting and whitespace changes
[PATCH 6/6] drm: Add four ioctls for managing drm mode object leases
Changes for v3 suggested by Dave Airlie <airlied@gmail.com>
* Expand on the comment about the magic use of &drm_lease_idr_object
* Pad lease ioctl structures to align on 64-bit boundaries
Thanks much to Dave Airlie for his review.
-keith
^ permalink raw reply
* [PATCH 2/6] drm: Allow render nodes to query display objects
From: Keith Packard @ 2017-10-05 6:13 UTC (permalink / raw)
To: linux-kernel, Dave Airlie, Daniel Vetter; +Cc: Keith Packard, dri-devel
In-Reply-To: <20171005061310.29919-1-keithp@keithp.com>
This allows an application to discover what display resources are
available before requesting a lease from the X server.
Signed-off-by: Keith Packard <keithp@keithp.com>
---
drivers/gpu/drm/drm_ioctl.c | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 8bfeb32f8a10..7d0e481c5729 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -613,27 +613,27 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW),
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_GETCRTC, drm_mode_getcrtc, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_RENDER_ALLOW|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_GETPLANE, drm_mode_getplane, DRM_RENDER_ALLOW|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_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),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
@@ -642,7 +642,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
- DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+ DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
--
2.13.3
^ permalink raw reply related
* [PATCH 5/6] drm: Check mode object lease status in all master ioctl paths [v2]
From: Keith Packard @ 2017-10-05 6:13 UTC (permalink / raw)
To: linux-kernel, Dave Airlie, Daniel Vetter; +Cc: Keith Packard, dri-devel
In-Reply-To: <20171005061310.29919-1-keithp@keithp.com>
Attempts to modify un-leased objects are rejected with an error.
Information returned about unleased objects is modified to make them
appear unusable and/or disconnected.
Changes for v2 as suggested by Daniel Vetter <daniel.vetter@ffwll.ch>:
With the change in the __drm_mode_object_find API to pass the
file_priv along, we can now centralize most of the lease-based access
checks in that function.
A few places skip that API and require in-line checks.
Signed-off-by: Keith Packard <keithp@keithp.com>
---
drivers/gpu/drm/drm_auth.c | 2 +-
drivers/gpu/drm/drm_connector.c | 5 +++--
drivers/gpu/drm/drm_encoder.c | 8 +++++---
drivers/gpu/drm/drm_mode_config.c | 32 +++++++++++++++++++-------------
drivers/gpu/drm/drm_mode_object.c | 22 ++++++++++++++++++++++
drivers/gpu/drm/drm_plane.c | 8 +++++---
drivers/gpu/drm/drm_vblank.c | 18 ++++++++++++++++--
7 files changed, 71 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c
index 541177c71d51..bab26b477738 100644
--- a/drivers/gpu/drm/drm_auth.c
+++ b/drivers/gpu/drm/drm_auth.c
@@ -310,7 +310,7 @@ void drm_master_release(struct drm_file *file_priv)
*/
bool drm_is_current_master(struct drm_file *fpriv)
{
- return fpriv->is_master && fpriv->master == fpriv->minor->dev->master;
+ return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master;
}
EXPORT_SYMBOL(drm_is_current_master);
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index f8feb2bf142a..65ecdd954a69 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -1294,7 +1294,8 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
return -ENOENT;
for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++)
- if (connector->encoder_ids[i] != 0)
+ if (connector->encoder_ids[i] != 0 &&
+ drm_lease_held(file_priv, connector->encoder_ids[i]))
encoders_count++;
if ((out_resp->count_encoders >= encoders_count) && encoders_count) {
@@ -1361,7 +1362,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
encoder = drm_connector_get_encoder(connector);
- if (encoder)
+ if (encoder && drm_lease_held(file_priv, encoder->base.id))
out_resp->encoder_id = encoder->base.id;
else
out_resp->encoder_id = 0;
diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c
index 43f644844b83..6ad6416f2ede 100644
--- a/drivers/gpu/drm/drm_encoder.c
+++ b/drivers/gpu/drm/drm_encoder.c
@@ -226,7 +226,7 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
crtc = drm_encoder_get_crtc(encoder);
- if (crtc)
+ if (crtc && drm_lease_held(file_priv, crtc->base.id))
enc_resp->crtc_id = crtc->base.id;
else
enc_resp->crtc_id = 0;
@@ -234,8 +234,10 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
enc_resp->encoder_type = encoder->encoder_type;
enc_resp->encoder_id = encoder->base.id;
- enc_resp->possible_crtcs = encoder->possible_crtcs;
- enc_resp->possible_clones = encoder->possible_clones;
+ enc_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
+ encoder->possible_crtcs);
+ enc_resp->possible_clones = drm_lease_filter_encoders(file_priv,
+ encoder->possible_clones);
return 0;
}
diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c
index d9862259a2a7..f7ceee2ae340 100644
--- a/drivers/gpu/drm/drm_mode_config.c
+++ b/drivers/gpu/drm/drm_mode_config.c
@@ -122,20 +122,24 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
count = 0;
crtc_id = u64_to_user_ptr(card_res->crtc_id_ptr);
drm_for_each_crtc(crtc, dev) {
- if (count < card_res->count_crtcs &&
- put_user(crtc->base.id, crtc_id + count))
- return -EFAULT;
- count++;
+ if (drm_lease_held(file_priv, crtc->base.id)) {
+ if (count < card_res->count_crtcs &&
+ put_user(crtc->base.id, crtc_id + count))
+ return -EFAULT;
+ count++;
+ }
}
card_res->count_crtcs = count;
count = 0;
encoder_id = u64_to_user_ptr(card_res->encoder_id_ptr);
drm_for_each_encoder(encoder, dev) {
- if (count < card_res->count_encoders &&
- put_user(encoder->base.id, encoder_id + count))
- return -EFAULT;
- count++;
+ if (drm_lease_held(file_priv, encoder->base.id)) {
+ if (count < card_res->count_encoders &&
+ put_user(encoder->base.id, encoder_id + count))
+ return -EFAULT;
+ count++;
+ }
}
card_res->count_encoders = count;
@@ -143,12 +147,14 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
count = 0;
connector_id = u64_to_user_ptr(card_res->connector_id_ptr);
drm_for_each_connector_iter(connector, &conn_iter) {
- if (count < card_res->count_connectors &&
- put_user(connector->base.id, connector_id + count)) {
- drm_connector_list_iter_end(&conn_iter);
- return -EFAULT;
+ if (drm_lease_held(file_priv, connector->base.id)) {
+ if (count < card_res->count_connectors &&
+ put_user(connector->base.id, connector_id + count)) {
+ drm_connector_list_iter_end(&conn_iter);
+ return -EFAULT;
+ }
+ count++;
}
- count++;
}
card_res->count_connectors = count;
drm_connector_list_iter_end(&conn_iter);
diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c
index ccc3a35d2de2..dbc280ddef9b 100644
--- a/drivers/gpu/drm/drm_mode_object.c
+++ b/drivers/gpu/drm/drm_mode_object.c
@@ -104,6 +104,25 @@ void drm_mode_object_unregister(struct drm_device *dev,
mutex_unlock(&dev->mode_config.idr_mutex);
}
+/**
+ * drm_lease_required - check types which must be leased to be used
+ * @type: type of object
+ *
+ * Returns whether the provided type of drm_mode_object must
+ * be owned or leased to be used by a process.
+ */
+static bool drm_lease_required(uint32_t type)
+{
+ switch(type) {
+ case DRM_MODE_OBJECT_CRTC:
+ case DRM_MODE_OBJECT_CONNECTOR:
+ case DRM_MODE_OBJECT_ENCODER:
+ return true;
+ default:
+ return false;
+ }
+}
+
struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
struct drm_file *file_priv,
uint32_t id, uint32_t type)
@@ -117,6 +136,9 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev,
if (obj && obj->id != id)
obj = NULL;
+ if (obj && drm_lease_required(obj->type) && !_drm_lease_held(file_priv, obj->id))
+ obj = NULL;
+
if (obj && obj->free_cb) {
if (!kref_get_unless_zero(&obj->refcount))
obj = NULL;
diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c
index 462c244498e2..9a7306a912b6 100644
--- a/drivers/gpu/drm/drm_plane.c
+++ b/drivers/gpu/drm/drm_plane.c
@@ -400,9 +400,9 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
return -ENOENT;
drm_modeset_lock(&plane->mutex, NULL);
- if (plane->state && plane->state->crtc)
+ if (plane->state && plane->state->crtc && drm_lease_held(file_priv, plane->state->crtc->base.id))
plane_resp->crtc_id = plane->state->crtc->base.id;
- else if (!plane->state && plane->crtc)
+ else if (!plane->state && plane->crtc && drm_lease_held(file_priv, plane->crtc->base.id))
plane_resp->crtc_id = plane->crtc->base.id;
else
plane_resp->crtc_id = 0;
@@ -416,7 +416,9 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
drm_modeset_unlock(&plane->mutex);
plane_resp->plane_id = plane->base.id;
- plane_resp->possible_crtcs = plane->possible_crtcs;
+ plane_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv,
+ plane->possible_crtcs);
+
plane_resp->gamma_size = 0;
/*
diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 70f2b9593edc..47d5cfa0c167 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -1401,9 +1401,11 @@ static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait)
int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
+ struct drm_crtc *crtc;
struct drm_vblank_crtc *vblank;
union drm_wait_vblank *vblwait = data;
int ret;
+ unsigned int pipe_index;
unsigned int flags, seq, pipe, high_pipe;
if (!dev->irq_enabled)
@@ -1425,9 +1427,21 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data,
flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
high_pipe = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
if (high_pipe)
- pipe = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
+ pipe_index = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
else
- pipe = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
+ pipe_index = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
+
+ /* Convert lease-relative crtc index into global crtc index */
+ pipe = 0;
+ drm_for_each_crtc(crtc, dev) {
+ if (drm_lease_held(file_priv, crtc->base.id)) {
+ if (pipe_index == 0)
+ break;
+ pipe_index--;
+ }
+ pipe++;
+ }
+
if (pipe >= dev->num_crtcs)
return -EINVAL;
--
2.13.3
^ permalink raw reply related
* [PATCH 3/6] drm: Add new LEASE debug level
From: Keith Packard @ 2017-10-05 6:13 UTC (permalink / raw)
To: linux-kernel, Dave Airlie, Daniel Vetter; +Cc: Keith Packard, dri-devel
In-Reply-To: <20171005061310.29919-1-keithp@keithp.com>
Separate out lease debugging from the core.
Signed-off-by: Keith Packard <keithp@keithp.com>
---
drivers/gpu/drm/drm_drv.c | 3 ++-
include/drm/drmP.h | 4 ++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 2ed2d919beae..f390b30f5906 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -57,7 +57,8 @@ MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug cat
"\t\tBit 2 (0x04) will enable KMS messages (modesetting code)\n"
"\t\tBit 3 (0x08) will enable PRIME messages (prime code)\n"
"\t\tBit 4 (0x10) will enable ATOMIC messages (atomic code)\n"
-"\t\tBit 5 (0x20) will enable VBL messages (vblank code)");
+"\t\tBit 5 (0x20) will enable VBL messages (vblank code)\n"
+"\t\tBit 7 (0x80) will enable LEASE messages (leasing code)");
module_param_named(debug, drm_debug, int, 0600);
static DEFINE_SPINLOCK(drm_minor_lock);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 3aa3809ab524..2a54ccb16232 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -145,6 +145,7 @@ struct pci_controller;
#define DRM_UT_ATOMIC 0x10
#define DRM_UT_VBL 0x20
#define DRM_UT_STATE 0x40
+#define DRM_UT_LEASE 0x80
/***********************************************************************/
/** \name DRM template customization defaults */
@@ -259,6 +260,9 @@ struct pci_controller;
#define DRM_DEBUG_VBL(fmt, ...) \
drm_printk(KERN_DEBUG, DRM_UT_VBL, fmt, ##__VA_ARGS__)
+#define DRM_DEBUG_LEASE(fmt, ...) \
+ drm_printk(KERN_DEBUG, DRM_UT_LEASE, fmt, ##__VA_ARGS__)
+
#define _DRM_DEV_DEFINE_DEBUG_RATELIMITED(dev, level, fmt, args...) \
({ \
static DEFINE_RATELIMIT_STATE(_rs, \
--
2.13.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.