Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f8f15c34 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-msm-next-2018-07-30' of git://people.freedesktop.org/~robclark/linux into drm-next



A bit larger this time around, due to introduction of "dpu1" support
for the display controller in sdm845 and beyond.  This has been on
list and undergoing refactoring since Feb (going from ~110kloc to
~30kloc), and all my review complaints have been addressed, so I'd be
happy to see this upstream so further feature work can procede on top
of upstream.

Also includes the gpu coredump support, which should be useful for
debugging gpu crashes.  And various other misc fixes and such.

Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGv-8y3zguY0Mj1vh=o+vrv_bJ8AwZ96wBXYPvMeQT2XcA@mail.gmail.com
parents caca1ff0 a7663a79
Loading
Loading
Loading
Loading
+131 −0
Original line number Diff line number Diff line
Qualcomm Technologies, Inc. DPU KMS

Description:

Device tree bindings for MSM Mobile Display Subsytem(MDSS) that encapsulates
sub-blocks like DPU display controller, DSI and DP interfaces etc.
The DPU display controller is found in SDM845 SoC.

MDSS:
Required properties:
- compatible: "qcom,sdm845-mdss"
- reg: physical base address and length of contoller's registers.
- reg-names: register region names. The following region is required:
  * "mdss"
- power-domains: a power domain consumer specifier according to
  Documentation/devicetree/bindings/power/power_domain.txt
- clocks: list of clock specifiers for clocks needed by the device.
- clock-names: device clock names, must be in same order as clocks property.
  The following clocks are required:
  * "iface"
  * "bus"
  * "core"
- interrupts: interrupt signal from MDSS.
- interrupt-controller: identifies the node as an interrupt controller.
- #interrupt-cells: specifies the number of cells needed to encode an interrupt
  source, should be 1.
- iommus: phandle of iommu device node.
- #address-cells: number of address cells for the MDSS children. Should be 1.
- #size-cells: Should be 1.
- ranges: parent bus address space is the same as the child bus address space.

Optional properties:
- assigned-clocks: list of clock specifiers for clocks needing rate assignment
- assigned-clock-rates: list of clock frequencies sorted in the same order as
  the assigned-clocks property.

MDP:
Required properties:
- compatible: "qcom,sdm845-dpu"
- reg: physical base address and length of controller's registers.
- reg-names : register region names. The following region is required:
  * "mdp"
  * "vbif"
- clocks: list of clock specifiers for clocks needed by the device.
- clock-names: device clock names, must be in same order as clocks property.
  The following clocks are required.
  * "bus"
  * "iface"
  * "core"
  * "vsync"
- interrupts: interrupt line from DPU to MDSS.
- ports: contains the list of output ports from DPU device. These ports connect
  to interfaces that are external to the DPU hardware, such as DSI, DP etc.

  Each output port contains an endpoint that describes how it is connected to an
  external interface. These are described by the standard properties documented
  here:
	Documentation/devicetree/bindings/graph.txt
	Documentation/devicetree/bindings/media/video-interfaces.txt

	Port 0 -> DPU_INTF1 (DSI1)
	Port 1 -> DPU_INTF2 (DSI2)

Optional properties:
- assigned-clocks: list of clock specifiers for clocks needing rate assignment
- assigned-clock-rates: list of clock frequencies sorted in the same order as
  the assigned-clocks property.

Example:

	mdss: mdss@ae00000 {
		compatible = "qcom,sdm845-mdss";
		reg = <0xae00000 0x1000>;
		reg-names = "mdss";

		power-domains = <&clock_dispcc 0>;

		clocks = <&gcc GCC_DISP_AHB_CLK>, <&gcc GCC_DISP_AXI_CLK>,
			 <&clock_dispcc DISP_CC_MDSS_MDP_CLK>;
		clock-names = "iface", "bus", "core";

		assigned-clocks = <&clock_dispcc DISP_CC_MDSS_MDP_CLK>;
		assigned-clock-rates = <300000000>;

		interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;
		interrupt-controller;
		#interrupt-cells = <1>;

		iommus = <&apps_iommu 0>;

		#address-cells = <2>;
		#size-cells = <1>;
		ranges = <0 0 0xae00000 0xb2008>;

		mdss_mdp: mdp@ae01000 {
			compatible = "qcom,sdm845-dpu";
			reg = <0 0x1000 0x8f000>, <0 0xb0000 0x2008>;
			reg-names = "mdp", "vbif";

			clocks = <&clock_dispcc DISP_CC_MDSS_AHB_CLK>,
				 <&clock_dispcc DISP_CC_MDSS_AXI_CLK>,
				 <&clock_dispcc DISP_CC_MDSS_MDP_CLK>,
				 <&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>;
			clock-names = "iface", "bus", "core", "vsync";

			assigned-clocks = <&clock_dispcc DISP_CC_MDSS_MDP_CLK>,
					  <&clock_dispcc DISP_CC_MDSS_VSYNC_CLK>;
			assigned-clock-rates = <0 0 300000000 19200000>;

			interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;

			ports {
				#address-cells = <1>;
				#size-cells = <0>;

				port@0 {
					reg = <0>;
					dpu_intf1_out: endpoint {
						remote-endpoint = <&dsi0_in>;
					};
				};

				port@1 {
					reg = <1>;
					dpu_intf2_out: endpoint {
						remote-endpoint = <&dsi1_in>;
					};
				};
			};
		};
	};
