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

Commit 31aec642 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-fixes-2017-03-09' of...

Merge tag 'drm-intel-fixes-2017-03-09' of git://anongit.freedesktop.org/git/drm-intel into drm-fixes

flushing out gvt-g fixes

* tag 'drm-intel-fixes-2017-03-09' of git://anongit.freedesktop.org/git/drm-intel: (29 commits)
  drm/i915/gvt: change some gvt_err to gvt_dbg_cmd
  drm/i915/gvt: protect RO and Rsvd bits of virtual vgpu configuration space
  drm/i915/gvt: handle workload lifecycle properly
  drm/i915/gvt: fix an error for F_RO flag
  drm/i915/gvt: use pfn_valid for better checking
  drm/i915/gvt: set SFUSE_STRAP properly for vitual monitor detection
  drm/i915/gvt: fix an error for one register
  drm/i915/gvt: add more registers into handlers list
  drm/i915/gvt: have more registers with F_CMD_ACCESS flags set
  drm/i915/gvt: add some new MMIOs to cmd_access white list
  drm/i915/gvt: fix pcode mailbox write emulation of BDW
  drm/i915/gvt: add resolution definition for vGPU type
  drm/i915/gvt: Add more edid definition support
  drm/i915/gvt: adjust to fixed vGPU types
  drm/i915/gvt: remove unnecessary error msg from gtt write
  drm/i915/gvt: refine pcode write emulation
  drm/i915/gvt: clear the vGPU reset logic
  drm/i915/gvt: decrease priority of output msg for untracked mmio
  drm/i915/gvt: set default value to 0 for unhandled mmio regs
  drm/i915/gvt: add cmd_access to GEN7_HALF_SLICE_CHICKEN1
  ...
parents aa717ae1 70647f91
Loading
Loading
Loading
Loading
+54 −3
Original line number Original line Diff line number Diff line
@@ -41,6 +41,54 @@ enum {
	INTEL_GVT_PCI_BAR_MAX,
	INTEL_GVT_PCI_BAR_MAX,
};
};


/* bitmap for writable bits (RW or RW1C bits, but cannot co-exist in one
 * byte) byte by byte in standard pci configuration space. (not the full
 * 256 bytes.)
 */
static const u8 pci_cfg_space_rw_bmp[PCI_INTERRUPT_LINE + 4] = {
	[PCI_COMMAND]		= 0xff, 0x07,
	[PCI_STATUS]		= 0x00, 0xf9, /* the only one RW1C byte */
	[PCI_CACHE_LINE_SIZE]	= 0xff,
	[PCI_BASE_ADDRESS_0 ... PCI_CARDBUS_CIS - 1] = 0xff,
	[PCI_ROM_ADDRESS]	= 0x01, 0xf8, 0xff, 0xff,
	[PCI_INTERRUPT_LINE]	= 0xff,
};

/**
 * vgpu_pci_cfg_mem_write - write virtual cfg space memory
 *
 * Use this function to write virtual cfg space memory.
 * For standard cfg space, only RW bits can be changed,
 * and we emulates the RW1C behavior of PCI_STATUS register.
 */
static void vgpu_pci_cfg_mem_write(struct intel_vgpu *vgpu, unsigned int off,
				   u8 *src, unsigned int bytes)
{
	u8 *cfg_base = vgpu_cfg_space(vgpu);
	u8 mask, new, old;
	int i = 0;

	for (; i < bytes && (off + i < sizeof(pci_cfg_space_rw_bmp)); i++) {
		mask = pci_cfg_space_rw_bmp[off + i];
		old = cfg_base[off + i];
		new = src[i] & mask;

		/**
		 * The PCI_STATUS high byte has RW1C bits, here
		 * emulates clear by writing 1 for these bits.
		 * Writing a 0b to RW1C bits has no effect.
		 */
		if (off + i == PCI_STATUS + 1)
			new = (~new & old) & mask;

		cfg_base[off + i] = (old & ~mask) | new;
	}

	/* For other configuration space directly copy as it is. */
	if (i < bytes)
		memcpy(cfg_base + off + i, src + i, bytes - i);
}

