You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge tag 'drm-intel-next-2015-12-18' of git://anongit.freedesktop.org/drm-intel into drm-next
- fix atomic watermark recomputation logic (Maarten) - modeset sequence fixes for LPT (Ville) - more kbl enabling&prep work (Rodrigo, Wayne) - first bits for mst audio - page dirty tracking fixes from Dave Gordon - new get_eld hook from Takashi, also included in the sound tree - fixup cursor handling when placed at address 0 (Ville) - refactor VBT parsing code (Jani) - rpm wakelock debug infrastructure ( Imre) - fbdev is pinned again (Chris) - tune the busywait logic to avoid wasting cpu cycles (Chris) * tag 'drm-intel-next-2015-12-18' of git://anongit.freedesktop.org/drm-intel: (81 commits) drm/i915: Update DRIVER_DATE to 20151218 drm/i915/skl: Default to noncoherent access up to F0 drm/i915: Only spin whilst waiting on the current request drm/i915: Limit the busy wait on requests to 5us not 10ms! drm/i915: Break busywaiting for requests on pending signals drm/i915: don't enable autosuspend on platforms without RPM support drm/i915/backlight: prefer dev_priv over dev pointer drm/i915: Disable primary plane if we fail to reconstruct BIOS fb (v2) drm/i915: Pin the ifbdev for the info->system_base GGTT mmapping drm/i915: Set the map-and-fenceable flag for preallocated objects drm/i915: mdelay(10) considered harmful drm/i915: check that we are in an RPM atomic section in GGTT PTE updaters drm/i915: add support for checking RPM atomic sections drm/i915: check that we hold an RPM wakelock ref before we put it drm/i915: add support for checking if we hold an RPM reference drm/i915: use assert_rpm_wakelock_held instead of opencoding it drm/i915: add assert_rpm_wakelock_held helper drm/i915: remove HAS_RUNTIME_PM check from RPM get/put/assert helpers drm/i915: get a permanent RPM reference on platforms w/o RPM support drm/i915: refactor RPM disabling due to RC6 being disabled ...
This commit is contained in:
@@ -666,7 +666,9 @@ static int build_enum_path_resources(struct drm_dp_sideband_msg_tx *msg, int por
|
||||
}
|
||||
|
||||
static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_num,
|
||||
u8 vcpi, uint16_t pbn)
|
||||
u8 vcpi, uint16_t pbn,
|
||||
u8 number_sdp_streams,
|
||||
u8 *sdp_stream_sink)
|
||||
{
|
||||
struct drm_dp_sideband_msg_req_body req;
|
||||
memset(&req, 0, sizeof(req));
|
||||
@@ -674,6 +676,9 @@ static int build_allocate_payload(struct drm_dp_sideband_msg_tx *msg, int port_n
|
||||
req.u.allocate_payload.port_number = port_num;
|
||||
req.u.allocate_payload.vcpi = vcpi;
|
||||
req.u.allocate_payload.pbn = pbn;
|
||||
req.u.allocate_payload.number_sdp_streams = number_sdp_streams;
|
||||
memcpy(req.u.allocate_payload.sdp_stream_sink, sdp_stream_sink,
|
||||
number_sdp_streams);
|
||||
drm_dp_encode_sideband_req(&req, msg);
|
||||
msg->path_msg = true;
|
||||
return 0;
|
||||
@@ -1562,6 +1567,8 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_sideband_msg_tx *txmsg;
|
||||
struct drm_dp_mst_branch *mstb;
|
||||
int len, ret;
|
||||
u8 sinks[DRM_DP_MAX_SDP_STREAMS];
|
||||
int i;
|
||||
|
||||
mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent);
|
||||
if (!mstb)
|
||||
@@ -1573,10 +1580,13 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr,
|
||||
goto fail_put;
|
||||
}
|
||||
|
||||
for (i = 0; i < port->num_sdp_streams; i++)
|
||||
sinks[i] = i;
|
||||
|
||||
txmsg->dst = mstb;
|
||||
len = build_allocate_payload(txmsg, port->port_num,
|
||||
id,
|
||||
pbn);
|
||||
pbn, port->num_sdp_streams, sinks);
|
||||
|
||||
drm_dp_queue_down_tx(mgr, txmsg);
|
||||
|
||||
@@ -2260,6 +2270,27 @@ out:
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_mst_detect_port);
|
||||
|
||||
/**
|
||||
* drm_dp_mst_port_has_audio() - Check whether port has audio capability or not
|
||||
* @mgr: manager for this port
|
||||
* @port: unverified pointer to a port.
|
||||
*
|
||||
* This returns whether the port supports audio or not.
|
||||
*/
|
||||
bool drm_dp_mst_port_has_audio(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_mst_port *port)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
port = drm_dp_get_validated_port_ref(mgr, port);
|
||||
if (!port)
|
||||
return ret;
|
||||
ret = port->has_audio;
|
||||
drm_dp_put_port(port);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_dp_mst_port_has_audio);
|
||||
|
||||
/**
|
||||
* drm_dp_mst_get_edid() - get EDID for an MST port
|
||||
* @connector: toplevel connector to get EDID for
|
||||
@@ -2285,6 +2316,7 @@ struct edid *drm_dp_mst_get_edid(struct drm_connector *connector, struct drm_dp_
|
||||
edid = drm_get_edid(connector, &port->aux.ddc);
|
||||
drm_mode_connector_set_tile_property(connector);
|
||||
}
|
||||
port->has_audio = drm_detect_monitor_audio(edid);
|
||||
drm_dp_put_port(port);
|
||||
return edid;
|
||||
}
|
||||
@@ -2568,7 +2600,7 @@ static void drm_dp_mst_dump_mstb(struct seq_file *m,
|
||||
|
||||
seq_printf(m, "%smst: %p, %d\n", prefix, mstb, mstb->num_ports);
|
||||
list_for_each_entry(port, &mstb->ports, next) {
|
||||
seq_printf(m, "%sport: %d: ddps: %d ldps: %d, %p, conn: %p\n", prefix, port->port_num, port->ddps, port->ldps, port, port->connector);
|
||||
seq_printf(m, "%sport: %d: ddps: %d ldps: %d, sdp: %d/%d, %p, conn: %p\n", prefix, port->port_num, port->ddps, port->ldps, port->num_sdp_streams, port->num_sdp_stream_sinks, port, port->connector);
|
||||
if (port->mstb)
|
||||
drm_dp_mst_dump_mstb(m, port->mstb);
|
||||
}
|
||||
|
||||
@@ -129,11 +129,11 @@ struct intel_dvo_dev_ops {
|
||||
void (*dump_regs)(struct intel_dvo_device *dvo);
|
||||
};
|
||||
|
||||
extern struct intel_dvo_dev_ops sil164_ops;
|
||||
extern struct intel_dvo_dev_ops ch7xxx_ops;
|
||||
extern struct intel_dvo_dev_ops ivch_ops;
|
||||
extern struct intel_dvo_dev_ops tfp410_ops;
|
||||
extern struct intel_dvo_dev_ops ch7017_ops;
|
||||
extern struct intel_dvo_dev_ops ns2501_ops;
|
||||
extern const struct intel_dvo_dev_ops sil164_ops;
|
||||
extern const struct intel_dvo_dev_ops ch7xxx_ops;
|
||||
extern const struct intel_dvo_dev_ops ivch_ops;
|
||||
extern const struct intel_dvo_dev_ops tfp410_ops;
|
||||
extern const struct intel_dvo_dev_ops ch7017_ops;
|
||||
extern const struct intel_dvo_dev_ops ns2501_ops;
|
||||
|
||||
#endif /* _INTEL_DVO_H */
|
||||
|
||||
@@ -402,7 +402,7 @@ static void ch7017_destroy(struct intel_dvo_device *dvo)
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops ch7017_ops = {
|
||||
const struct intel_dvo_dev_ops ch7017_ops = {
|
||||
.init = ch7017_init,
|
||||
.detect = ch7017_detect,
|
||||
.mode_valid = ch7017_mode_valid,
|
||||
|
||||
@@ -356,7 +356,7 @@ static void ch7xxx_destroy(struct intel_dvo_device *dvo)
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops ch7xxx_ops = {
|
||||
const struct intel_dvo_dev_ops ch7xxx_ops = {
|
||||
.init = ch7xxx_init,
|
||||
.detect = ch7xxx_detect,
|
||||
.mode_valid = ch7xxx_mode_valid,
|
||||
|
||||
@@ -490,7 +490,7 @@ static void ivch_destroy(struct intel_dvo_device *dvo)
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops ivch_ops = {
|
||||
const struct intel_dvo_dev_ops ivch_ops = {
|
||||
.init = ivch_init,
|
||||
.dpms = ivch_dpms,
|
||||
.get_hw_state = ivch_get_hw_state,
|
||||
|
||||
@@ -698,7 +698,7 @@ static void ns2501_destroy(struct intel_dvo_device *dvo)
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops ns2501_ops = {
|
||||
const struct intel_dvo_dev_ops ns2501_ops = {
|
||||
.init = ns2501_init,
|
||||
.detect = ns2501_detect,
|
||||
.mode_valid = ns2501_mode_valid,
|
||||
|
||||
@@ -267,7 +267,7 @@ static void sil164_destroy(struct intel_dvo_device *dvo)
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops sil164_ops = {
|
||||
const struct intel_dvo_dev_ops sil164_ops = {
|
||||
.init = sil164_init,
|
||||
.detect = sil164_detect,
|
||||
.mode_valid = sil164_mode_valid,
|
||||
|
||||
@@ -306,7 +306,7 @@ static void tfp410_destroy(struct intel_dvo_device *dvo)
|
||||
}
|
||||
}
|
||||
|
||||
struct intel_dvo_dev_ops tfp410_ops = {
|
||||
const struct intel_dvo_dev_ops tfp410_ops = {
|
||||
.init = tfp410_init,
|
||||
.detect = tfp410_detect,
|
||||
.mode_valid = tfp410_mode_valid,
|
||||
|
||||
@@ -1142,8 +1142,34 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
|
||||
MEMSTAT_VID_SHIFT);
|
||||
seq_printf(m, "Current P-state: %d\n",
|
||||
(rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT);
|
||||
} else if (IS_GEN6(dev) || (IS_GEN7(dev) && !IS_VALLEYVIEW(dev)) ||
|
||||
IS_BROADWELL(dev) || IS_GEN9(dev)) {
|
||||
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
|
||||
u32 freq_sts;
|
||||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
|
||||
seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts);
|
||||
seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq);
|
||||
|
||||
seq_printf(m, "actual GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff));
|
||||
|
||||
seq_printf(m, "current GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq));
|
||||
|
||||
seq_printf(m, "max GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.max_freq));
|
||||
|
||||
seq_printf(m, "min GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.min_freq));
|
||||
|
||||
seq_printf(m, "idle GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq));
|
||||
|
||||
seq_printf(m,
|
||||
"efficient (RPe) frequency: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
} else if (INTEL_INFO(dev)->gen >= 6) {
|
||||
u32 rp_state_limits;
|
||||
u32 gt_perf_status;
|
||||
u32 rp_state_cap;
|
||||
@@ -1284,33 +1310,6 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
|
||||
seq_printf(m,
|
||||
"efficient (RPe) frequency: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
|
||||
} else if (IS_VALLEYVIEW(dev)) {
|
||||
u32 freq_sts;
|
||||
|
||||
mutex_lock(&dev_priv->rps.hw_lock);
|
||||
freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
|
||||
seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts);
|
||||
seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq);
|
||||
|
||||
seq_printf(m, "actual GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff));
|
||||
|
||||
seq_printf(m, "current GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq));
|
||||
|
||||
seq_printf(m, "max GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.max_freq));
|
||||
|
||||
seq_printf(m, "min GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.min_freq));
|
||||
|
||||
seq_printf(m, "idle GPU freq: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq));
|
||||
|
||||
seq_printf(m,
|
||||
"efficient (RPe) frequency: %d MHz\n",
|
||||
intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq));
|
||||
mutex_unlock(&dev_priv->rps.hw_lock);
|
||||
} else {
|
||||
seq_puts(m, "no P-state info available\n");
|
||||
}
|
||||
@@ -1602,7 +1601,7 @@ static int i915_drpc_info(struct seq_file *m, void *unused)
|
||||
struct drm_info_node *node = m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
return vlv_drpc_info(m);
|
||||
else if (INTEL_INFO(dev)->gen >= 6)
|
||||
return gen6_drpc_info(m);
|
||||
@@ -1743,7 +1742,7 @@ static int i915_sr_status(struct seq_file *m, void *unused)
|
||||
sr_enabled = I915_READ(INSTPM) & INSTPM_SELF_EN;
|
||||
else if (IS_PINEVIEW(dev))
|
||||
sr_enabled = I915_READ(DSPFW3) & PINEVIEW_SELF_REFRESH_EN;
|
||||
else if (IS_VALLEYVIEW(dev))
|
||||
else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
sr_enabled = I915_READ(FW_BLC_SELF_VLV) & FW_CSPWRDWNEN;
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
@@ -1843,25 +1842,31 @@ static int i915_opregion(struct seq_file *m, void *unused)
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_opregion *opregion = &dev_priv->opregion;
|
||||
void *data = kmalloc(OPREGION_SIZE, GFP_KERNEL);
|
||||
int ret;
|
||||
|
||||
if (data == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = mutex_lock_interruptible(&dev->struct_mutex);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (opregion->header) {
|
||||
memcpy(data, opregion->header, OPREGION_SIZE);
|
||||
seq_write(m, data, OPREGION_SIZE);
|
||||
}
|
||||
if (opregion->header)
|
||||
seq_write(m, opregion->header, OPREGION_SIZE);
|
||||
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
out:
|
||||
kfree(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_vbt(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct drm_info_node *node = m->private;
|
||||
struct drm_device *dev = node->minor->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct intel_opregion *opregion = &dev_priv->opregion;
|
||||
|
||||
if (opregion->vbt)
|
||||
seq_write(m, opregion->vbt, opregion->vbt_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2850,6 +2855,20 @@ static void intel_dp_info(struct seq_file *m,
|
||||
intel_panel_info(m, &intel_connector->panel);
|
||||
}
|
||||
|
||||
static void intel_dp_mst_info(struct seq_file *m,
|
||||
struct intel_connector *intel_connector)
|
||||
{
|
||||
struct intel_encoder *intel_encoder = intel_connector->encoder;
|
||||
struct intel_dp_mst_encoder *intel_mst =
|
||||
enc_to_mst(&intel_encoder->base);
|
||||
struct intel_digital_port *intel_dig_port = intel_mst->primary;
|
||||
struct intel_dp *intel_dp = &intel_dig_port->dp;
|
||||
bool has_audio = drm_dp_mst_port_has_audio(&intel_dp->mst_mgr,
|
||||
intel_connector->port);
|
||||
|
||||
seq_printf(m, "\taudio support: %s\n", yesno(has_audio));
|
||||
}
|
||||
|
||||
static void intel_hdmi_info(struct seq_file *m,
|
||||
struct intel_connector *intel_connector)
|
||||
{
|
||||
@@ -2893,6 +2912,8 @@ static void intel_connector_info(struct seq_file *m,
|
||||
intel_hdmi_info(m, intel_connector);
|
||||
else if (intel_encoder->type == INTEL_OUTPUT_LVDS)
|
||||
intel_lvds_info(m, intel_connector);
|
||||
else if (intel_encoder->type == INTEL_OUTPUT_DP_MST)
|
||||
intel_dp_mst_info(m, intel_connector);
|
||||
}
|
||||
|
||||
seq_printf(m, "\tmodes:\n");
|
||||
@@ -3983,7 +4004,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
|
||||
ret = i8xx_pipe_crc_ctl_reg(&source, &val);
|
||||
else if (INTEL_INFO(dev)->gen < 5)
|
||||
ret = i9xx_pipe_crc_ctl_reg(dev, pipe, &source, &val);
|
||||
else if (IS_VALLEYVIEW(dev))
|
||||
else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
ret = vlv_pipe_crc_ctl_reg(dev, pipe, &source, &val);
|
||||
else if (IS_GEN5(dev) || IS_GEN6(dev))
|
||||
ret = ilk_pipe_crc_ctl_reg(&source, &val);
|
||||
@@ -4052,7 +4073,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe,
|
||||
|
||||
if (IS_G4X(dev))
|
||||
g4x_undo_pipe_scramble_reset(dev, pipe);
|
||||
else if (IS_VALLEYVIEW(dev))
|
||||
else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
vlv_undo_pipe_scramble_reset(dev, pipe);
|
||||
else if (IS_HASWELL(dev) && pipe == PIPE_A)
|
||||
hsw_trans_edp_pipe_A_crc_wa(dev, false);
|
||||
@@ -4442,7 +4463,8 @@ static void wm_latency_show(struct seq_file *m, const uint16_t wm[8])
|
||||
* - WM1+ latency values in 0.5us units
|
||||
* - latencies are in us on gen9/vlv/chv
|
||||
*/
|
||||
if (INTEL_INFO(dev)->gen >= 9 || IS_VALLEYVIEW(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 9 || IS_VALLEYVIEW(dev) ||
|
||||
IS_CHERRYVIEW(dev))
|
||||
latency *= 10;
|
||||
else if (level > 0)
|
||||
latency *= 5;
|
||||
@@ -5316,6 +5338,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
|
||||
{"i915_ips_status", i915_ips_status, 0},
|
||||
{"i915_sr_status", i915_sr_status, 0},
|
||||
{"i915_opregion", i915_opregion, 0},
|
||||
{"i915_vbt", i915_vbt, 0},
|
||||
{"i915_gem_framebuffer", i915_gem_framebuffer_info, 0},
|
||||
{"i915_context_status", i915_context_status, 0},
|
||||
{"i915_dump_lrc", i915_dump_lrc, 0},
|
||||
|
||||
@@ -169,6 +169,9 @@ static int i915_getparam(struct drm_device *dev, void *data,
|
||||
case I915_PARAM_HAS_RESOURCE_STREAMER:
|
||||
value = HAS_RESOURCE_STREAMER(dev);
|
||||
break;
|
||||
case I915_PARAM_HAS_EXEC_SOFTPIN:
|
||||
value = 1;
|
||||
break;
|
||||
default:
|
||||
DRM_DEBUG("Unknown parameter %d\n", param->param);
|
||||
return -EINVAL;
|
||||
@@ -256,7 +259,7 @@ intel_setup_mchbar(struct drm_device *dev)
|
||||
u32 temp;
|
||||
bool enabled;
|
||||
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
return;
|
||||
|
||||
dev_priv->mchbar_need_disable = false;
|
||||
@@ -367,7 +370,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = intel_parse_bios(dev);
|
||||
ret = intel_bios_init(dev_priv);
|
||||
if (ret)
|
||||
DRM_INFO("failed to find VBIOS tables\n");
|
||||
|
||||
@@ -779,7 +782,7 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
|
||||
info->num_sprites[PIPE_A] = 2;
|
||||
info->num_sprites[PIPE_B] = 2;
|
||||
info->num_sprites[PIPE_C] = 1;
|
||||
} else if (IS_VALLEYVIEW(dev))
|
||||
} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
for_each_pipe(dev_priv, pipe)
|
||||
info->num_sprites[pipe] = 2;
|
||||
else
|
||||
@@ -791,7 +794,7 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
|
||||
info->num_pipes = 0;
|
||||
} else if (info->num_pipes > 0 &&
|
||||
(INTEL_INFO(dev)->gen == 7 || INTEL_INFO(dev)->gen == 8) &&
|
||||
!IS_VALLEYVIEW(dev)) {
|
||||
HAS_PCH_SPLIT(dev)) {
|
||||
u32 fuse_strap = I915_READ(FUSE_STRAP);
|
||||
u32 sfuse_strap = I915_READ(SFUSE_STRAP);
|
||||
|
||||
@@ -836,9 +839,6 @@ static void intel_device_info_runtime_init(struct drm_device *dev)
|
||||
|
||||
static void intel_init_dpio(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
if (!IS_VALLEYVIEW(dev_priv))
|
||||
return;
|
||||
|
||||
/*
|
||||
* IOSF_PORT_DPIO is used for VLV x2 PHY (DP/HDMI B and C),
|
||||
* CHV x1 PHY (DP/HDMI D)
|
||||
@@ -847,7 +847,7 @@ static void intel_init_dpio(struct drm_i915_private *dev_priv)
|
||||
if (IS_CHERRYVIEW(dev_priv)) {
|
||||
DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO_2;
|
||||
DPIO_PHY_IOSF_PORT(DPIO_PHY1) = IOSF_PORT_DPIO;
|
||||
} else {
|
||||
} else if (IS_VALLEYVIEW(dev_priv)) {
|
||||
DPIO_PHY_IOSF_PORT(DPIO_PHY0) = IOSF_PORT_DPIO;
|
||||
}
|
||||
}
|
||||
@@ -896,6 +896,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
|
||||
intel_pm_setup(dev);
|
||||
|
||||
intel_runtime_pm_get(dev_priv);
|
||||
|
||||
intel_display_crc_init(dev);
|
||||
|
||||
i915_dump_device_info(dev_priv);
|
||||
@@ -1085,6 +1087,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
|
||||
|
||||
i915_audio_component_init(dev_priv);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
out_power_well:
|
||||
@@ -1120,6 +1124,9 @@ free_priv:
|
||||
kmem_cache_destroy(dev_priv->requests);
|
||||
kmem_cache_destroy(dev_priv->vmas);
|
||||
kmem_cache_destroy(dev_priv->objects);
|
||||
|
||||
intel_runtime_pm_put(dev_priv);
|
||||
|
||||
kfree(dev_priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ static const struct intel_device_info intel_cherryview_info = {
|
||||
.gen = 8, .num_pipes = 3,
|
||||
.need_gfx_hws = 1, .has_hotplug = 1,
|
||||
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING,
|
||||
.is_valleyview = 1,
|
||||
.is_cherryview = 1,
|
||||
.display_mmio_offset = VLV_DISPLAY_BASE,
|
||||
GEN_CHV_PIPEOFFSETS,
|
||||
CURSOR_OFFSETS,
|
||||
@@ -543,15 +543,12 @@ bool i915_semaphore_is_enabled(struct drm_device *dev)
|
||||
static void intel_suspend_encoders(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
struct drm_device *dev = dev_priv->dev;
|
||||
struct drm_encoder *encoder;
|
||||
struct intel_encoder *encoder;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
|
||||
struct intel_encoder *intel_encoder = to_intel_encoder(encoder);
|
||||
|
||||
if (intel_encoder->suspend)
|
||||
intel_encoder->suspend(intel_encoder);
|
||||
}
|
||||
for_each_intel_encoder(dev, encoder)
|
||||
if (encoder->suspend)
|
||||
encoder->suspend(encoder);
|
||||
drm_modeset_unlock_all(dev);
|
||||
}
|
||||
|
||||
@@ -580,6 +577,8 @@ static int i915_drm_suspend(struct drm_device *dev)
|
||||
dev_priv->modeset_restore = MODESET_SUSPENDED;
|
||||
mutex_unlock(&dev_priv->modeset_restore_lock);
|
||||
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
/* We do a lot of poking in a lot of registers, make sure they work
|
||||
* properly. */
|
||||
intel_display_set_init_power(dev_priv, true);
|
||||
@@ -592,7 +591,7 @@ static int i915_drm_suspend(struct drm_device *dev)
|
||||
if (error) {
|
||||
dev_err(&dev->pdev->dev,
|
||||
"GEM idle failed, resume might fail\n");
|
||||
return error;
|
||||
goto out;
|
||||
}
|
||||
|
||||
intel_guc_suspend(dev);
|
||||
@@ -635,7 +634,10 @@ static int i915_drm_suspend(struct drm_device *dev)
|
||||
if (HAS_CSR(dev_priv))
|
||||
flush_work(&dev_priv->csr.work);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
|
||||
@@ -644,6 +646,8 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
|
||||
bool fw_csr;
|
||||
int ret;
|
||||
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
fw_csr = suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload;
|
||||
/*
|
||||
* In case of firmware assisted context save/restore don't manually
|
||||
@@ -662,7 +666,7 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
|
||||
if (!fw_csr)
|
||||
intel_power_domains_init_hw(dev_priv, true);
|
||||
|
||||
return ret;
|
||||
goto out;
|
||||
}
|
||||
|
||||
pci_disable_device(drm_dev->pdev);
|
||||
@@ -683,7 +687,10 @@ static int i915_drm_suspend_late(struct drm_device *drm_dev, bool hibernation)
|
||||
|
||||
dev_priv->suspended_to_idle = suspend_to_idle(dev_priv);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int i915_suspend_switcheroo(struct drm_device *dev, pm_message_t state)
|
||||
@@ -714,6 +721,8 @@ static int i915_drm_resume(struct drm_device *dev)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
i915_gem_restore_gtt_mappings(dev);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
@@ -778,6 +787,8 @@ static int i915_drm_resume(struct drm_device *dev)
|
||||
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -802,7 +813,9 @@ static int i915_drm_resume_early(struct drm_device *dev)
|
||||
|
||||
pci_set_master(dev->pdev);
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv))
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
ret = vlv_resume_prepare(dev_priv, false);
|
||||
if (ret)
|
||||
DRM_ERROR("Resume prepare failed: %d, continuing anyway\n",
|
||||
@@ -823,6 +836,8 @@ static int i915_drm_resume_early(struct drm_device *dev)
|
||||
out:
|
||||
dev_priv->suspended_to_idle = false;
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1455,6 +1470,9 @@ static int intel_runtime_suspend(struct device *device)
|
||||
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
/*
|
||||
* We are safe here against re-faults, since the fault handler takes
|
||||
* an RPM reference.
|
||||
@@ -1462,6 +1480,8 @@ static int intel_runtime_suspend(struct device *device)
|
||||
i915_gem_release_all_mmaps(dev_priv);
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
|
||||
cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
|
||||
|
||||
intel_guc_suspend(dev);
|
||||
|
||||
intel_suspend_gt_powersave(dev);
|
||||
@@ -1472,11 +1492,15 @@ static int intel_runtime_suspend(struct device *device)
|
||||
DRM_ERROR("Runtime suspend failed, disabling it (%d)\n", ret);
|
||||
intel_runtime_pm_enable_interrupts(dev_priv);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
cancel_delayed_work_sync(&dev_priv->gpu_error.hangcheck_work);
|
||||
intel_uncore_forcewake_reset(dev, false);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count));
|
||||
dev_priv->pm.suspended = true;
|
||||
|
||||
/*
|
||||
@@ -1520,6 +1544,9 @@ static int intel_runtime_resume(struct device *device)
|
||||
|
||||
DRM_DEBUG_KMS("Resuming device\n");
|
||||
|
||||
WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count));
|
||||
disable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
intel_opregion_notify_adapter(dev, PCI_D0);
|
||||
dev_priv->pm.suspended = false;
|
||||
|
||||
@@ -1532,7 +1559,7 @@ static int intel_runtime_resume(struct device *device)
|
||||
ret = bxt_resume_prepare(dev_priv);
|
||||
else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
||||
hsw_disable_pc8(dev_priv);
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
ret = vlv_resume_prepare(dev_priv, true);
|
||||
|
||||
/*
|
||||
@@ -1549,11 +1576,13 @@ static int intel_runtime_resume(struct device *device)
|
||||
* power well, so hpd is reinitialized from there. For
|
||||
* everyone else do it here.
|
||||
*/
|
||||
if (!IS_VALLEYVIEW(dev_priv))
|
||||
if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv))
|
||||
intel_hpd_init(dev_priv);
|
||||
|
||||
intel_enable_gt_powersave(dev);
|
||||
|
||||
enable_rpm_wakeref_asserts(dev_priv);
|
||||
|
||||
if (ret)
|
||||
DRM_ERROR("Runtime resume failed, disabling it (%d)\n", ret);
|
||||
else
|
||||
@@ -1574,7 +1603,7 @@ static int intel_suspend_complete(struct drm_i915_private *dev_priv)
|
||||
ret = bxt_suspend_complete(dev_priv);
|
||||
else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv))
|
||||
ret = hsw_suspend_complete(dev_priv);
|
||||
else if (IS_VALLEYVIEW(dev_priv))
|
||||
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
ret = vlv_suspend_complete(dev_priv);
|
||||
else
|
||||
ret = 0;
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <uapi/drm/i915_drm.h>
|
||||
#include <uapi/drm/drm_fourcc.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include "i915_reg.h"
|
||||
#include "intel_bios.h"
|
||||
#include "intel_ringbuffer.h"
|
||||
@@ -57,7 +58,7 @@
|
||||
|
||||
#define DRIVER_NAME "i915"
|
||||
#define DRIVER_DESC "Intel Graphics"
|
||||
#define DRIVER_DATE "20151204"
|
||||
#define DRIVER_DATE "20151218"
|
||||
|
||||
#undef WARN_ON
|
||||
/* Many gcc seem to no see through this and fall over :( */
|
||||
@@ -457,7 +458,9 @@ struct intel_opregion {
|
||||
u32 swsci_gbda_sub_functions;
|
||||
u32 swsci_sbcb_sub_functions;
|
||||
struct opregion_asle *asle;
|
||||
void *vbt;
|
||||
void *rvda;
|
||||
const void *vbt;
|
||||
u32 vbt_size;
|
||||
u32 *lid_state;
|
||||
struct work_struct asle_work;
|
||||
};
|
||||
@@ -763,6 +766,7 @@ struct intel_csr {
|
||||
func(is_crestline) sep \
|
||||
func(is_ivybridge) sep \
|
||||
func(is_valleyview) sep \
|
||||
func(is_cherryview) sep \
|
||||
func(is_haswell) sep \
|
||||
func(is_skylake) sep \
|
||||
func(is_broxton) sep \
|
||||
@@ -1601,6 +1605,8 @@ struct skl_wm_level {
|
||||
* For more, read the Documentation/power/runtime_pm.txt.
|
||||
*/
|
||||
struct i915_runtime_pm {
|
||||
atomic_t wakeref_count;
|
||||
atomic_t atomic_seq;
|
||||
bool suspended;
|
||||
bool irqs_enabled;
|
||||
};
|
||||
@@ -1944,6 +1950,8 @@ struct drm_i915_private {
|
||||
/* perform PHY state sanity checks? */
|
||||
bool chv_phy_assert[2];
|
||||
|
||||
struct intel_encoder *dig_port_map[I915_MAX_PORTS];
|
||||
|
||||
/*
|
||||
* NOTE: This is the dri1/ums dungeon, don't add stuff here. Your patch
|
||||
* will be rejected. Instead look for a better place.
|
||||
@@ -2181,8 +2189,17 @@ struct drm_i915_gem_request {
|
||||
struct drm_i915_private *i915;
|
||||
struct intel_engine_cs *ring;
|
||||
|
||||
/** GEM sequence number associated with this request. */
|
||||
uint32_t seqno;
|
||||
/** GEM sequence number associated with the previous request,
|
||||
* when the HWS breadcrumb is equal to this the GPU is processing
|
||||
* this request.
|
||||
*/
|
||||
u32 previous_seqno;
|
||||
|
||||
/** GEM sequence number associated with this request,
|
||||
* when the HWS breadcrumb is equal or greater than this the GPU
|
||||
* has finished processing this request.
|
||||
*/
|
||||
u32 seqno;
|
||||
|
||||
/** Position in the ringbuffer of the start of the request */
|
||||
u32 head;
|
||||
@@ -2455,9 +2472,9 @@ struct drm_i915_cmd_table {
|
||||
INTEL_DEVID(dev) == 0x0152 || \
|
||||
INTEL_DEVID(dev) == 0x015a)
|
||||
#define IS_VALLEYVIEW(dev) (INTEL_INFO(dev)->is_valleyview)
|
||||
#define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
|
||||
#define IS_CHERRYVIEW(dev) (INTEL_INFO(dev)->is_cherryview)
|
||||
#define IS_HASWELL(dev) (INTEL_INFO(dev)->is_haswell)
|
||||
#define IS_BROADWELL(dev) (!INTEL_INFO(dev)->is_valleyview && IS_GEN8(dev))
|
||||
#define IS_BROADWELL(dev) (!INTEL_INFO(dev)->is_cherryview && IS_GEN8(dev))
|
||||
#define IS_SKYLAKE(dev) (INTEL_INFO(dev)->is_skylake)
|
||||
#define IS_BROXTON(dev) (INTEL_INFO(dev)->is_broxton)
|
||||
#define IS_KABYLAKE(dev) (INTEL_INFO(dev)->is_kabylake)
|
||||
@@ -2488,6 +2505,14 @@ struct drm_i915_cmd_table {
|
||||
#define IS_SKL_ULX(dev) (INTEL_DEVID(dev) == 0x190E || \
|
||||
INTEL_DEVID(dev) == 0x1915 || \
|
||||
INTEL_DEVID(dev) == 0x191E)
|
||||
#define IS_KBL_ULT(dev) (INTEL_DEVID(dev) == 0x5906 || \
|
||||
INTEL_DEVID(dev) == 0x5913 || \
|
||||
INTEL_DEVID(dev) == 0x5916 || \
|
||||
INTEL_DEVID(dev) == 0x5921 || \
|
||||
INTEL_DEVID(dev) == 0x5926)
|
||||
#define IS_KBL_ULX(dev) (INTEL_DEVID(dev) == 0x590E || \
|
||||
INTEL_DEVID(dev) == 0x5915 || \
|
||||
INTEL_DEVID(dev) == 0x591E)
|
||||
#define IS_SKL_GT3(dev) (IS_SKYLAKE(dev) && \
|
||||
(INTEL_DEVID(dev) & 0x00F0) == 0x0020)
|
||||
#define IS_SKL_GT4(dev) (IS_SKYLAKE(dev) && \
|
||||
@@ -2584,20 +2609,22 @@ struct drm_i915_cmd_table {
|
||||
IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
|
||||
#define HAS_RUNTIME_PM(dev) (IS_GEN6(dev) || IS_HASWELL(dev) || \
|
||||
IS_BROADWELL(dev) || IS_VALLEYVIEW(dev) || \
|
||||
IS_SKYLAKE(dev) || IS_KABYLAKE(dev))
|
||||
IS_CHERRYVIEW(dev) || IS_SKYLAKE(dev) || \
|
||||
IS_KABYLAKE(dev))
|
||||
#define HAS_RC6(dev) (INTEL_INFO(dev)->gen >= 6)
|
||||
#define HAS_RC6p(dev) (INTEL_INFO(dev)->gen == 6 || IS_IVYBRIDGE(dev))
|
||||
|
||||
#define HAS_CSR(dev) (IS_GEN9(dev))
|
||||
|
||||
#define HAS_GUC_UCODE(dev) (IS_GEN9(dev))
|
||||
#define HAS_GUC_SCHED(dev) (IS_GEN9(dev))
|
||||
#define HAS_GUC_UCODE(dev) (IS_GEN9(dev) && !IS_KABYLAKE(dev))
|
||||
#define HAS_GUC_SCHED(dev) (IS_GEN9(dev) && !IS_KABYLAKE(dev))
|
||||
|
||||
#define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \
|
||||
INTEL_INFO(dev)->gen >= 8)
|
||||
|
||||
#define HAS_CORE_RING_FREQ(dev) (INTEL_INFO(dev)->gen >= 6 && \
|
||||
!IS_VALLEYVIEW(dev) && !IS_BROXTON(dev))
|
||||
!IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) && \
|
||||
!IS_BROXTON(dev))
|
||||
|
||||
#define INTEL_PCH_DEVICE_ID_MASK 0xff00
|
||||
#define INTEL_PCH_IBX_DEVICE_ID_TYPE 0x3b00
|
||||
@@ -2620,7 +2647,8 @@ struct drm_i915_cmd_table {
|
||||
#define HAS_PCH_NOP(dev) (INTEL_PCH_TYPE(dev) == PCH_NOP)
|
||||
#define HAS_PCH_SPLIT(dev) (INTEL_PCH_TYPE(dev) != PCH_NONE)
|
||||
|
||||
#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->gen < 5 || IS_VALLEYVIEW(dev))
|
||||
#define HAS_GMCH_DISPLAY(dev) (INTEL_INFO(dev)->gen < 5 || \
|
||||
IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
|
||||
/* DPF == dynamic parity feature */
|
||||
#define HAS_L3_DPF(dev) (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
|
||||
@@ -2860,6 +2888,7 @@ void i915_gem_vma_destroy(struct i915_vma *vma);
|
||||
#define PIN_UPDATE (1<<5)
|
||||
#define PIN_ZONE_4G (1<<6)
|
||||
#define PIN_HIGH (1<<7)
|
||||
#define PIN_OFFSET_FIXED (1<<8)
|
||||
#define PIN_OFFSET_MASK (~4095)
|
||||
int __must_check
|
||||
i915_gem_object_pin(struct drm_i915_gem_object *obj,
|
||||
@@ -2874,6 +2903,7 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
|
||||
|
||||
int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level,
|
||||
u32 flags);
|
||||
void __i915_vma_set_map_and_fenceable(struct i915_vma *vma);
|
||||
int __must_check i915_vma_unbind(struct i915_vma *vma);
|
||||
/*
|
||||
* BEWARE: Do not use the function below unless you can _absolutely_
|
||||
@@ -2894,6 +2924,9 @@ static inline int __sg_page_count(struct scatterlist *sg)
|
||||
return sg->length >> PAGE_SHIFT;
|
||||
}
|
||||
|
||||
struct page *
|
||||
i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n);
|
||||
|
||||
static inline struct page *
|
||||
i915_gem_object_get_page(struct drm_i915_gem_object *obj, int n)
|
||||
{
|
||||
@@ -2945,15 +2978,17 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2)
|
||||
return (int32_t)(seq1 - seq2) >= 0;
|
||||
}
|
||||
|
||||
static inline bool i915_gem_request_started(struct drm_i915_gem_request *req,
|
||||
bool lazy_coherency)
|
||||
{
|
||||
u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency);
|
||||
return i915_seqno_passed(seqno, req->previous_seqno);
|
||||
}
|
||||
|
||||
static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req,
|
||||
bool lazy_coherency)
|
||||
{
|
||||
u32 seqno;
|
||||
|
||||
BUG_ON(req == NULL);
|
||||
|
||||
seqno = req->ring->get_seqno(req->ring, lazy_coherency);
|
||||
|
||||
u32 seqno = req->ring->get_seqno(req->ring, lazy_coherency);
|
||||
return i915_seqno_passed(seqno, req->seqno);
|
||||
}
|
||||
|
||||
@@ -3205,6 +3240,7 @@ int __must_check i915_gem_evict_something(struct drm_device *dev,
|
||||
unsigned long start,
|
||||
unsigned long end,
|
||||
unsigned flags);
|
||||
int __must_check i915_gem_evict_for_vma(struct i915_vma *target);
|
||||
int i915_gem_evict_vm(struct i915_address_space *vm, bool do_idle);
|
||||
|
||||
/* belongs in i915_gem_gtt.h */
|
||||
@@ -3333,6 +3369,10 @@ static inline bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter)
|
||||
}
|
||||
extern void intel_i2c_reset(struct drm_device *dev);
|
||||
|
||||
/* intel_bios.c */
|
||||
int intel_bios_init(struct drm_i915_private *dev_priv);
|
||||
bool intel_bios_is_valid_vbt(const void *buf, size_t size);
|
||||
|
||||
/* intel_opregion.c */
|
||||
#ifdef CONFIG_ACPI
|
||||
extern int intel_opregion_setup(struct drm_device *dev);
|
||||
@@ -3511,7 +3551,7 @@ __raw_write(64, q)
|
||||
|
||||
static inline i915_reg_t i915_vgacntrl_reg(struct drm_device *dev)
|
||||
{
|
||||
if (IS_VALLEYVIEW(dev))
|
||||
if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev))
|
||||
return VLV_VGACNTRL;
|
||||
else if (INTEL_INFO(dev)->gen >= 5)
|
||||
return CPU_VGACNTRL;
|
||||
|
||||
+149
-67
@@ -1146,23 +1146,74 @@ static bool missed_irq(struct drm_i915_private *dev_priv,
|
||||
return test_bit(ring->id, &dev_priv->gpu_error.missed_irq_rings);
|
||||
}
|
||||
|
||||
static int __i915_spin_request(struct drm_i915_gem_request *req)
|
||||
static unsigned long local_clock_us(unsigned *cpu)
|
||||
{
|
||||
unsigned long t;
|
||||
|
||||
/* Cheaply and approximately convert from nanoseconds to microseconds.
|
||||
* The result and subsequent calculations are also defined in the same
|
||||
* approximate microseconds units. The principal source of timing
|
||||
* error here is from the simple truncation.
|
||||
*
|
||||
* Note that local_clock() is only defined wrt to the current CPU;
|
||||
* the comparisons are no longer valid if we switch CPUs. Instead of
|
||||
* blocking preemption for the entire busywait, we can detect the CPU
|
||||
* switch and use that as indicator of system load and a reason to
|
||||
* stop busywaiting, see busywait_stop().
|
||||
*/
|
||||
*cpu = get_cpu();
|
||||
t = local_clock() >> 10;
|
||||
put_cpu();
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
static bool busywait_stop(unsigned long timeout, unsigned cpu)
|
||||
{
|
||||
unsigned this_cpu;
|
||||
|
||||
if (time_after(local_clock_us(&this_cpu), timeout))
|
||||
return true;
|
||||
|
||||
return this_cpu != cpu;
|
||||
}
|
||||
|
||||
static int __i915_spin_request(struct drm_i915_gem_request *req, int state)
|
||||
{
|
||||
unsigned long timeout;
|
||||
unsigned cpu;
|
||||
|
||||
if (i915_gem_request_get_ring(req)->irq_refcount)
|
||||
/* When waiting for high frequency requests, e.g. during synchronous
|
||||
* rendering split between the CPU and GPU, the finite amount of time
|
||||
* required to set up the irq and wait upon it limits the response
|
||||
* rate. By busywaiting on the request completion for a short while we
|
||||
* can service the high frequency waits as quick as possible. However,
|
||||
* if it is a slow request, we want to sleep as quickly as possible.
|
||||
* The tradeoff between waiting and sleeping is roughly the time it
|
||||
* takes to sleep on a request, on the order of a microsecond.
|
||||
*/
|
||||
|
||||
if (req->ring->irq_refcount)
|
||||
return -EBUSY;
|
||||
|
||||
timeout = jiffies + 1;
|
||||
/* Only spin if we know the GPU is processing this request */
|
||||
if (!i915_gem_request_started(req, true))
|
||||
return -EAGAIN;
|
||||
|
||||
timeout = local_clock_us(&cpu) + 5;
|
||||
while (!need_resched()) {
|
||||
if (i915_gem_request_completed(req, true))
|
||||
return 0;
|
||||
|
||||
if (time_after_eq(jiffies, timeout))
|
||||
if (signal_pending_state(state, current))
|
||||
break;
|
||||
|
||||
if (busywait_stop(timeout, cpu))
|
||||
break;
|
||||
|
||||
cpu_relax_lowlatency();
|
||||
}
|
||||
|
||||
if (i915_gem_request_completed(req, false))
|
||||
return 0;
|
||||
|
||||
@@ -1197,6 +1248,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
const bool irq_test_in_progress =
|
||||
ACCESS_ONCE(dev_priv->gpu_error.test_irq_rings) & intel_ring_flag(ring);
|
||||
int state = interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE;
|
||||
DEFINE_WAIT(wait);
|
||||
unsigned long timeout_expire;
|
||||
s64 before, now;
|
||||
@@ -1229,7 +1281,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
|
||||
before = ktime_get_raw_ns();
|
||||
|
||||
/* Optimistic spin for the next jiffie before touching IRQs */
|
||||
ret = __i915_spin_request(req);
|
||||
ret = __i915_spin_request(req, state);
|
||||
if (ret == 0)
|
||||
goto out;
|
||||
|
||||
@@ -1241,8 +1293,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
|
||||
for (;;) {
|
||||
struct timer_list timer;
|
||||
|
||||
prepare_to_wait(&ring->irq_queue, &wait,
|
||||
interruptible ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
|
||||
prepare_to_wait(&ring->irq_queue, &wait, state);
|
||||
|
||||
/* We need to check whether any gpu reset happened in between
|
||||
* the caller grabbing the seqno and now ... */
|
||||
@@ -1260,7 +1311,7 @@ int __i915_wait_request(struct drm_i915_gem_request *req,
|
||||
break;
|
||||
}
|
||||
|
||||
if (interruptible && signal_pending(current)) {
|
||||
if (signal_pending_state(state, current)) {
|
||||
ret = -ERESTARTSYS;
|
||||
break;
|
||||
}
|
||||
@@ -2554,6 +2605,7 @@ void __i915_add_request(struct drm_i915_gem_request *request,
|
||||
request->batch_obj = obj;
|
||||
|
||||
request->emitted_jiffies = jiffies;
|
||||
request->previous_seqno = ring->last_submitted_seqno;
|
||||
ring->last_submitted_seqno = request->seqno;
|
||||
list_add_tail(&request->list, &ring->request_list);
|
||||
|
||||
@@ -2765,20 +2817,13 @@ static void i915_gem_reset_ring_cleanup(struct drm_i915_private *dev_priv,
|
||||
|
||||
if (i915.enable_execlists) {
|
||||
spin_lock_irq(&ring->execlist_lock);
|
||||
while (!list_empty(&ring->execlist_queue)) {
|
||||
struct drm_i915_gem_request *submit_req;
|
||||
|
||||
submit_req = list_first_entry(&ring->execlist_queue,
|
||||
struct drm_i915_gem_request,
|
||||
execlist_link);
|
||||
list_del(&submit_req->execlist_link);
|
||||
/* list_splice_tail_init checks for empty lists */
|
||||
list_splice_tail_init(&ring->execlist_queue,
|
||||
&ring->execlist_retired_req_list);
|
||||
|
||||
if (submit_req->ctx != ring->default_context)
|
||||
intel_lr_context_unpin(submit_req);
|
||||
|
||||
i915_gem_request_unreference(submit_req);
|
||||
}
|
||||
spin_unlock_irq(&ring->execlist_lock);
|
||||
intel_execlists_retire_requests(ring);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3480,30 +3525,50 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
|
||||
if (IS_ERR(vma))
|
||||
goto err_unpin;
|
||||
|
||||
if (flags & PIN_HIGH) {
|
||||
search_flag = DRM_MM_SEARCH_BELOW;
|
||||
alloc_flag = DRM_MM_CREATE_TOP;
|
||||
if (flags & PIN_OFFSET_FIXED) {
|
||||
uint64_t offset = flags & PIN_OFFSET_MASK;
|
||||
|
||||
if (offset & (alignment - 1) || offset + size > end) {
|
||||
ret = -EINVAL;
|
||||
goto err_free_vma;
|
||||
}
|
||||
vma->node.start = offset;
|
||||
vma->node.size = size;
|
||||
vma->node.color = obj->cache_level;
|
||||
ret = drm_mm_reserve_node(&vm->mm, &vma->node);
|
||||
if (ret) {
|
||||
ret = i915_gem_evict_for_vma(vma);
|
||||
if (ret == 0)
|
||||
ret = drm_mm_reserve_node(&vm->mm, &vma->node);
|
||||
}
|
||||
if (ret)
|
||||
goto err_free_vma;
|
||||
} else {
|
||||
search_flag = DRM_MM_SEARCH_DEFAULT;
|
||||
alloc_flag = DRM_MM_CREATE_DEFAULT;
|
||||
}
|
||||
if (flags & PIN_HIGH) {
|
||||
search_flag = DRM_MM_SEARCH_BELOW;
|
||||
alloc_flag = DRM_MM_CREATE_TOP;
|
||||
} else {
|
||||
search_flag = DRM_MM_SEARCH_DEFAULT;
|
||||
alloc_flag = DRM_MM_CREATE_DEFAULT;
|
||||
}
|
||||
|
||||
search_free:
|
||||
ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
|
||||
size, alignment,
|
||||
obj->cache_level,
|
||||
start, end,
|
||||
search_flag,
|
||||
alloc_flag);
|
||||
if (ret) {
|
||||
ret = i915_gem_evict_something(dev, vm, size, alignment,
|
||||
obj->cache_level,
|
||||
start, end,
|
||||
flags);
|
||||
if (ret == 0)
|
||||
goto search_free;
|
||||
ret = drm_mm_insert_node_in_range_generic(&vm->mm, &vma->node,
|
||||
size, alignment,
|
||||
obj->cache_level,
|
||||
start, end,
|
||||
search_flag,
|
||||
alloc_flag);
|
||||
if (ret) {
|
||||
ret = i915_gem_evict_something(dev, vm, size, alignment,
|
||||
obj->cache_level,
|
||||
start, end,
|
||||
flags);
|
||||
if (ret == 0)
|
||||
goto search_free;
|
||||
|
||||
goto err_free_vma;
|
||||
goto err_free_vma;
|
||||
}
|
||||
}
|
||||
if (WARN_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level))) {
|
||||
ret = -EINVAL;
|
||||
@@ -4094,9 +4159,36 @@ i915_vma_misplaced(struct i915_vma *vma, uint32_t alignment, uint64_t flags)
|
||||
vma->node.start < (flags & PIN_OFFSET_MASK))
|
||||
return true;
|
||||
|
||||
if (flags & PIN_OFFSET_FIXED &&
|
||||
vma->node.start != (flags & PIN_OFFSET_MASK))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)
|
||||
{
|
||||
struct drm_i915_gem_object *obj = vma->obj;
|
||||
bool mappable, fenceable;
|
||||
u32 fence_size, fence_alignment;
|
||||
|
||||
fence_size = i915_gem_get_gtt_size(obj->base.dev,
|
||||
obj->base.size,
|
||||
obj->tiling_mode);
|
||||
fence_alignment = i915_gem_get_gtt_alignment(obj->base.dev,
|
||||
obj->base.size,
|
||||
obj->tiling_mode,
|
||||
true);
|
||||
|
||||
fenceable = (vma->node.size == fence_size &&
|
||||
(vma->node.start & (fence_alignment - 1)) == 0);
|
||||
|
||||
mappable = (vma->node.start + fence_size <=
|
||||
to_i915(obj->base.dev)->gtt.mappable_end);
|
||||
|
||||
obj->map_and_fenceable = mappable && fenceable;
|
||||
}
|
||||
|
||||
static int
|
||||
i915_gem_object_do_pin(struct drm_i915_gem_object *obj,
|
||||
struct i915_address_space *vm,
|
||||
@@ -4164,25 +4256,7 @@ i915_gem_object_do_pin(struct drm_i915_gem_object *obj,
|
||||
|
||||
if (ggtt_view && ggtt_view->type == I915_GGTT_VIEW_NORMAL &&
|
||||
(bound ^ vma->bound) & GLOBAL_BIND) {
|
||||
bool mappable, fenceable;
|
||||
u32 fence_size, fence_alignment;
|
||||
|
||||
fence_size = i915_gem_get_gtt_size(obj->base.dev,
|
||||
obj->base.size,
|
||||
obj->tiling_mode);
|
||||
fence_alignment = i915_gem_get_gtt_alignment(obj->base.dev,
|
||||
obj->base.size,
|
||||
obj->tiling_mode,
|
||||
true);
|
||||
|
||||
fenceable = (vma->node.size == fence_size &&
|
||||
(vma->node.start & (fence_alignment - 1)) == 0);
|
||||
|
||||
mappable = (vma->node.start + fence_size <=
|
||||
dev_priv->gtt.mappable_end);
|
||||
|
||||
obj->map_and_fenceable = mappable && fenceable;
|
||||
|
||||
__i915_vma_set_map_and_fenceable(vma);
|
||||
WARN_ON(flags & PIN_MAPPABLE && !obj->map_and_fenceable);
|
||||
}
|
||||
|
||||
@@ -4842,14 +4916,6 @@ int i915_gem_init(struct drm_device *dev)
|
||||
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
|
||||
if (IS_VALLEYVIEW(dev)) {
|
||||
/* VLVA0 (potential hack), BIOS isn't actually waking us */
|
||||
I915_WRITE(VLV_GTLC_WAKE_CTRL, VLV_GTLC_ALLOWWAKEREQ);
|
||||
if (wait_for((I915_READ(VLV_GTLC_PW_STATUS) &
|
||||
VLV_GTLC_ALLOWWAKEACK), 10))
|
||||
DRM_DEBUG_DRIVER("allow wake ack timed out\n");
|
||||
}
|
||||
|
||||
if (!i915.enable_execlists) {
|
||||
dev_priv->gt.execbuf_submit = i915_gem_ringbuffer_submission;
|
||||
dev_priv->gt.init_rings = i915_gem_init_rings;
|
||||
@@ -4967,7 +5033,7 @@ i915_gem_load(struct drm_device *dev)
|
||||
|
||||
dev_priv->relative_constants_mode = I915_EXEC_CONSTANTS_REL_GENERAL;
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev))
|
||||
if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev))
|
||||
dev_priv->num_fence_regs = 32;
|
||||
else if (INTEL_INFO(dev)->gen >= 4 || IS_I945G(dev) || IS_I945GM(dev) || IS_G33(dev))
|
||||
dev_priv->num_fence_regs = 16;
|
||||
@@ -5188,6 +5254,21 @@ bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Like i915_gem_object_get_page(), but mark the returned page dirty */
|
||||
struct page *
|
||||
i915_gem_object_get_dirty_page(struct drm_i915_gem_object *obj, int n)
|
||||
{
|
||||
struct page *page;
|
||||
|
||||
/* Only default objects have per-page dirty tracking */
|
||||
if (WARN_ON(obj->ops != &i915_gem_object_ops))
|
||||
return NULL;
|
||||
|
||||
page = i915_gem_object_get_page(obj, n);
|
||||
set_page_dirty(page);
|
||||
return page;
|
||||
}
|
||||
|
||||
/* Allocate a new GEM object and fill it with the supplied data */
|
||||
struct drm_i915_gem_object *
|
||||
i915_gem_object_create_from_data(struct drm_device *dev,
|
||||
@@ -5213,6 +5294,7 @@ i915_gem_object_create_from_data(struct drm_device *dev,
|
||||
i915_gem_object_pin_pages(obj);
|
||||
sg = obj->pages;
|
||||
bytes = sg_copy_from_buffer(sg->sgl, sg->nents, (void *)data, size);
|
||||
obj->dirty = 1; /* Backing store is now out of date */
|
||||
i915_gem_object_unpin_pages(obj);
|
||||
|
||||
if (WARN_ON(bytes != size)) {
|
||||
|
||||
@@ -189,8 +189,15 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size)
|
||||
* shouldn't touch the cache level, especially as that
|
||||
* would make the object snooped which might have a
|
||||
* negative performance impact.
|
||||
*
|
||||
* Snooping is required on non-llc platforms in execlist
|
||||
* mode, but since all GGTT accesses use PAT entry 0 we
|
||||
* get snooping anyway regardless of cache_level.
|
||||
*
|
||||
* This is only applicable for Ivy Bridge devices since
|
||||
* later platforms don't have L3 control bits in the PTE.
|
||||
*/
|
||||
if (INTEL_INFO(dev)->gen >= 7 && !IS_VALLEYVIEW(dev)) {
|
||||
if (IS_IVYBRIDGE(dev)) {
|
||||
ret = i915_gem_object_set_cache_level(obj, I915_CACHE_L3_LLC);
|
||||
/* Failure shouldn't ever happen this early */
|
||||
if (WARN_ON(ret)) {
|
||||
|
||||
@@ -199,6 +199,45 @@ found:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
i915_gem_evict_for_vma(struct i915_vma *target)
|
||||
{
|
||||
struct drm_mm_node *node, *next;
|
||||
|
||||
list_for_each_entry_safe(node, next,
|
||||
&target->vm->mm.head_node.node_list,
|
||||
node_list) {
|
||||
struct i915_vma *vma;
|
||||
int ret;
|
||||
|
||||
if (node->start + node->size <= target->node.start)
|
||||
continue;
|
||||
if (node->start >= target->node.start + target->node.size)
|
||||
break;
|
||||
|
||||
vma = container_of(node, typeof(*vma), node);
|
||||
|
||||
if (vma->pin_count) {
|
||||
if (!vma->exec_entry || (vma->pin_count > 1))
|
||||
/* Object is pinned for some other use */
|
||||
return -EBUSY;
|
||||
|
||||
/* We need to evict a buffer in the same batch */
|
||||
if (vma->exec_entry->flags & EXEC_OBJECT_PINNED)
|
||||
/* Overlapping fixed objects in the same batch */
|
||||
return -EINVAL;
|
||||
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
ret = i915_vma_unbind(vma);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_gem_evict_vm - Evict all idle vmas from a vm
|
||||
* @vm: Address space to cleanse
|
||||
|
||||
@@ -264,7 +264,7 @@ relocate_entry_cpu(struct drm_i915_gem_object *obj,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vaddr = kmap_atomic(i915_gem_object_get_page(obj,
|
||||
vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj,
|
||||
reloc->offset >> PAGE_SHIFT));
|
||||
*(uint32_t *)(vaddr + page_offset) = lower_32_bits(delta);
|
||||
|
||||
@@ -273,7 +273,7 @@ relocate_entry_cpu(struct drm_i915_gem_object *obj,
|
||||
|
||||
if (page_offset == 0) {
|
||||
kunmap_atomic(vaddr);
|
||||
vaddr = kmap_atomic(i915_gem_object_get_page(obj,
|
||||
vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj,
|
||||
(reloc->offset + sizeof(uint32_t)) >> PAGE_SHIFT));
|
||||
}
|
||||
|
||||
@@ -355,7 +355,7 @@ relocate_entry_clflush(struct drm_i915_gem_object *obj,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
vaddr = kmap_atomic(i915_gem_object_get_page(obj,
|
||||
vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj,
|
||||
reloc->offset >> PAGE_SHIFT));
|
||||
clflush_write32(vaddr + page_offset, lower_32_bits(delta));
|
||||
|
||||
@@ -364,7 +364,7 @@ relocate_entry_clflush(struct drm_i915_gem_object *obj,
|
||||
|
||||
if (page_offset == 0) {
|
||||
kunmap_atomic(vaddr);
|
||||
vaddr = kmap_atomic(i915_gem_object_get_page(obj,
|
||||
vaddr = kmap_atomic(i915_gem_object_get_dirty_page(obj,
|
||||
(reloc->offset + sizeof(uint32_t)) >> PAGE_SHIFT));
|
||||
}
|
||||
|
||||
@@ -599,6 +599,8 @@ i915_gem_execbuffer_reserve_vma(struct i915_vma *vma,
|
||||
flags |= PIN_GLOBAL | PIN_MAPPABLE;
|
||||
if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS)
|
||||
flags |= BATCH_OFFSET_BIAS | PIN_OFFSET_BIAS;
|
||||
if (entry->flags & EXEC_OBJECT_PINNED)
|
||||
flags |= entry->offset | PIN_OFFSET_FIXED;
|
||||
if ((flags & PIN_MAPPABLE) == 0)
|
||||
flags |= PIN_HIGH;
|
||||
}
|
||||
@@ -670,6 +672,10 @@ eb_vma_misplaced(struct i915_vma *vma)
|
||||
vma->node.start & (entry->alignment - 1))
|
||||
return true;
|
||||
|
||||
if (entry->flags & EXEC_OBJECT_PINNED &&
|
||||
vma->node.start != entry->offset)
|
||||
return true;
|
||||
|
||||
if (entry->flags & __EXEC_OBJECT_NEEDS_BIAS &&
|
||||
vma->node.start < BATCH_OFFSET_BIAS)
|
||||
return true;
|
||||
@@ -695,6 +701,7 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring,
|
||||
struct i915_vma *vma;
|
||||
struct i915_address_space *vm;
|
||||
struct list_head ordered_vmas;
|
||||
struct list_head pinned_vmas;
|
||||
bool has_fenced_gpu_access = INTEL_INFO(ring->dev)->gen < 4;
|
||||
int retry;
|
||||
|
||||
@@ -703,6 +710,7 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring,
|
||||
vm = list_first_entry(vmas, struct i915_vma, exec_list)->vm;
|
||||
|
||||
INIT_LIST_HEAD(&ordered_vmas);
|
||||
INIT_LIST_HEAD(&pinned_vmas);
|
||||
while (!list_empty(vmas)) {
|
||||
struct drm_i915_gem_exec_object2 *entry;
|
||||
bool need_fence, need_mappable;
|
||||
@@ -721,7 +729,9 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring,
|
||||
obj->tiling_mode != I915_TILING_NONE;
|
||||
need_mappable = need_fence || need_reloc_mappable(vma);
|
||||
|
||||
if (need_mappable) {
|
||||
if (entry->flags & EXEC_OBJECT_PINNED)
|
||||
list_move_tail(&vma->exec_list, &pinned_vmas);
|
||||
else if (need_mappable) {
|
||||
entry->flags |= __EXEC_OBJECT_NEEDS_MAP;
|
||||
list_move(&vma->exec_list, &ordered_vmas);
|
||||
} else
|
||||
@@ -731,6 +741,7 @@ i915_gem_execbuffer_reserve(struct intel_engine_cs *ring,
|
||||
obj->base.pending_write_domain = 0;
|
||||
}
|
||||
list_splice(&ordered_vmas, vmas);
|
||||
list_splice(&pinned_vmas, vmas);
|
||||
|
||||
/* Attempt to pin all of the buffers into the GTT.
|
||||
* This is done in 3 phases:
|
||||
@@ -1317,7 +1328,8 @@ eb_get_batch(struct eb_vmas *eb)
|
||||
* Note that actual hangs have only been observed on gen7, but for
|
||||
* paranoia do it everywhere.
|
||||
*/
|
||||
vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS;
|
||||
if ((vma->exec_entry->flags & EXEC_OBJECT_PINNED) == 0)
|
||||
vma->exec_entry->flags |= __EXEC_OBJECT_NEEDS_BIAS;
|
||||
|
||||
return vma->obj;
|
||||
}
|
||||
|
||||
@@ -140,8 +140,7 @@ static int sanitize_enable_ppgtt(struct drm_device *dev, int enable_ppgtt)
|
||||
#endif
|
||||
|
||||
/* Early VLV doesn't have this */
|
||||
if (IS_VALLEYVIEW(dev) && !IS_CHERRYVIEW(dev) &&
|
||||
dev->pdev->revision < 0xb) {
|
||||
if (IS_VALLEYVIEW(dev) && dev->pdev->revision < 0xb) {
|
||||
DRM_DEBUG_DRIVER("disabling PPGTT on pre-B3 step VLV\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -770,10 +769,10 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
|
||||
gen8_ppgtt_clear_pte_range(vm, &ppgtt->pdp, start, length,
|
||||
scratch_pte);
|
||||
} else {
|
||||
uint64_t templ4, pml4e;
|
||||
uint64_t pml4e;
|
||||
struct i915_page_directory_pointer *pdp;
|
||||
|
||||
gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, templ4, pml4e) {
|
||||
gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) {
|
||||
gen8_ppgtt_clear_pte_range(vm, pdp, start, length,
|
||||
scratch_pte);
|
||||
}
|
||||
@@ -839,10 +838,10 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
|
||||
cache_level);
|
||||
} else {
|
||||
struct i915_page_directory_pointer *pdp;
|
||||
uint64_t templ4, pml4e;
|
||||
uint64_t pml4e;
|
||||
uint64_t length = (uint64_t)pages->orig_nents << PAGE_SHIFT;
|
||||
|
||||
gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, templ4, pml4e) {
|
||||
gen8_for_each_pml4e(pdp, &ppgtt->pml4, start, length, pml4e) {
|
||||
gen8_ppgtt_insert_pte_entries(vm, pdp, &sg_iter,
|
||||
start, cache_level);
|
||||
}
|
||||
@@ -1020,10 +1019,9 @@ static int gen8_ppgtt_alloc_pagetabs(struct i915_address_space *vm,
|
||||
{
|
||||
struct drm_device *dev = vm->dev;
|
||||
struct i915_page_table *pt;
|
||||
uint64_t temp;
|
||||
uint32_t pde;
|
||||
|
||||
gen8_for_each_pde(pt, pd, start, length, temp, pde) {
|
||||
gen8_for_each_pde(pt, pd, start, length, pde) {
|
||||
/* Don't reallocate page tables */
|
||||
if (test_bit(pde, pd->used_pdes)) {
|
||||
/* Scratch is never allocated this way */
|
||||
@@ -1082,13 +1080,12 @@ gen8_ppgtt_alloc_page_directories(struct i915_address_space *vm,
|
||||
{
|
||||
struct drm_device *dev = vm->dev;
|
||||
struct i915_page_directory *pd;
|
||||
uint64_t temp;
|
||||
uint32_t pdpe;
|
||||
uint32_t pdpes = I915_PDPES_PER_PDP(dev);
|
||||
|
||||
WARN_ON(!bitmap_empty(new_pds, pdpes));
|
||||
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
|
||||
if (test_bit(pdpe, pdp->used_pdpes))
|
||||
continue;
|
||||
|
||||
@@ -1136,12 +1133,11 @@ gen8_ppgtt_alloc_page_dirpointers(struct i915_address_space *vm,
|
||||
{
|
||||
struct drm_device *dev = vm->dev;
|
||||
struct i915_page_directory_pointer *pdp;
|
||||
uint64_t temp;
|
||||
uint32_t pml4e;
|
||||
|
||||
WARN_ON(!bitmap_empty(new_pdps, GEN8_PML4ES_PER_PML4));
|
||||
|
||||
gen8_for_each_pml4e(pdp, pml4, start, length, temp, pml4e) {
|
||||
gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
|
||||
if (!test_bit(pml4e, pml4->used_pml4es)) {
|
||||
pdp = alloc_pdp(dev);
|
||||
if (IS_ERR(pdp))
|
||||
@@ -1225,7 +1221,6 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
|
||||
struct i915_page_directory *pd;
|
||||
const uint64_t orig_start = start;
|
||||
const uint64_t orig_length = length;
|
||||
uint64_t temp;
|
||||
uint32_t pdpe;
|
||||
uint32_t pdpes = I915_PDPES_PER_PDP(dev);
|
||||
int ret;
|
||||
@@ -1252,7 +1247,7 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
|
||||
}
|
||||
|
||||
/* For every page directory referenced, allocate page tables */
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
|
||||
ret = gen8_ppgtt_alloc_pagetabs(vm, pd, start, length,
|
||||
new_page_tables + pdpe * BITS_TO_LONGS(I915_PDES));
|
||||
if (ret)
|
||||
@@ -1264,7 +1259,7 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
|
||||
|
||||
/* Allocations have completed successfully, so set the bitmaps, and do
|
||||
* the mappings. */
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
|
||||
gen8_pde_t *const page_directory = kmap_px(pd);
|
||||
struct i915_page_table *pt;
|
||||
uint64_t pd_len = length;
|
||||
@@ -1274,7 +1269,7 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
|
||||
/* Every pd should be allocated, we just did that above. */
|
||||
WARN_ON(!pd);
|
||||
|
||||
gen8_for_each_pde(pt, pd, pd_start, pd_len, temp, pde) {
|
||||
gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) {
|
||||
/* Same reasoning as pd */
|
||||
WARN_ON(!pt);
|
||||
WARN_ON(!pd_len);
|
||||
@@ -1311,6 +1306,8 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
|
||||
|
||||
err_out:
|
||||
while (pdpe--) {
|
||||
unsigned long temp;
|
||||
|
||||
for_each_set_bit(temp, new_page_tables + pdpe *
|
||||
BITS_TO_LONGS(I915_PDES), I915_PDES)
|
||||
free_pt(dev, pdp->page_directory[pdpe]->page_table[temp]);
|
||||
@@ -1333,7 +1330,7 @@ static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm,
|
||||
struct i915_hw_ppgtt *ppgtt =
|
||||
container_of(vm, struct i915_hw_ppgtt, base);
|
||||
struct i915_page_directory_pointer *pdp;
|
||||
uint64_t temp, pml4e;
|
||||
uint64_t pml4e;
|
||||
int ret = 0;
|
||||
|
||||
/* Do the pml4 allocations first, so we don't need to track the newly
|
||||
@@ -1352,7 +1349,7 @@ static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm,
|
||||
"The allocation has spanned more than 512GB. "
|
||||
"It is highly likely this is incorrect.");
|
||||
|
||||
gen8_for_each_pml4e(pdp, pml4, start, length, temp, pml4e) {
|
||||
gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
|
||||
WARN_ON(!pdp);
|
||||
|
||||
ret = gen8_alloc_va_range_3lvl(vm, pdp, start, length);
|
||||
@@ -1392,10 +1389,9 @@ static void gen8_dump_pdp(struct i915_page_directory_pointer *pdp,
|
||||
struct seq_file *m)
|
||||
{
|
||||
struct i915_page_directory *pd;
|
||||
uint64_t temp;
|
||||
uint32_t pdpe;
|
||||
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, temp, pdpe) {
|
||||
gen8_for_each_pdpe(pd, pdp, start, length, pdpe) {
|
||||
struct i915_page_table *pt;
|
||||
uint64_t pd_len = length;
|
||||
uint64_t pd_start = start;
|
||||
@@ -1405,7 +1401,7 @@ static void gen8_dump_pdp(struct i915_page_directory_pointer *pdp,
|
||||
continue;
|
||||
|
||||
seq_printf(m, "\tPDPE #%d\n", pdpe);
|
||||
gen8_for_each_pde(pt, pd, pd_start, pd_len, temp, pde) {
|
||||
gen8_for_each_pde(pt, pd, pd_start, pd_len, pde) {
|
||||
uint32_t pte;
|
||||
gen8_pte_t *pt_vaddr;
|
||||
|
||||
@@ -1455,11 +1451,11 @@ static void gen8_dump_ppgtt(struct i915_hw_ppgtt *ppgtt, struct seq_file *m)
|
||||
if (!USES_FULL_48BIT_PPGTT(vm->dev)) {
|
||||
gen8_dump_pdp(&ppgtt->pdp, start, length, scratch_pte, m);
|
||||
} else {
|
||||
uint64_t templ4, pml4e;
|
||||
uint64_t pml4e;
|
||||
struct i915_pml4 *pml4 = &ppgtt->pml4;
|
||||
struct i915_page_directory_pointer *pdp;
|
||||
|
||||
gen8_for_each_pml4e(pdp, pml4, start, length, templ4, pml4e) {
|
||||
gen8_for_each_pml4e(pdp, pml4, start, length, pml4e) {
|
||||
if (!test_bit(pml4e, pml4->used_pml4es))
|
||||
continue;
|
||||
|
||||
@@ -2355,6 +2351,9 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
|
||||
int i = 0;
|
||||
struct sg_page_iter sg_iter;
|
||||
dma_addr_t addr = 0; /* shut up gcc */
|
||||
int rpm_atomic_seq;
|
||||
|
||||
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
||||
|
||||
for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
|
||||
addr = sg_dma_address(sg_iter.sg) +
|
||||
@@ -2381,6 +2380,8 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
|
||||
*/
|
||||
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
|
||||
POSTING_READ(GFX_FLSH_CNTL_GEN6);
|
||||
|
||||
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2401,6 +2402,9 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
|
||||
int i = 0;
|
||||
struct sg_page_iter sg_iter;
|
||||
dma_addr_t addr = 0;
|
||||
int rpm_atomic_seq;
|
||||
|
||||
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
||||
|
||||
for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) {
|
||||
addr = sg_page_iter_dma_address(&sg_iter);
|
||||
@@ -2425,6 +2429,8 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
|
||||
*/
|
||||
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
|
||||
POSTING_READ(GFX_FLSH_CNTL_GEN6);
|
||||
|
||||
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
||||
}
|
||||
|
||||
static void gen8_ggtt_clear_range(struct i915_address_space *vm,
|
||||
@@ -2439,6 +2445,9 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
|
||||
(gen8_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
|
||||
const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
|
||||
int i;
|
||||
int rpm_atomic_seq;
|
||||
|
||||
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
||||
|
||||
if (WARN(num_entries > max_entries,
|
||||
"First entry = %d; Num entries = %d (max=%d)\n",
|
||||
@@ -2451,6 +2460,8 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
|
||||
for (i = 0; i < num_entries; i++)
|
||||
gen8_set_pte(>t_base[i], scratch_pte);
|
||||
readl(gtt_base);
|
||||
|
||||
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
||||
}
|
||||
|
||||
static void gen6_ggtt_clear_range(struct i915_address_space *vm,
|
||||
@@ -2465,6 +2476,9 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
|
||||
(gen6_pte_t __iomem *) dev_priv->gtt.gsm + first_entry;
|
||||
const int max_entries = gtt_total_entries(dev_priv->gtt) - first_entry;
|
||||
int i;
|
||||
int rpm_atomic_seq;
|
||||
|
||||
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
||||
|
||||
if (WARN(num_entries > max_entries,
|
||||
"First entry = %d; Num entries = %d (max=%d)\n",
|
||||
@@ -2477,6 +2491,8 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
|
||||
for (i = 0; i < num_entries; i++)
|
||||
iowrite32(scratch_pte, >t_base[i]);
|
||||
readl(gtt_base);
|
||||
|
||||
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
||||
}
|
||||
|
||||
static void i915_ggtt_insert_entries(struct i915_address_space *vm,
|
||||
@@ -2484,11 +2500,17 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm,
|
||||
uint64_t start,
|
||||
enum i915_cache_level cache_level, u32 unused)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = vm->dev->dev_private;
|
||||
unsigned int flags = (cache_level == I915_CACHE_NONE) ?
|
||||
AGP_USER_MEMORY : AGP_USER_CACHED_MEMORY;
|
||||
int rpm_atomic_seq;
|
||||
|
||||
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
||||
|
||||
intel_gtt_insert_sg_entries(pages, start >> PAGE_SHIFT, flags);
|
||||
|
||||
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
||||
|
||||
}
|
||||
|
||||
static void i915_ggtt_clear_range(struct i915_address_space *vm,
|
||||
@@ -2496,9 +2518,16 @@ static void i915_ggtt_clear_range(struct i915_address_space *vm,
|
||||
uint64_t length,
|
||||
bool unused)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = vm->dev->dev_private;
|
||||
unsigned first_entry = start >> PAGE_SHIFT;
|
||||
unsigned num_entries = length >> PAGE_SHIFT;
|
||||
int rpm_atomic_seq;
|
||||
|
||||
rpm_atomic_seq = assert_rpm_atomic_begin(dev_priv);
|
||||
|
||||
intel_gtt_clear_range(first_entry, num_entries);
|
||||
|
||||
assert_rpm_atomic_end(dev_priv, rpm_atomic_seq);
|
||||
}
|
||||
|
||||
static int ggtt_bind_vma(struct i915_vma *vma,
|
||||
@@ -2699,6 +2728,7 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
|
||||
return ret;
|
||||
}
|
||||
vma->bound |= GLOBAL_BIND;
|
||||
__i915_vma_set_map_and_fenceable(vma);
|
||||
list_add_tail(&vma->mm_list, &ggtt_vm->inactive_list);
|
||||
}
|
||||
|
||||
|
||||
@@ -455,32 +455,29 @@ static inline uint32_t gen6_pde_index(uint32_t addr)
|
||||
* between from start until start + length. On gen8+ it simply iterates
|
||||
* over every page directory entry in a page directory.
|
||||
*/
|
||||
#define gen8_for_each_pde(pt, pd, start, length, temp, iter) \
|
||||
for (iter = gen8_pde_index(start); \
|
||||
length > 0 && iter < I915_PDES ? \
|
||||
(pt = (pd)->page_table[iter]), 1 : 0; \
|
||||
iter++, \
|
||||
temp = ALIGN(start+1, 1 << GEN8_PDE_SHIFT) - start, \
|
||||
temp = min(temp, length), \
|
||||
start += temp, length -= temp)
|
||||
#define gen8_for_each_pde(pt, pd, start, length, iter) \
|
||||
for (iter = gen8_pde_index(start); \
|
||||
length > 0 && iter < I915_PDES && \
|
||||
(pt = (pd)->page_table[iter], true); \
|
||||
({ u64 temp = ALIGN(start+1, 1 << GEN8_PDE_SHIFT); \
|
||||
temp = min(temp - start, length); \
|
||||
start += temp, length -= temp; }), ++iter)
|
||||
|
||||
#define gen8_for_each_pdpe(pd, pdp, start, length, temp, iter) \
|
||||
for (iter = gen8_pdpe_index(start); \
|
||||
length > 0 && (iter < I915_PDPES_PER_PDP(dev)) ? \
|
||||
(pd = (pdp)->page_directory[iter]), 1 : 0; \
|
||||
iter++, \
|
||||
temp = ALIGN(start+1, 1 << GEN8_PDPE_SHIFT) - start, \
|
||||
temp = min(temp, length), \
|
||||
start += temp, length -= temp)
|
||||
#define gen8_for_each_pdpe(pd, pdp, start, length, iter) \
|
||||
for (iter = gen8_pdpe_index(start); \
|
||||
length > 0 && iter < I915_PDPES_PER_PDP(dev) && \
|
||||
(pd = (pdp)->page_directory[iter], true); \
|
||||
({ u64 temp = ALIGN(start+1, 1 << GEN8_PDPE_SHIFT); \
|
||||
temp = min(temp - start, length); \
|
||||
start += temp, length -= temp; }), ++iter)
|
||||
|
||||
#define gen8_for_each_pml4e(pdp, pml4, start, length, temp, iter) \
|
||||
for (iter = gen8_pml4e_index(start); \
|
||||
length > 0 && iter < GEN8_PML4ES_PER_PML4 ? \
|
||||
(pdp = (pml4)->pdps[iter]), 1 : 0; \
|
||||
iter++, \
|
||||
temp = ALIGN(start+1, 1ULL << GEN8_PML4E_SHIFT) - start, \
|
||||
temp = min(temp, length), \
|
||||
start += temp, length -= temp)
|
||||
#define gen8_for_each_pml4e(pdp, pml4, start, length, iter) \
|
||||
for (iter = gen8_pml4e_index(start); \
|
||||
length > 0 && iter < GEN8_PML4ES_PER_PML4 && \
|
||||
(pdp = (pml4)->pdps[iter], true); \
|
||||
({ u64 temp = ALIGN(start+1, 1ULL << GEN8_PML4E_SHIFT); \
|
||||
temp = min(temp - start, length); \
|
||||
start += temp, length -= temp; }), ++iter)
|
||||
|
||||
static inline uint32_t gen8_pte_index(uint64_t address)
|
||||
{
|
||||
|
||||
@@ -103,7 +103,7 @@ static int render_state_setup(struct render_state *so)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
page = sg_page(so->obj->pages->sgl);
|
||||
page = i915_gem_object_get_dirty_page(so->obj, 0);
|
||||
d = kmap(page);
|
||||
|
||||
while (i < rodata->batch_items) {
|
||||
|
||||
@@ -688,6 +688,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
|
||||
}
|
||||
|
||||
vma->bound |= GLOBAL_BIND;
|
||||
__i915_vma_set_map_and_fenceable(vma);
|
||||
list_add_tail(&vma->mm_list, &ggtt->inactive_list);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user