+16 −0
Original line number Diff line number Diff line
@@ -121,6 +121,20 @@ Required properties:
Optional properties:
- qcom,dsi-phy-regulator-ldo-mode: Boolean value indicating if the LDO mode PHY
  regulator is wanted.
- qcom,mdss-mdp-transfer-time-us:	Specifies the dsi transfer time for command mode
					panels in microseconds. Driver uses this number to adjust
					the clock rate according to the expected transfer time.
					Increasing this value would slow down the mdp processing
					and can result in slower performance.
					Decreasing this value can speed up the mdp processing,
					but this can also impact power consumption.
					As a rule this time should not be higher than the time
					that would be expected with the processing at the
					dsi link rate since anyways this would be the maximum
					transfer time that could be achieved.
					If ping pong split is enabled, this time should not be higher
					than two times the dsi link rate time.
					If the property is not specified, then the default value is 14000 us.

[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
[2] Documentation/devicetree/bindings/graph.txt
@@ -171,6 +185,8 @@ Example:
		qcom,master-dsi;
		qcom,sync-dual-dsi;

		qcom,mdss-mdp-transfer-time-us = <12000>;

		pinctrl-names = "default", "sleep";
		pinctrl-0 = <&dsi_active>;
		pinctrl-1 = <&dsi_suspend>;
+96 −0
Original line number Diff line number Diff line
=====================
MSM Crash Dump Format
=====================

Following a GPU hang the MSM driver outputs debugging information via
/sys/kernel/dri/X/show or via devcoredump (/sys/class/devcoredump/dcdX/data).
This document describes how the output is formatted.

Each entry is in the form key: value. Sections headers will not have a value
and all the contents of a section will be indented two spaces from the header.
Each section might have multiple array entries the start of which is designated
by a (-).

Mappings
--------

kernel
	The kernel version that generated the dump (UTS_RELEASE).

module
	The module that generated the crashdump.

time
	The kernel time at crash formated as seconds.microseconds.

comm
	Comm string for the binary that generated the fault.

cmdline
	Command line for the binary that generated the fault.

revision
	ID of the GPU that generated the crash formatted as
	core.major.minor.patchlevel separated by dots.

rbbm-status
	The current value of RBBM_STATUS which shows what top level GPU
	components are in use at the time of crash.

ringbuffer
	Section containing the contents of each ringbuffer. Each ringbuffer is
	identified with an id number.

	id
		Ringbuffer ID (0 based index).  Each ringbuffer in the section
		will have its own unique id.
	iova
		GPU address of the ringbuffer.

	last-fence
		The last fence that was issued on the ringbuffer

	retired-fence
		The last fence retired on the ringbuffer.

	rptr
		The current read pointer (rptr) for the ringbuffer.

	wptr
		The current write pointer (wptr) for the ringbuffer.

	size
		Maximum size of the ringbuffer programmed in the hardware.

	data
		The contents of the ring encoded as ascii85.  Only the used
		portions of the ring will be printed.

bo
	List of buffers from the hanging submission if available.
	Each buffer object will have a uinque iova.

	iova
		GPU address of the buffer object.

	size
		Allocated size of the buffer object.

	data
		The contents of the buffer object encoded with ascii85.  Only
		Trailing zeros at the end of the buffer will be skipped.

registers
	Set of registers values. Each entry is on its own line enclosed
	by brackets { }.

	offset
		Byte offset of the register from the start of the
		GPU memory region.

	value
		Hexadecimal value of the register.

registers-hlsq
		(5xx only) Register values from the HLSQ aperture.
		Same format as the register section.
+2 −0
Original line number Diff line number Diff line
@@ -392,6 +392,7 @@ bool mipi_dsi_packet_format_is_short(u8 type)
	case MIPI_DSI_DCS_SHORT_WRITE:
	case MIPI_DSI_DCS_SHORT_WRITE_PARAM:
	case MIPI_DSI_DCS_READ:
	case MIPI_DSI_DCS_COMPRESSION_MODE:
	case MIPI_DSI_SET_MAXIMUM_RETURN_PACKET_SIZE:
		return true;
	}