/**
/**
 * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space read
 * intel_vgpu_emulate_cfg_read - emulate vGPU configuration space read
 *
 *
@@ -123,7 +171,7 @@ static int emulate_pci_command_write(struct intel_vgpu *vgpu,
	u8 changed = old ^ new;
	u8 changed = old ^ new;
	int ret;
	int ret;


	memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes);
	vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);
	if (!(changed & PCI_COMMAND_MEMORY))
	if (!(changed & PCI_COMMAND_MEMORY))
		return 0;
		return 0;


@@ -237,6 +285,9 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
{
{
	int ret;
	int ret;


	if (vgpu->failsafe)
		return 0;

	if (WARN_ON(bytes > 4))
	if (WARN_ON(bytes > 4))
		return -EINVAL;
		return -EINVAL;


@@ -274,10 +325,10 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
		if (ret)
		if (ret)
			return ret;
			return ret;


		memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes);
		vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);
		break;
		break;
	default:
	default:
		memcpy(vgpu_cfg_space(vgpu) + offset, p_data, bytes);
		vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);
		break;
		break;
	}
	}
	return 0;
	return 0;
+5 −5
Original line number Original line Diff line number Diff line
@@ -668,7 +668,7 @@ static inline void print_opcode(u32 cmd, int ring_id)
	if (d_info == NULL)
	if (d_info == NULL)
		return;
		return;


	gvt_err("opcode=0x%x %s sub_ops:",
	gvt_dbg_cmd("opcode=0x%x %s sub_ops:",
			cmd >> (32 - d_info->op_len), d_info->name);
			cmd >> (32 - d_info->op_len), d_info->name);


	for (i = 0; i < d_info->nr_sub_op; i++)
	for (i = 0; i < d_info->nr_sub_op; i++)
@@ -693,23 +693,23 @@ static void parser_exec_state_dump(struct parser_exec_state *s)
	int cnt = 0;
	int cnt = 0;
	int i;
	int i;


	gvt_err("  vgpu%d RING%d: ring_start(%08lx) ring_end(%08lx)"
	gvt_dbg_cmd("  vgpu%d RING%d: ring_start(%08lx) ring_end(%08lx)"
			" ring_head(%08lx) ring_tail(%08lx)\n", s->vgpu->id,
			" ring_head(%08lx) ring_tail(%08lx)\n", s->vgpu->id,
			s->ring_id, s->ring_start, s->ring_start + s->ring_size,
			s->ring_id, s->ring_start, s->ring_start + s->ring_size,
			s->ring_head, s->ring_tail);
			s->ring_head, s->ring_tail);


	gvt_err("  %s %s ip_gma(%08lx) ",
	gvt_dbg_cmd("  %s %s ip_gma(%08lx) ",
			s->buf_type == RING_BUFFER_INSTRUCTION ?
			s->buf_type == RING_BUFFER_INSTRUCTION ?
			"RING_BUFFER" : "BATCH_BUFFER",
			"RING_BUFFER" : "BATCH_BUFFER",
			s->buf_addr_type == GTT_BUFFER ?
			s->buf_addr_type == GTT_BUFFER ?
			"GTT" : "PPGTT", s->ip_gma);
			"GTT" : "PPGTT", s->ip_gma);


	if (s->ip_va == NULL) {
	if (s->ip_va == NULL) {
		gvt_err(" ip_va(NULL)");
		gvt_dbg_cmd(" ip_va(NULL)");
		return;
		return;
	}
	}


	gvt_err("  ip_va=%p: %08x %08x %08x %08x\n",
	gvt_dbg_cmd("  ip_va=%p: %08x %08x %08x %08x\n",
			s->ip_va, cmd_val(s, 0), cmd_val(s, 1),
			s->ip_va, cmd_val(s, 0), cmd_val(s, 1),
			cmd_val(s, 2), cmd_val(s, 3));
			cmd_val(s, 2), cmd_val(s, 3));


+94 −45
Original line number Original line Diff line number Diff line
@@ -83,8 +83,43 @@ static int pipe_is_enabled(struct intel_vgpu *vgpu, int pipe)
	return 0;
	return 0;
}
}


static unsigned char virtual_dp_monitor_edid[GVT_EDID_NUM][EDID_SIZE] = {
	{
/* EDID with 1024x768 as its resolution */
		/*Header*/
		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
		/* Vendor & Product Identification */
		0x22, 0xf0, 0x54, 0x29, 0x00, 0x00, 0x00, 0x00, 0x04, 0x17,
		/* Version & Revision */
		0x01, 0x04,
		/* Basic Display Parameters & Features */
		0xa5, 0x34, 0x20, 0x78, 0x23,
		/* Color Characteristics */
		0xfc, 0x81, 0xa4, 0x55, 0x4d, 0x9d, 0x25, 0x12, 0x50, 0x54,
		/* Established Timings: maximum resolution is 1024x768 */
		0x21, 0x08, 0x00,
		/* Standard Timings. All invalid */
		0x00, 0xc0, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00,
		0x00, 0x40, 0x00, 0x00, 0x00, 0x01,
		/* 18 Byte Data Blocks 1: invalid */
		0x00, 0x00, 0x80, 0xa0, 0x70, 0xb0,
		0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x06, 0x44, 0x21, 0x00, 0x00, 0x1a,
		/* 18 Byte Data Blocks 2: invalid */
		0x00, 0x00, 0x00, 0xfd, 0x00, 0x18, 0x3c, 0x18, 0x50, 0x11, 0x00, 0x0a,
		0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
		/* 18 Byte Data Blocks 3: invalid */
		0x00, 0x00, 0x00, 0xfc, 0x00, 0x48,
		0x50, 0x20, 0x5a, 0x52, 0x32, 0x34, 0x34, 0x30, 0x77, 0x0a, 0x20, 0x20,
		/* 18 Byte Data Blocks 4: invalid */
		0x00, 0x00, 0x00, 0xff, 0x00, 0x43, 0x4e, 0x34, 0x33, 0x30, 0x34, 0x30,
		0x44, 0x58, 0x51, 0x0a, 0x20, 0x20,
		/* Extension Block Count */
		0x00,
		/* Checksum */
		0xef,
	},
	{
/* EDID with 1920x1200 as its resolution */
/* EDID with 1920x1200 as its resolution */
static unsigned char virtual_dp_monitor_edid[] = {
		/*Header*/
		/*Header*/
		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
		0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
		/* Vendor & Product Identification */
		/* Vendor & Product Identification */
@@ -121,6 +156,7 @@ static unsigned char virtual_dp_monitor_edid[] = {
		0x00,
		0x00,
		/* Checksum */
		/* Checksum */
		0x45,
		0x45,
	},
};
};


