Merge tag 'drm-misc-next-2020-07-22' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

drm-misc-next for v5.9:

UAPI Changes:

Cross-subsystem Changes:
- Convert panel-dsi-cm and ingenic bindings to YAML.
- Add lockdep annotations for dma-fence. \o/
- Describe why indefinite fences are a bad idea
- Update binding for rocktech jh057n00900.

Core Changes:
- Add vblank workers.
- Use spin_(un)lock_irq instead of the irqsave/restore variants in crtc code.
- Add managed vram helpers.
- Convert more logging to drm functions.
- Replace more http links with https in core and drivers.
- Cleanup to ttm iomem functions and implementation.
- Remove TTM CMA memtype as it doesn't work correctly.
- Remove TTM_MEMTYPE_FLAG_MAPPABLE for many drivers that have no
  unmappable memory resources.

Driver Changes:
- Add CRC support to nouveau, using the new vblank workers.
- Dithering and atomic state fix for nouveau.
- Fixes for Frida FRD350H54004 panel.
- Add support for OSD mode (sprite planes), IPU (scaling) and multiple
  panels/bridges to ingenic.
- Use managed vram helpers in ast.
- Assorted small fixes to ingenic, i810, mxsfb.
- Remove optional unused ttm dummy functions.

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/d6bf269e-ccb2-8a7b-fdae-226e9e3f8274@linux.intel.com
This commit is contained in:
Dave Airlie
2020-07-23 14:01:37 +10:00
102 changed files with 4398 additions and 783 deletions
@@ -165,6 +165,7 @@ examples:
- |
#include <dt-bindings/clock/imx8mq-clock.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/imx8mq-reset.h>
@@ -191,12 +192,12 @@ examples:
phy-names = "dphy";
panel@0 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "rocktech,jh057n00900";
reg = <0>;
port@0 {
reg = <0>;
vcc-supply = <&reg_2v8_p>;
iovcc-supply = <&reg_1v8_p>;
reset-gpios = <&gpio3 13 GPIO_ACTIVE_LOW>;
port {
panel_in: endpoint {
remote-endpoint = <&mipi_dsi_out>;
};
@@ -0,0 +1,65 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/ingenic,ipu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Ingenic SoCs Image Processing Unit (IPU) devicetree bindings
maintainers:
- Paul Cercueil <paul@crapouillou.net>
properties:
compatible:
oneOf:
- enum:
- ingenic,jz4725b-ipu
- ingenic,jz4760-ipu
- items:
- const: ingenic,jz4770-ipu
- const: ingenic,jz4760-ipu
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
clock-names:
const: ipu
patternProperties:
"^ports?$":
description: OF graph bindings (specified in bindings/graph.txt).
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/jz4770-cgu.h>
ipu@13080000 {
compatible = "ingenic,jz4770-ipu", "ingenic,jz4760-ipu";
reg = <0x13080000 0x800>;
interrupt-parent = <&intc>;
interrupts = <29>;
clocks = <&cgu JZ4770_CLK_IPU>;
clock-names = "ipu";
port {
ipu_ep: endpoint {
remote-endpoint = <&lcdc_ep>;
};
};
};
@@ -1,45 +0,0 @@
Ingenic JZ47xx LCD driver
Required properties:
- compatible: one of:
* ingenic,jz4740-lcd
* ingenic,jz4725b-lcd
* ingenic,jz4770-lcd
- reg: LCD registers location and length
- clocks: LCD pixclock and device clock specifiers.
The device clock is only required on the JZ4740.
- clock-names: "lcd_pclk" and "lcd"
- interrupts: Specifies the interrupt line the LCD controller is connected to.
Example:
panel {
compatible = "sharp,ls020b1dd01d";
backlight = <&backlight>;
power-supply = <&vcc>;
port {
panel_input: endpoint {
remote-endpoint = <&panel_output>;
};
};
};
lcd: lcd-controller@13050000 {
compatible = "ingenic,jz4725b-lcd";
reg = <0x13050000 0x1000>;
interrupt-parent = <&intc>;
interrupts = <31>;
clocks = <&cgu JZ4725B_CLK_LCD>;
clock-names = "lcd";
port {
panel_output: endpoint {
remote-endpoint = <&panel_input>;
};
};
};
@@ -0,0 +1,126 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/ingenic,lcd.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Ingenic SoCs LCD controller devicetree bindings
maintainers:
- Paul Cercueil <paul@crapouillou.net>
properties:
$nodename:
pattern: "^lcd-controller@[0-9a-f]+$"
compatible:
enum:
- ingenic,jz4740-lcd
- ingenic,jz4725b-lcd
- ingenic,jz4770-lcd
- ingenic,jz4780-lcd
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: Pixel clock
- description: Module clock
minItems: 1
clock-names:
items:
- const: lcd_pclk
- const: lcd
minItems: 1
port:
description: OF graph bindings (specified in bindings/graph.txt).
ports:
description: OF graph bindings (specified in bindings/graph.txt).
type: object
properties:
port@0:
type: object
description: DPI output, to interface with TFT panels.
port@8:
type: object
description: Link to the Image Processing Unit (IPU).
(See ingenic,ipu.yaml).
required:
- port@0
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
if:
properties:
compatible:
contains:
enum:
- ingenic,jz4740-lcd
- ingenic,jz4780-lcd
then:
properties:
clocks:
minItems: 2
clock-names:
minItems: 2
else:
properties:
clocks:
maxItems: 1
clock-names:
maxItems: 1
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/jz4740-cgu.h>
lcd-controller@13050000 {
compatible = "ingenic,jz4740-lcd";
reg = <0x13050000 0x1000>;
interrupt-parent = <&intc>;
interrupts = <30>;
clocks = <&cgu JZ4740_CLK_LCD_PCLK>, <&cgu JZ4740_CLK_LCD>;
clock-names = "lcd_pclk", "lcd";
port {
endpoint {
remote-endpoint = <&panel_input>;
};
};
};
- |
#include <dt-bindings/clock/jz4725b-cgu.h>
lcd-controller@13050000 {
compatible = "ingenic,jz4725b-lcd";
reg = <0x13050000 0x1000>;
interrupt-parent = <&intc>;
interrupts = <31>;
clocks = <&cgu JZ4725B_CLK_LCD>;
clock-names = "lcd_pclk";
port {
endpoint {
remote-endpoint = <&panel_input>;
};
};
};
@@ -1,29 +0,0 @@
Generic MIPI DSI Command Mode Panel
===================================
Required properties:
- compatible: "panel-dsi-cm"
Optional properties:
- label: a symbolic name for the panel
- reset-gpios: panel reset gpio
- te-gpios: panel TE gpio
Required nodes:
- Video port for DSI input
Example
-------
lcd0: display {
compatible = "tpo,taal", "panel-dsi-cm";
label = "lcd0";
reset-gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>;
port {
lcd0_in: endpoint {
remote-endpoint = <&dsi1_out_ep>;
};
};
};
@@ -0,0 +1,86 @@
# SPDX-License-Identifier: (GPL-2.0-only or BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/display/panel/panel-dsi-cm.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: DSI command mode panels
maintainers:
- Tomi Valkeinen <tomi.valkeinen@ti.com>
- Sebastian Reichel <sre@kernel.org>
description: |
This binding file is a collection of the DSI panels that
are usually driven in command mode. If no backlight is
referenced via the optional backlight property, the DSI
panel is assumed to have native backlight support.
The panel may use an OF graph binding for the association
to the display, or it may be a direct child node of the
display.
allOf:
- $ref: panel-common.yaml#
properties:
compatible:
items:
- enum:
- motorola,droid4-panel # Panel from Motorola Droid4 phone
- nokia,himalaya # Panel from Nokia N950 phone
- tpo,taal # Panel from OMAP4 SDP board
- const: panel-dsi-cm # Generic DSI command mode panel compatible fallback
reg:
maxItems: 1
description: DSI virtual channel
vddi-supply:
description:
Display panels require power to be supplied. While several panels need
more than one power supply with panel-specific constraints governing the
order and timings of the power supplies, in many cases a single power
supply is sufficient, either because the panel has a single power rail, or
because all its power rails can be driven by the same supply. In that case
the vddi-supply property specifies the supply powering the panel as a
phandle to a regulator.
vpnl-supply:
description:
When the display panel needs a second power supply, this property can be
used in addition to vddi-supply. Both supplies will be enabled at the
same time before the panel is being accessed.
width-mm: true
height-mm: true
label: true
rotation: true
panel-timing: true
port: true
reset-gpios: true
te-gpios: true
backlight: true
additionalProperties: false
required:
- compatible
- reg
examples:
- |
#include <dt-bindings/gpio/gpio.h>
dsi-controller {
#address-cells = <1>;
#size-cells = <0>;
panel@0 {
compatible = "tpo,taal", "panel-dsi-cm";
reg = <0>;
reset-gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>;
};
};
...
@@ -24,6 +24,7 @@ properties:
# Xingbangda XBD599 5.99" 720x1440 TFT LCD panel
- xingbangda,xbd599
port: true
reg:
maxItems: 1
description: DSI virtual channel
+82
View File
@@ -133,6 +133,18 @@ DMA Fences
.. kernel-doc:: drivers/dma-buf/dma-fence.c
:doc: DMA fences overview
DMA Fence Cross-Driver Contract
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. kernel-doc:: drivers/dma-buf/dma-fence.c
:doc: fence cross-driver contract
DMA Fence Signalling Annotations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. kernel-doc:: drivers/dma-buf/dma-fence.c
:doc: fence signalling annotation
DMA Fences Functions Reference
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -166,3 +178,73 @@ DMA Fence uABI/Sync File
.. kernel-doc:: include/linux/sync_file.h
:internal:
Indefinite DMA Fences
~~~~~~~~~~~~~~~~~~~~
At various times &dma_fence with an indefinite time until dma_fence_wait()
finishes have been proposed. Examples include:
* Future fences, used in HWC1 to signal when a buffer isn't used by the display
any longer, and created with the screen update that makes the buffer visible.
The time this fence completes is entirely under userspace's control.
* Proxy fences, proposed to handle &drm_syncobj for which the fence has not yet
been set. Used to asynchronously delay command submission.
* Userspace fences or gpu futexes, fine-grained locking within a command buffer
that userspace uses for synchronization across engines or with the CPU, which
are then imported as a DMA fence for integration into existing winsys
protocols.
* Long-running compute command buffers, while still using traditional end of
batch DMA fences for memory management instead of context preemption DMA
fences which get reattached when the compute job is rescheduled.
Common to all these schemes is that userspace controls the dependencies of these
fences and controls when they fire. Mixing indefinite fences with normal
in-kernel DMA fences does not work, even when a fallback timeout is included to
protect against malicious userspace:
* Only the kernel knows about all DMA fence dependencies, userspace is not aware
of dependencies injected due to memory management or scheduler decisions.
* Only userspace knows about all dependencies in indefinite fences and when
exactly they will complete, the kernel has no visibility.
Furthermore the kernel has to be able to hold up userspace command submission
for memory management needs, which means we must support indefinite fences being
dependent upon DMA fences. If the kernel also support indefinite fences in the
kernel like a DMA fence, like any of the above proposal would, there is the
potential for deadlocks.
.. kernel-render:: DOT
:alt: Indefinite Fencing Dependency Cycle
:caption: Indefinite Fencing Dependency Cycle
digraph "Fencing Cycle" {
node [shape=box bgcolor=grey style=filled]
kernel [label="Kernel DMA Fences"]
userspace [label="userspace controlled fences"]
kernel -> userspace [label="memory management"]
userspace -> kernel [label="Future fence, fence proxy, ..."]
{ rank=same; kernel userspace }
}
This means that the kernel might accidentally create deadlocks
through memory management dependencies which userspace is unaware of, which
randomly hangs workloads until the timeout kicks in. Workloads, which from
userspace's perspective, do not contain a deadlock. In such a mixed fencing
architecture there is no single entity with knowledge of all dependencies.
Thefore preventing such deadlocks from within the kernel is not possible.
The only solution to avoid dependencies loops is by not allowing indefinite
fences in the kernel. This means:
* No future fences, proxy fences or userspace fences imported as DMA fences,
with or without a timeout.
* No DMA fences that signal end of batchbuffer for command submission where
userspace is allowed to use userspace fencing or long running compute
workloads. This also means no implicit fencing for shared buffers in these
cases.
+1 -1
View File
@@ -127,7 +127,7 @@ At least on the EP9315 there is a silicon bug which causes bit 27 of
the VIDSCRNPAGE (framebuffer physical offset) to be tied low. There is
an unofficial errata for this bug at::
http://marc.info/?l=linux-arm-kernel&m=110061245502000&w=2
https://marc.info/?l=linux-arm-kernel&m=110061245502000&w=2
By default the EP93xx framebuffer driver checks if the allocated physical
address has bit 27 set. If it does, then the memory is freed and an
+15
View File
@@ -543,3 +543,18 @@ Vertical Blanking and Interrupt Handling Functions Reference
.. kernel-doc:: drivers/gpu/drm/drm_vblank.c
:export:
Vertical Blank Work
===================
.. kernel-doc:: drivers/gpu/drm/drm_vblank_work.c
:doc: vblank works
Vertical Blank Work Functions Reference
---------------------------------------
.. kernel-doc:: include/drm/drm_vblank_work.h
:internal:
.. kernel-doc:: drivers/gpu/drm/drm_vblank_work.c
:export:
+4 -4
View File
@@ -185,7 +185,7 @@ enhancing the kernel code to adapt as a kernel module and also did the
implementation of the user space side [3]. Now (2009) Tiago Vignatti and Dave
Airlie finally put this work in shape and queued to Jesse Barnes' PCI tree.
0) http://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
1) http://lists.freedesktop.org/archives/xorg/2005-March/006663.html
2) http://lists.freedesktop.org/archives/xorg/2005-March/006745.html
3) http://lists.freedesktop.org/archives/xorg/2007-October/029507.html
0) https://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
1) https://lists.freedesktop.org/archives/xorg/2005-March/006663.html
2) https://lists.freedesktop.org/archives/xorg/2005-March/006745.html
3) https://lists.freedesktop.org/archives/xorg/2007-October/029507.html
+207
View File
@@ -64,6 +64,52 @@ static atomic64_t dma_fence_context_counter = ATOMIC64_INIT(1);
* &dma_buf.resv pointer.
*/
/**
* DOC: fence cross-driver contract
*
* Since &dma_fence provide a cross driver contract, all drivers must follow the
* same rules:
*
* * Fences must complete in a reasonable time. Fences which represent kernels
* and shaders submitted by userspace, which could run forever, must be backed
* up by timeout and gpu hang recovery code. Minimally that code must prevent
* further command submission and force complete all in-flight fences, e.g.
* when the driver or hardware do not support gpu reset, or if the gpu reset
* failed for some reason. Ideally the driver supports gpu recovery which only
* affects the offending userspace context, and no other userspace
* submissions.
*
* * Drivers may have different ideas of what completion within a reasonable
* time means. Some hang recovery code uses a fixed timeout, others a mix
* between observing forward progress and increasingly strict timeouts.
* Drivers should not try to second guess timeout handling of fences from
* other drivers.
*
* * To ensure there's no deadlocks of dma_fence_wait() against other locks
* drivers should annotate all code required to reach dma_fence_signal(),
* which completes the fences, with dma_fence_begin_signalling() and
* dma_fence_end_signalling().
*
* * Drivers are allowed to call dma_fence_wait() while holding dma_resv_lock().
* This means any code required for fence completion cannot acquire a
* &dma_resv lock. Note that this also pulls in the entire established
* locking hierarchy around dma_resv_lock() and dma_resv_unlock().
*
* * Drivers are allowed to call dma_fence_wait() from their &shrinker
* callbacks. This means any code required for fence completion cannot
* allocate memory with GFP_KERNEL.
*
* * Drivers are allowed to call dma_fence_wait() from their &mmu_notifier
* respectively &mmu_interval_notifier callbacks. This means any code required
* for fence completeion cannot allocate memory with GFP_NOFS or GFP_NOIO.
* Only GFP_ATOMIC is permissible, which might fail.
*
* Note that only GPU drivers have a reasonable excuse for both requiring
* &mmu_interval_notifier and &shrinker callbacks at the same time as having to
* track asynchronous compute work using &dma_fence. No driver outside of
* drivers/gpu should ever call dma_fence_wait() in such contexts.
*/
static const char *dma_fence_stub_get_name(struct dma_fence *fence)
{
return "stub";
@@ -110,6 +156,160 @@ u64 dma_fence_context_alloc(unsigned num)
}
EXPORT_SYMBOL(dma_fence_context_alloc);
/**
* DOC: fence signalling annotation
*
* Proving correctness of all the kernel code around &dma_fence through code
* review and testing is tricky for a few reasons:
*
* * It is a cross-driver contract, and therefore all drivers must follow the
* same rules for lock nesting order, calling contexts for various functions
* and anything else significant for in-kernel interfaces. But it is also
* impossible to test all drivers in a single machine, hence brute-force N vs.
* N testing of all combinations is impossible. Even just limiting to the
* possible combinations is infeasible.
*
* * There is an enormous amount of driver code involved. For render drivers
* there's the tail of command submission, after fences are published,
* scheduler code, interrupt and workers to process job completion,
* and timeout, gpu reset and gpu hang recovery code. Plus for integration
* with core mm with have &mmu_notifier, respectively &mmu_interval_notifier,
* and &shrinker. For modesetting drivers there's the commit tail functions
* between when fences for an atomic modeset are published, and when the
* corresponding vblank completes, including any interrupt processing and
* related workers. Auditing all that code, across all drivers, is not
* feasible.
*
* * Due to how many other subsystems are involved and the locking hierarchies
* this pulls in there is extremely thin wiggle-room for driver-specific
* differences. &dma_fence interacts with almost all of the core memory
* handling through page fault handlers via &dma_resv, dma_resv_lock() and
* dma_resv_unlock(). On the other side it also interacts through all
* allocation sites through &mmu_notifier and &shrinker.
*
* Furthermore lockdep does not handle cross-release dependencies, which means
* any deadlocks between dma_fence_wait() and dma_fence_signal() can't be caught
* at runtime with some quick testing. The simplest example is one thread
* waiting on a &dma_fence while holding a lock::
*
* lock(A);
* dma_fence_wait(B);
* unlock(A);
*
* while the other thread is stuck trying to acquire the same lock, which
* prevents it from signalling the fence the previous thread is stuck waiting
* on::
*
* lock(A);
* unlock(A);
* dma_fence_signal(B);
*
* By manually annotating all code relevant to signalling a &dma_fence we can
* teach lockdep about these dependencies, which also helps with the validation
* headache since now lockdep can check all the rules for us::
*
* cookie = dma_fence_begin_signalling();
* lock(A);
* unlock(A);
* dma_fence_signal(B);
* dma_fence_end_signalling(cookie);
*
* For using dma_fence_begin_signalling() and dma_fence_end_signalling() to
* annotate critical sections the following rules need to be observed:
*
* * All code necessary to complete a &dma_fence must be annotated, from the
* point where a fence is accessible to other threads, to the point where
* dma_fence_signal() is called. Un-annotated code can contain deadlock issues,
* and due to the very strict rules and many corner cases it is infeasible to
* catch these just with review or normal stress testing.
*
* * &struct dma_resv deserves a special note, since the readers are only
* protected by rcu. This means the signalling critical section starts as soon
* as the new fences are installed, even before dma_resv_unlock() is called.
*
* * The only exception are fast paths and opportunistic signalling code, which
* calls dma_fence_signal() purely as an optimization, but is not required to
* guarantee completion of a &dma_fence. The usual example is a wait IOCTL
* which calls dma_fence_signal(), while the mandatory completion path goes
* through a hardware interrupt and possible job completion worker.
*
* * To aid composability of code, the annotations can be freely nested, as long
* as the overall locking hierarchy is consistent. The annotations also work
* both in interrupt and process context. Due to implementation details this
* requires that callers pass an opaque cookie from
* dma_fence_begin_signalling() to dma_fence_end_signalling().
*
* * Validation against the cross driver contract is implemented by priming
* lockdep with the relevant hierarchy at boot-up. This means even just
* testing with a single device is enough to validate a driver, at least as
* far as deadlocks with dma_fence_wait() against dma_fence_signal() are
* concerned.
*/
#ifdef CONFIG_LOCKDEP
struct lockdep_map dma_fence_lockdep_map = {
.name = "dma_fence_map"
};
/**
* dma_fence_begin_signalling - begin a critical DMA fence signalling section
*
* Drivers should use this to annotate the beginning of any code section
* required to eventually complete &dma_fence by calling dma_fence_signal().
*
* The end of these critical sections are annotated with
* dma_fence_end_signalling().
*
* Returns:
*
* Opaque cookie needed by the implementation, which needs to be passed to
* dma_fence_end_signalling().
*/
bool dma_fence_begin_signalling(void)
{
/* explicitly nesting ... */
if (lock_is_held_type(&dma_fence_lockdep_map, 1))
return true;
/* rely on might_sleep check for soft/hardirq locks */
if (in_atomic())
return true;
/* ... and non-recursive readlock */
lock_acquire(&dma_fence_lockdep_map, 0, 0, 1, 1, NULL, _RET_IP_);
return false;
}
EXPORT_SYMBOL(dma_fence_begin_signalling);
/**
* dma_fence_end_signalling - end a critical DMA fence signalling section
*
* Closes a critical section annotation opened by dma_fence_begin_signalling().
*/
void dma_fence_end_signalling(bool cookie)
{
if (cookie)
return;
lock_release(&dma_fence_lockdep_map, _RET_IP_);
}
EXPORT_SYMBOL(dma_fence_end_signalling);
void __dma_fence_might_wait(void)
{
bool tmp;
tmp = lock_is_held_type(&dma_fence_lockdep_map, 1);
if (tmp)
lock_release(&dma_fence_lockdep_map, _THIS_IP_);
lock_map_acquire(&dma_fence_lockdep_map);
lock_map_release(&dma_fence_lockdep_map);
if (tmp)
lock_acquire(&dma_fence_lockdep_map, 0, 0, 1, 1, NULL, _THIS_IP_);
}
#endif
/**
* dma_fence_signal_locked - signal completion of a fence
* @fence: the fence to signal
@@ -170,14 +370,19 @@ int dma_fence_signal(struct dma_fence *fence)
{
unsigned long flags;
int ret;
bool tmp;
if (!fence)
return -EINVAL;
tmp = dma_fence_begin_signalling();
spin_lock_irqsave(fence->lock, flags);
ret = dma_fence_signal_locked(fence);
spin_unlock_irqrestore(fence->lock, flags);
dma_fence_end_signalling(tmp);
return ret;
}
EXPORT_SYMBOL(dma_fence_signal);
@@ -210,6 +415,8 @@ dma_fence_wait_timeout(struct dma_fence *fence, bool intr, signed long timeout)
might_sleep();
__dma_fence_might_wait();
trace_dma_fence_wait_start(fence);
if (fence->ops->wait)
ret = fence->ops->wait(fence, intr, timeout);
+8
View File
@@ -36,6 +36,7 @@
#include <linux/export.h>
#include <linux/mm.h>
#include <linux/sched/mm.h>
#include <linux/mmu_notifier.h>
/**
* DOC: Reservation Object Overview
@@ -116,6 +117,13 @@ static int __init dma_resv_lockdep(void)
if (ret == -EDEADLK)
dma_resv_lock_slow(&obj, &ctx);
fs_reclaim_acquire(GFP_KERNEL);
#ifdef CONFIG_MMU_NOTIFIER
lock_map_acquire(&__mmu_notifier_invalidate_range_start_map);
__dma_fence_might_wait();
lock_map_release(&__mmu_notifier_invalidate_range_start_map);
#else
__dma_fence_might_wait();
#endif
fs_reclaim_release(GFP_KERNEL);
ww_mutex_unlock(&obj.lock);
ww_acquire_fini(&ctx);
+1 -1
View File
@@ -18,7 +18,7 @@ drm-y := drm_auth.o drm_cache.o \
drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
drm_client_modeset.o drm_atomic_uapi.o drm_hdcp.o \
drm_managed.o
drm_managed.o drm_vblank_work.o
drm-$(CONFIG_DRM_LEGACY) += drm_legacy_misc.o drm_bufs.o drm_context.o drm_dma.o drm_scatter.o drm_lock.o
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
+2 -7
View File
@@ -94,7 +94,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
man->func = &amdgpu_gtt_mgr_func;
man->available_caching = TTM_PL_MASK_CACHING;
man->default_caching = TTM_PL_FLAG_CACHED;
man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA;
man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
break;
case TTM_PL_VRAM:
/* "On-card" video ram */
@@ -109,7 +109,7 @@ static int amdgpu_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
case AMDGPU_PL_OA:
/* On-chip GDS memory*/
man->func = &ttm_bo_manager_func;
man->flags = TTM_MEMTYPE_FLAG_FIXED | TTM_MEMTYPE_FLAG_CMA;
man->flags = TTM_MEMTYPE_FLAG_FIXED;
man->available_caching = TTM_PL_FLAG_UNCACHED;
man->default_caching = TTM_PL_FLAG_UNCACHED;
break;
@@ -837,10 +837,6 @@ static int amdgpu_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_
return 0;
}
static void amdgpu_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
{
}
static unsigned long amdgpu_ttm_io_mem_pfn(struct ttm_buffer_object *bo,
unsigned long page_offset)
{
@@ -1755,7 +1751,6 @@ static struct ttm_bo_driver amdgpu_bo_driver = {
.release_notify = &amdgpu_bo_release_notify,
.fault_reserve_notify = &amdgpu_bo_fault_reserve_notify,
.io_mem_reserve = &amdgpu_ttm_io_mem_reserve,
.io_mem_free = &amdgpu_ttm_io_mem_free,
.io_mem_pfn = amdgpu_ttm_io_mem_pfn,
.access_memory = &amdgpu_ttm_access_memory,
.del_from_lru_notify = &amdgpu_vm_del_from_lru_notify
+1 -1
View File
@@ -3,7 +3,7 @@
# Makefile for the drm device driver. This driver provides support for the
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
ast-y := ast_cursor.o ast_drv.o ast_main.o ast_mode.o ast_ttm.o ast_post.o \
ast-y := ast_cursor.o ast_drv.o ast_main.o ast_mm.o ast_mode.o ast_post.o \
ast_dp501.o
obj-$(CONFIG_DRM_AST) := ast.o
-2
View File
@@ -110,7 +110,6 @@ struct ast_private {
uint32_t dram_bus_width;
uint32_t dram_type;
uint32_t mclk;
uint32_t vram_size;
int fb_mtrr;
@@ -292,7 +291,6 @@ int ast_mode_config_init(struct ast_private *ast);
#define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1)
int ast_mm_init(struct ast_private *ast);
void ast_mm_fini(struct ast_private *ast);
/* ast post */
void ast_enable_vga(struct drm_device *dev);
+5 -40
View File
@@ -378,38 +378,6 @@ static int ast_get_dram_info(struct drm_device *dev)
return 0;
}
static u32 ast_get_vram_info(struct drm_device *dev)
{
struct ast_private *ast = to_ast_private(dev);
u8 jreg;
u32 vram_size;
ast_open_key(ast);
vram_size = AST_VIDMEM_DEFAULT_SIZE;
jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xaa, 0xff);
switch (jreg & 3) {
case 0: vram_size = AST_VIDMEM_SIZE_8M; break;
case 1: vram_size = AST_VIDMEM_SIZE_16M; break;
case 2: vram_size = AST_VIDMEM_SIZE_32M; break;
case 3: vram_size = AST_VIDMEM_SIZE_64M; break;
}
jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x99, 0xff);
switch (jreg & 0x03) {
case 1:
vram_size -= 0x100000;
break;
case 2:
vram_size -= 0x200000;
break;
case 3:
vram_size -= 0x400000;
break;
}
return vram_size;
}
int ast_driver_load(struct drm_device *dev, unsigned long flags)
{
struct ast_private *ast;
@@ -450,16 +418,14 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags)
ast_detect_chip(dev, &need_post);
if (need_post)
ast_post_gpu(dev);
ret = ast_get_dram_info(dev);
if (ret)
goto out_free;
ast->vram_size = ast_get_vram_info(dev);
drm_info(dev, "dram MCLK=%u Mhz type=%d bus_width=%d size=%08x\n",
ast->mclk, ast->dram_type,
ast->dram_bus_width, ast->vram_size);
drm_info(dev, "dram MCLK=%u Mhz type=%d bus_width=%d\n",
ast->mclk, ast->dram_type, ast->dram_bus_width);
if (need_post)
ast_post_gpu(dev);
ret = ast_mm_init(ast);
if (ret)
@@ -486,6 +452,5 @@ void ast_driver_unload(struct drm_device *dev)
ast_release_firmware(dev);
kfree(ast->dp501_fw_addr);
ast_mm_fini(ast);
kfree(ast);
}
@@ -28,22 +28,72 @@
#include <linux/pci.h>
#include <drm/drm_print.h>
#include <drm/drm_gem_vram_helper.h>
#include <drm/drm_managed.h>
#include <drm/drm_print.h>
#include "ast_drv.h"
static u32 ast_get_vram_size(struct ast_private *ast)
{
u8 jreg;
u32 vram_size;
ast_open_key(ast);
vram_size = AST_VIDMEM_DEFAULT_SIZE;
jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xaa, 0xff);
switch (jreg & 3) {
case 0:
vram_size = AST_VIDMEM_SIZE_8M;
break;
case 1:
vram_size = AST_VIDMEM_SIZE_16M;
break;
case 2:
vram_size = AST_VIDMEM_SIZE_32M;
break;
case 3:
vram_size = AST_VIDMEM_SIZE_64M;
break;
}
jreg = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0x99, 0xff);
switch (jreg & 0x03) {
case 1:
vram_size -= 0x100000;
break;
case 2:
vram_size -= 0x200000;
break;
case 3:
vram_size -= 0x400000;
break;
}
return vram_size;
}
static void ast_mm_release(struct drm_device *dev, void *ptr)
{
struct ast_private *ast = to_ast_private(dev);
arch_phys_wc_del(ast->fb_mtrr);
arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),
pci_resource_len(dev->pdev, 0));
}
int ast_mm_init(struct ast_private *ast)
{
struct drm_vram_mm *vmm;
u32 vram_size;
int ret;
struct drm_device *dev = ast->dev;
vmm = drm_vram_helper_alloc_mm(
dev, pci_resource_start(dev->pdev, 0),
ast->vram_size);
if (IS_ERR(vmm)) {
ret = PTR_ERR(vmm);
vram_size = ast_get_vram_size(ast);
ret = drmm_vram_helper_init(dev, pci_resource_start(dev->pdev, 0),
vram_size);
if (ret) {
drm_err(dev, "Error initializing VRAM MM; %d\n", ret);
return ret;
}
@@ -53,16 +103,5 @@ int ast_mm_init(struct ast_private *ast)
ast->fb_mtrr = arch_phys_wc_add(pci_resource_start(dev->pdev, 0),
pci_resource_len(dev->pdev, 0));
return 0;
}
void ast_mm_fini(struct ast_private *ast)
{
struct drm_device *dev = ast->dev;
drm_vram_helper_release_mm(dev);
arch_phys_wc_del(ast->fb_mtrr);
arch_io_free_memtype_wc(pci_resource_start(dev->pdev, 0),
pci_resource_len(dev->pdev, 0));
return drmm_add_action_or_reset(dev, ast_mm_release, NULL);
}
+2 -4
View File
@@ -1844,9 +1844,7 @@ static void connector_bad_edid(struct drm_connector *connector,
if (connector->bad_edid_counter++ && !drm_debug_enabled(DRM_UT_KMS))
return;
dev_warn(connector->dev->dev,
"%s: EDID is invalid:\n",
connector->name);
drm_warn(connector->dev, "%s: EDID is invalid:\n", connector->name);
for (i = 0; i < num_blocks; i++) {
u8 *block = edid + i * EDID_LENGTH;
char prefix[20];
@@ -5298,7 +5296,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
}
if (!drm_edid_is_valid(edid)) {
clear_eld(connector);
dev_warn(connector->dev->dev, "%s: EDID invalid.\n",
drm_warn(connector->dev, "%s: EDID invalid.\n",
connector->name);
return 0;
}

Some files were not shown because too many files have changed in this diff Show More