@@ -410,6 +411,7 @@ EXPORT_SYMBOL(mipi_dsi_packet_format_is_short);
bool mipi_dsi_packet_format_is_long(u8 type)
{
	switch (type) {
	case MIPI_DSI_PPS_LONG_WRITE:
	case MIPI_DSI_NULL_PACKET:
	case MIPI_DSI_BLANKING_PACKET:
	case MIPI_DSI_GENERIC_LONG_WRITE:
+111 −0
Original line number Diff line number Diff line
@@ -30,6 +30,100 @@
#include <drm/drmP.h>
#include <drm/drm_print.h>

void __drm_puts_coredump(struct drm_printer *p, const char *str)
{
	struct drm_print_iterator *iterator = p->arg;
	ssize_t len;

	if (!iterator->remain)
		return;

	if (iterator->offset < iterator->start) {
		ssize_t copy;

		len = strlen(str);

		if (iterator->offset + len <= iterator->start) {
			iterator->offset += len;
			return;
		}

		copy = len - (iterator->start - iterator->offset);

		if (copy > iterator->remain)
			copy = iterator->remain;

		/* Copy out the bit of the string that we need */
		memcpy(iterator->data,
			str + (iterator->start - iterator->offset), copy);

		iterator->offset = iterator->start + copy;
		iterator->remain -= copy;
	} else {
		ssize_t pos = iterator->offset - iterator->start;

		len = min_t(ssize_t, strlen(str), iterator->remain);

		memcpy(iterator->data + pos, str, len);

		iterator->offset += len;
		iterator->remain -= len;
	}
}
EXPORT_SYMBOL(__drm_puts_coredump);

void __drm_printfn_coredump(struct drm_printer *p, struct va_format *vaf)
{
	struct drm_print_iterator *iterator = p->arg;
	size_t len;
	char *buf;

	if (!iterator->remain)
		return;

	/* Figure out how big the string will be */
	len = snprintf(NULL, 0, "%pV", vaf);

	/* This is the easiest path, we've already advanced beyond the offset */
	if (iterator->offset + len <= iterator->start) {
		iterator->offset += len;
		return;
	}

	/* Then check if we can directly copy into the target buffer */
	if ((iterator->offset >= iterator->start) && (len < iterator->remain)) {
		ssize_t pos = iterator->offset - iterator->start;

		snprintf(((char *) iterator->data) + pos,
			iterator->remain, "%pV", vaf);

		iterator->offset += len;
		iterator->remain -= len;

		return;
	}

	/*
	 * Finally, hit the slow path and make a temporary string to copy over
	 * using _drm_puts_coredump
	 */
	buf = kmalloc(len + 1, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
	if (!buf)
		return;

	snprintf(buf, len + 1, "%pV", vaf);
	__drm_puts_coredump(p, (const char *) buf);

	kfree(buf);
}
EXPORT_SYMBOL(__drm_printfn_coredump);

void __drm_puts_seq_file(struct drm_printer *p, const char *str)
{
	seq_puts(p->arg, str);
}
EXPORT_SYMBOL(__drm_puts_seq_file);

void __drm_printfn_seq_file(struct drm_printer *p, struct va_format *vaf)
{
	seq_printf(p->arg, "%pV", vaf);
@@ -48,6 +142,23 @@ void __drm_printfn_debug(struct drm_printer *p, struct va_format *vaf)
}
EXPORT_SYMBOL(__drm_printfn_debug);

/**
 * drm_puts - print a const string to a &drm_printer stream
 * @p: the &drm printer
 * @str: const string
 *
 * Allow &drm_printer types that have a constant string
 * option to use it.
 */
void drm_puts(struct drm_printer *p, const char *str)
{
	if (p->puts)
		p->puts(p, str);
	else
		drm_printf(p, "%s", str);
}
EXPORT_SYMBOL(drm_puts);

/**
 * drm_printf - print to a &drm_printer stream
 * @p: the &drm_printer
Loading