#define DPCD_HEADER_SIZE        0xb
#define DPCD_HEADER_SIZE        0xb
@@ -140,14 +176,20 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
		vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTA_HOTPLUG_SPT |
		vgpu_vreg(vgpu, SDEISR) &= ~(SDE_PORTA_HOTPLUG_SPT |
				SDE_PORTE_HOTPLUG_SPT);
				SDE_PORTE_HOTPLUG_SPT);


	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B))
	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_B)) {
		vgpu_vreg(vgpu, SDEISR) |= SDE_PORTB_HOTPLUG_CPT;
		vgpu_vreg(vgpu, SDEISR) |= SDE_PORTB_HOTPLUG_CPT;
		vgpu_vreg(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIB_DETECTED;
	}


	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C))
	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_C)) {
		vgpu_vreg(vgpu, SDEISR) |= SDE_PORTC_HOTPLUG_CPT;
		vgpu_vreg(vgpu, SDEISR) |= SDE_PORTC_HOTPLUG_CPT;
		vgpu_vreg(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDIC_DETECTED;
	}


	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_D))
	if (intel_vgpu_has_monitor_on_port(vgpu, PORT_D)) {
		vgpu_vreg(vgpu, SDEISR) |= SDE_PORTD_HOTPLUG_CPT;
		vgpu_vreg(vgpu, SDEISR) |= SDE_PORTD_HOTPLUG_CPT;
		vgpu_vreg(vgpu, SFUSE_STRAP) |= SFUSE_STRAP_DDID_DETECTED;
	}


	if (IS_SKYLAKE(dev_priv) &&
	if (IS_SKYLAKE(dev_priv) &&
			intel_vgpu_has_monitor_on_port(vgpu, PORT_E)) {
			intel_vgpu_has_monitor_on_port(vgpu, PORT_E)) {
@@ -160,6 +202,8 @@ static void emulate_monitor_status_change(struct intel_vgpu *vgpu)
				GEN8_PORT_DP_A_HOTPLUG;
				GEN8_PORT_DP_A_HOTPLUG;
		else
		else
			vgpu_vreg(vgpu, SDEISR) |= SDE_PORTA_HOTPLUG_SPT;
			vgpu_vreg(vgpu, SDEISR) |= SDE_PORTA_HOTPLUG_SPT;

		vgpu_vreg(vgpu, DDI_BUF_CTL(PORT_A)) |= DDI_INIT_DISPLAY_DETECTED;
	}
	}
}
}


@@ -175,10 +219,13 @@ static void clean_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num)
}
}


static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num,
static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num,
		int type)
				    int type, unsigned int resolution)
{
{
	struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num);
	struct intel_vgpu_port *port = intel_vgpu_port(vgpu, port_num);


	if (WARN_ON(resolution >= GVT_EDID_NUM))
		return -EINVAL;

	port->edid = kzalloc(sizeof(*(port->edid)), GFP_KERNEL);
	port->edid = kzalloc(sizeof(*(port->edid)), GFP_KERNEL);
	if (!port->edid)
	if (!port->edid)
		return -ENOMEM;
		return -ENOMEM;
@@ -189,7 +236,7 @@ static int setup_virtual_dp_monitor(struct intel_vgpu *vgpu, int port_num,
		return -ENOMEM;
		return -ENOMEM;
	}
	}


	memcpy(port->edid->edid_block, virtual_dp_monitor_edid,
	memcpy(port->edid->edid_block, virtual_dp_monitor_edid[resolution],
			EDID_SIZE);
			EDID_SIZE);
	port->edid->data_valid = true;
	port->edid->data_valid = true;


@@ -322,16 +369,18 @@ void intel_vgpu_clean_display(struct intel_vgpu *vgpu)
 * Zero on success, negative error code if failed.
 * Zero on success, negative error code if failed.
 *
 *
 */
 */
int intel_vgpu_init_display(struct intel_vgpu *vgpu)
int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution)
{
{
	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;


	intel_vgpu_init_i2c_edid(vgpu);
	intel_vgpu_init_i2c_edid(vgpu);


	if (IS_SKYLAKE(dev_priv))
	if (IS_SKYLAKE(dev_priv))
		return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D);
		return setup_virtual_dp_monitor(vgpu, PORT_D, GVT_DP_D,
						resolution);
	else
	else
		return setup_virtual_dp_monitor(vgpu, PORT_B, GVT_DP_B);
		return setup_virtual_dp_monitor(vgpu, PORT_B, GVT_DP_B,
						resolution);
}
}


/**
/**
+19 −1
Original line number Original line Diff line number Diff line
@@ -154,10 +154,28 @@ struct intel_vgpu_port {
	int type;
	int type;
};
};


enum intel_vgpu_edid {
	GVT_EDID_1024_768,
	GVT_EDID_1920_1200,
	GVT_EDID_NUM,
};

static inline char *vgpu_edid_str(enum intel_vgpu_edid id)
{
	switch (id) {
	case GVT_EDID_1024_768:
		return "1024x768";
	case GVT_EDID_1920_1200:
		return "1920x1200";
	default:
		return "";
	}
}

void intel_gvt_emulate_vblank(struct intel_gvt *gvt);
void intel_gvt_emulate_vblank(struct intel_gvt *gvt);
void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt);
void intel_gvt_check_vblank_emulation(struct intel_gvt *gvt);


int intel_vgpu_init_display(struct intel_vgpu *vgpu);
int intel_vgpu_init_display(struct intel_vgpu *vgpu, u64 resolution);
void intel_vgpu_reset_display(struct intel_vgpu *vgpu);
void intel_vgpu_reset_display(struct intel_vgpu *vgpu);
void intel_vgpu_clean_display(struct intel_vgpu *vgpu);
void intel_vgpu_clean_display(struct intel_vgpu *vgpu);


+1 −1
Original line number Original line Diff line number Diff line
@@ -80,7 +80,7 @@ static int expose_firmware_sysfs(struct intel_gvt *gvt)
	int ret;
	int ret;


	size = sizeof(*h) + info->mmio_size + info->cfg_space_size - 1;
	size = sizeof(*h) + info->mmio_size + info->cfg_space_size - 1;
	firmware = vmalloc(size);
	firmware = vzalloc(size);
	if (!firmware)
	if (!firmware)
		return -ENOMEM;
		return -ENOMEM;


Loading