Merge tag 'drm-intel-next-2016-06-06' of git://anongit.freedesktop.org/drm-intel into drm-next

- some polish for the guc code (Dave Gordon)
- big refactoring of gen9 display clock handling code (Ville)
- refactoring work in the context code (Chris Wilson)
- give encoder/crtc/planes useful names for debug output (Ville)
- improvements to skl/kbl wm computation code (Mahesh Kumar)
- bunch of smaller improvements all over as usual

* tag 'drm-intel-next-2016-06-06' of git://anongit.freedesktop.org/drm-intel: (64 commits)
  drm/i915: Update DRIVER_DATE to 20160606
  drm/i915: Extract physical display dimensions from VBT
  drm/i915: Silence "unexpected child device config size" for VBT on 845g
  drm/i915/skl+: Use scaling amount for plane data rate calculation (v4)
  drm/i915/skl+: calculate plane pixel rate (v4)
  drm/i915/skl+: calculate ddb minimum allocation (v6)
  drm/i915: Don't try to calculate relative data rates during hw readout
  drm/i915: Only ignore eDP ports that are connected
  drm/i915: Update GEN6_PMINTRMSK setup with GuC enabled
  drm/i915: kill STANDARD/CURSOR plane screams
  drm/i915: Give encoders useful names
  drm/i915: Give meaningful names to all the planes
  drm/i915: Don't leak primary/cursor planes on crtc init failure
  drm/i915: Set crtc->name to "pipe A", "pipe B", etc.
  drm/i915: Use plane->name in debug prints
  drm/i915: Use crtc->name in debug messages
  drm/i915: Reject modeset if the dotclock is too high
  drm/i915: Fix NULL pointer deference when out of PLLs in IVB
  drm/i915/ilk: Don't disable SSC source if it's in use
  drm/i915/bxt: Sanitize CDCLK to fix breakage during S4 resume
  ...
This commit is contained in:
Dave Airlie 2016-06-09 12:11:29 +10:00
commit 5b735940aa
41 changed files with 1479 additions and 969 deletions

View file

@ -199,13 +199,6 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
seq_printf(m, " (frontbuffer: 0x%03x)", obj->frontbuffer_bits);
}
static void describe_ctx(struct seq_file *m, struct intel_context *ctx)
{
seq_putc(m, ctx->legacy_hw_ctx.initialized ? 'I' : 'i');
seq_putc(m, ctx->remap_slice ? 'R' : 'r');
seq_putc(m, ' ');
}
static int i915_gem_object_list_info(struct seq_file *m, void *data)
{
struct drm_info_node *node = m->private;
@ -424,6 +417,42 @@ static void print_batch_pool_stats(struct seq_file *m,
print_file_stats(m, "[k]batch pool", stats);
}
static int per_file_ctx_stats(int id, void *ptr, void *data)
{
struct i915_gem_context *ctx = ptr;
int n;
for (n = 0; n < ARRAY_SIZE(ctx->engine); n++) {
if (ctx->engine[n].state)
per_file_stats(0, ctx->engine[n].state, data);
if (ctx->engine[n].ringbuf)
per_file_stats(0, ctx->engine[n].ringbuf->obj, data);
}
return 0;
}
static void print_context_stats(struct seq_file *m,
struct drm_i915_private *dev_priv)
{
struct file_stats stats;
struct drm_file *file;
memset(&stats, 0, sizeof(stats));
mutex_lock(&dev_priv->dev->struct_mutex);
if (dev_priv->kernel_context)
per_file_ctx_stats(0, dev_priv->kernel_context, &stats);
list_for_each_entry(file, &dev_priv->dev->filelist, lhead) {
struct drm_i915_file_private *fpriv = file->driver_priv;
idr_for_each(&fpriv->context_idr, per_file_ctx_stats, &stats);
}
mutex_unlock(&dev_priv->dev->struct_mutex);
print_file_stats(m, "[k]contexts", stats);
}
#define count_vmas(list, member) do { \
list_for_each_entry(vma, list, member) { \
size += i915_gem_obj_total_ggtt_size(vma->obj); \
@ -528,10 +557,10 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
seq_putc(m, '\n');
print_batch_pool_stats(m, dev_priv);
mutex_unlock(&dev->struct_mutex);
mutex_lock(&dev->filelist_mutex);
print_context_stats(m, dev_priv);
list_for_each_entry_reverse(file, &dev->filelist, lhead) {
struct file_stats stats;
struct task_struct *task;
@ -1279,6 +1308,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused)
}
seq_printf(m, "PM IER=0x%08x IMR=0x%08x ISR=0x%08x IIR=0x%08x, MASK=0x%08x\n",
pm_ier, pm_imr, pm_isr, pm_iir, pm_mask);
seq_printf(m, "pm_intr_keep: 0x%08x\n", dev_priv->rps.pm_intr_keep);
seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status);
seq_printf(m, "Render p-state ratio: %d\n",
(gt_perf_status & (IS_GEN9(dev) ? 0x1ff00 : 0xff00)) >> 8);
@ -1989,8 +2019,7 @@ static int i915_context_status(struct seq_file *m, void *unused)
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *engine;
struct intel_context *ctx;
enum intel_engine_id id;
struct i915_gem_context *ctx;
int ret;
ret = mutex_lock_interruptible(&dev->struct_mutex);
@ -1998,32 +2027,36 @@ static int i915_context_status(struct seq_file *m, void *unused)
return ret;
list_for_each_entry(ctx, &dev_priv->context_list, link) {
if (!i915.enable_execlists &&
ctx->legacy_hw_ctx.rcs_state == NULL)
continue;
seq_printf(m, "HW context %u ", ctx->hw_id);
describe_ctx(m, ctx);
if (ctx == dev_priv->kernel_context)
seq_printf(m, "(kernel context) ");
if (IS_ERR(ctx->file_priv)) {
seq_puts(m, "(deleted) ");
} else if (ctx->file_priv) {
struct pid *pid = ctx->file_priv->file->pid;
struct task_struct *task;
if (i915.enable_execlists) {
seq_putc(m, '\n');
for_each_engine_id(engine, dev_priv, id) {
struct drm_i915_gem_object *ctx_obj =
ctx->engine[id].state;
struct intel_ringbuffer *ringbuf =
ctx->engine[id].ringbuf;
seq_printf(m, "%s: ", engine->name);
if (ctx_obj)
describe_obj(m, ctx_obj);
if (ringbuf)
describe_ctx_ringbuf(m, ringbuf);
seq_putc(m, '\n');
task = get_pid_task(pid, PIDTYPE_PID);
if (task) {
seq_printf(m, "(%s [%d]) ",
task->comm, task->pid);
put_task_struct(task);
}
} else {
describe_obj(m, ctx->legacy_hw_ctx.rcs_state);
seq_puts(m, "(kernel) ");
}
seq_putc(m, ctx->remap_slice ? 'R' : 'r');
seq_putc(m, '\n');
for_each_engine(engine, dev_priv) {
struct intel_context *ce = &ctx->engine[engine->id];
seq_printf(m, "%s: ", engine->name);
seq_putc(m, ce->initialised ? 'I' : 'i');
if (ce->state)
describe_obj(m, ce->state);
if (ce->ringbuf)
describe_ctx_ringbuf(m, ce->ringbuf);
seq_putc(m, '\n');
}
seq_putc(m, '\n');
@ -2035,13 +2068,13 @@ static int i915_context_status(struct seq_file *m, void *unused)
}
static void i915_dump_lrc_obj(struct seq_file *m,
struct intel_context *ctx,
struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state;
struct page *page;
uint32_t *reg_state;
int j;
struct drm_i915_gem_object *ctx_obj = ctx->engine[engine->id].state;
unsigned long ggtt_offset = 0;
seq_printf(m, "CONTEXT: %s %u\n", engine->name, ctx->hw_id);
@ -2083,7 +2116,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused)
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *engine;
struct intel_context *ctx;
struct i915_gem_context *ctx;
int ret;
if (!i915.enable_execlists) {
@ -2263,7 +2296,7 @@ static int i915_swizzle_info(struct seq_file *m, void *data)
static int per_file_ctx(int id, void *ptr, void *data)
{
struct intel_context *ctx = ptr;
struct i915_gem_context *ctx = ptr;
struct seq_file *m = data;
struct i915_hw_ppgtt *ppgtt = ctx->ppgtt;
@ -2504,6 +2537,7 @@ static void i915_guc_client_info(struct seq_file *m,
seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n",
client->wq_size, client->wq_offset, client->wq_tail);
seq_printf(m, "\tWork queue full: %u\n", client->no_wq_space);
seq_printf(m, "\tFailed to queue: %u\n", client->q_fail);
seq_printf(m, "\tFailed doorbell: %u\n", client->b_fail);
seq_printf(m, "\tLast submission result: %d\n", client->retcode);

View file

@ -507,7 +507,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
* working irqs for e.g. gmbus and dp aux transfers. */
intel_modeset_init(dev);
intel_guc_ucode_init(dev);
intel_guc_init(dev);
ret = i915_gem_init(dev);
if (ret)
@ -544,7 +544,7 @@ static int i915_load_modeset_init(struct drm_device *dev)
cleanup_gem:
i915_gem_fini(dev);
cleanup_irq:
intel_guc_ucode_fini(dev);
intel_guc_fini(dev);
drm_irq_uninstall(dev);
intel_teardown_gmbus(dev);
cleanup_csr:
@ -1307,7 +1307,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
intel_uncore_sanitize(dev_priv);
intel_opregion_setup(dev);
intel_opregion_setup(dev_priv);
i915_gem_load_init_fences(dev_priv);
@ -1376,7 +1376,7 @@ static void i915_driver_register(struct drm_i915_private *dev_priv)
if (INTEL_INFO(dev_priv)->num_pipes) {
/* Must be done after probing outputs */
intel_opregion_init(dev);
intel_opregion_register(dev_priv);
acpi_video_register();
}
@ -1395,7 +1395,7 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv)
i915_audio_component_cleanup(dev_priv);
intel_gpu_ips_teardown();
acpi_video_unregister();
intel_opregion_fini(dev_priv->dev);
intel_opregion_unregister(dev_priv);
i915_teardown_sysfs(dev_priv->dev);
i915_gem_shrinker_cleanup(dev_priv);
}
@ -1527,7 +1527,7 @@ int i915_driver_unload(struct drm_device *dev)
/* Flush any outstanding unpin_work. */
flush_workqueue(dev_priv->wq);
intel_guc_ucode_fini(dev);
intel_guc_fini(dev);
i915_gem_fini(dev);
intel_fbc_cleanup_cfb(dev_priv);

View file

@ -626,10 +626,10 @@ static int i915_drm_suspend(struct drm_device *dev)
i915_save_state(dev);
opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold;
intel_opregion_notify_adapter(dev, opregion_target_state);
intel_opregion_notify_adapter(dev_priv, opregion_target_state);
intel_uncore_forcewake_reset(dev_priv, false);
intel_opregion_fini(dev);
intel_opregion_unregister(dev_priv);
intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
@ -747,7 +747,7 @@ static int i915_drm_resume(struct drm_device *dev)
mutex_unlock(&dev->struct_mutex);
i915_restore_state(dev);
intel_opregion_setup(dev);
intel_opregion_setup(dev_priv);
intel_init_pch_refclk(dev);
drm_mode_config_reset(dev);
@ -792,7 +792,7 @@ static int i915_drm_resume(struct drm_device *dev)
/* Config may have changed between suspend and resume */
drm_helper_hpd_irq_event(dev);
intel_opregion_init(dev);
intel_opregion_register(dev_priv);
intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false);
@ -800,7 +800,7 @@ static int i915_drm_resume(struct drm_device *dev)
dev_priv->modeset_restore = MODESET_DONE;
mutex_unlock(&dev_priv->modeset_restore_lock);
intel_opregion_notify_adapter(dev, PCI_D0);
intel_opregion_notify_adapter(dev_priv, PCI_D0);
drm_kms_helper_poll_enable(dev);
@ -1588,14 +1588,14 @@ static int intel_runtime_suspend(struct device *device)
* FIXME: We really should find a document that references the arguments
* used below!
*/
if (IS_BROADWELL(dev)) {
if (IS_BROADWELL(dev_priv)) {
/*
* On Broadwell, if we use PCI_D1 the PCH DDI ports will stop
* being detected, and the call we do at intel_runtime_resume()
* won't be able to restore them. Since PCI_D3hot matches the
* actual specification and appears to be working, use it.
*/
intel_opregion_notify_adapter(dev, PCI_D3hot);
intel_opregion_notify_adapter(dev_priv, PCI_D3hot);
} else {
/*
* current versions of firmware which depend on this opregion
@ -1604,7 +1604,7 @@ static int intel_runtime_suspend(struct device *device)
* to distinguish it from notifications that might be sent via
* the suspend path.
*/
intel_opregion_notify_adapter(dev, PCI_D1);
intel_opregion_notify_adapter(dev_priv, PCI_D1);
}
assert_forcewakes_inactive(dev_priv);
@ -1628,7 +1628,7 @@ static int intel_runtime_resume(struct device *device)
WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count));
disable_rpm_wakeref_asserts(dev_priv);
intel_opregion_notify_adapter(dev, PCI_D0);
intel_opregion_notify_adapter(dev_priv, PCI_D0);
dev_priv->pm.suspended = false;
if (intel_uncore_unclaimed_mmio(dev_priv))
DRM_DEBUG_DRIVER("Unclaimed access during suspend, bios?\n");

View file

@ -66,7 +66,7 @@
#define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics"
#define DRIVER_DATE "20160522"
#define DRIVER_DATE "20160606"
#undef WARN_ON
/* Many gcc seem to no see through this and fall over :( */
@ -834,9 +834,8 @@ struct i915_ctx_hang_stats {
/* This must match up with the value previously used for execbuf2.rsvd1. */
#define DEFAULT_CONTEXT_HANDLE 0
#define CONTEXT_NO_ZEROMAP (1<<0)
/**
* struct intel_context - as the name implies, represents a context.
* struct i915_gem_context - as the name implies, represents a context.
* @ref: reference count.
* @user_handle: userspace tracking identity for this context.
* @remap_slice: l3 row remapping information.
@ -854,37 +853,33 @@ struct i915_ctx_hang_stats {
* Contexts are memory images used by the hardware to store copies of their
* internal state.
*/
struct intel_context {
struct i915_gem_context {
struct kref ref;
int user_handle;
uint8_t remap_slice;
struct drm_i915_private *i915;
int flags;
struct drm_i915_file_private *file_priv;
struct i915_ctx_hang_stats hang_stats;
struct i915_hw_ppgtt *ppgtt;
struct i915_ctx_hang_stats hang_stats;
/* Unique identifier for this context, used by the hw for tracking */
unsigned long flags;
unsigned hw_id;
u32 user_handle;
#define CONTEXT_NO_ZEROMAP (1<<0)
/* Legacy ring buffer submission */
struct {
struct drm_i915_gem_object *rcs_state;
bool initialized;
} legacy_hw_ctx;
/* Execlists */
struct {
struct intel_context {
struct drm_i915_gem_object *state;
struct intel_ringbuffer *ringbuf;
int pin_count;
struct i915_vma *lrc_vma;
u64 lrc_desc;
uint32_t *lrc_reg_state;
u64 lrc_desc;
int pin_count;
bool initialised;
} engine[I915_NUM_ENGINES];
struct list_head link;
u8 remap_slice;
};
enum fb_op_origin {
@ -1132,6 +1127,8 @@ struct intel_gen6_power_mgmt {
bool interrupts_enabled;
u32 pm_iir;
u32 pm_intr_keep;
/* Frequencies are stored in potentially platform dependent multiples.
* In other words, *_freq needs to be multiplied by X to be interesting.
* Soft limits are those which are used for the dynamic reclocking done
@ -1715,7 +1712,7 @@ struct i915_execbuffer_params {
uint64_t batch_obj_vm_offset;
struct intel_engine_cs *engine;
struct drm_i915_gem_object *batch_obj;
struct intel_context *ctx;
struct i915_gem_context *ctx;
struct drm_i915_gem_request *request;
};
@ -1765,6 +1762,7 @@ struct drm_i915_private {
wait_queue_head_t gmbus_wait_queue;
struct pci_dev *bridge_dev;
struct i915_gem_context *kernel_context;
struct intel_engine_cs engine[I915_NUM_ENGINES];
struct drm_i915_gem_object *semaphore_obj;
uint32_t last_seqno, next_seqno;
@ -1820,13 +1818,17 @@ struct drm_i915_private {
int num_fence_regs; /* 8 on pre-965, 16 otherwise */
unsigned int fsb_freq, mem_freq, is_ddr3;
unsigned int skl_boot_cdclk;
unsigned int skl_preferred_vco_freq;
unsigned int cdclk_freq, max_cdclk_freq, atomic_cdclk_freq;
unsigned int max_dotclk_freq;
unsigned int rawclk_freq;
unsigned int hpll_freq;
unsigned int czclk_freq;
struct {
unsigned int vco, ref;
} cdclk_pll;
/**
* wq - Driver workqueue for GEM.
*
@ -2018,8 +2020,6 @@ struct drm_i915_private {
void (*stop_engine)(struct intel_engine_cs *engine);
} gt;
struct intel_context *kernel_context;
/* perform PHY state sanity checks? */
bool chv_phy_assert[2];
@ -2386,7 +2386,7 @@ struct drm_i915_gem_request {
* i915_gem_request_free() will then decrement the refcount on the
* context.
*/
struct intel_context *ctx;
struct i915_gem_context *ctx;
struct intel_ringbuffer *ringbuf;
/**
@ -2398,7 +2398,7 @@ struct drm_i915_gem_request {
* we keep the previous context pinned until the following (this)
* request is retired.
*/
struct intel_context *previous_context;
struct i915_gem_context *previous_context;
/** Batch buffer related to this request if any (used for
error state dump only) */
@ -2442,7 +2442,7 @@ struct drm_i915_gem_request {
struct drm_i915_gem_request * __must_check
i915_gem_request_alloc(struct intel_engine_cs *engine,
struct intel_context *ctx);
struct i915_gem_context *ctx);
void i915_gem_request_free(struct kref *req_ref);
int i915_gem_request_add_to_client(struct drm_i915_gem_request *req,
struct drm_file *file);
@ -2807,8 +2807,14 @@ struct drm_i915_cmd_table {
#define HAS_CSR(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))
/*
* For now, anything with a GuC requires uCode loading, and then supports
* command submission once loaded. But these are logically independent
* properties, so we have separate macros to test them.
*/
#define HAS_GUC(dev) (IS_GEN9(dev) && !IS_KABYLAKE(dev))
#define HAS_GUC_UCODE(dev) (HAS_GUC(dev))
#define HAS_GUC_SCHED(dev) (HAS_GUC(dev))
#define HAS_RESOURCE_STREAMER(dev) (IS_HASWELL(dev) || \
INTEL_INFO(dev)->gen >= 8)
@ -3422,22 +3428,36 @@ void i915_gem_context_reset(struct drm_device *dev);
int i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
int i915_switch_context(struct drm_i915_gem_request *req);
struct intel_context *
i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
void i915_gem_context_free(struct kref *ctx_ref);
struct drm_i915_gem_object *
i915_gem_alloc_context_obj(struct drm_device *dev, size_t size);
static inline void i915_gem_context_reference(struct intel_context *ctx)
static inline struct i915_gem_context *
i915_gem_context_lookup(struct drm_i915_file_private *file_priv, u32 id)
{
struct i915_gem_context *ctx;
lockdep_assert_held(&file_priv->dev_priv->dev->struct_mutex);
ctx = idr_find(&file_priv->context_idr, id);
if (!ctx)
return ERR_PTR(-ENOENT);
return ctx;
}
static inline void i915_gem_context_reference(struct i915_gem_context *ctx)
{
kref_get(&ctx->ref);
}
static inline void i915_gem_context_unreference(struct intel_context *ctx)
static inline void i915_gem_context_unreference(struct i915_gem_context *ctx)
{
lockdep_assert_held(&ctx->i915->dev->struct_mutex);
kref_put(&ctx->ref, i915_gem_context_free);
}
static inline bool i915_gem_context_is_default(const struct intel_context *c)
static inline bool i915_gem_context_is_default(const struct i915_gem_context *c)
{
return c->user_handle == DEFAULT_CONTEXT_HANDLE;
}
@ -3607,19 +3627,19 @@ bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv,
/* intel_opregion.c */
#ifdef CONFIG_ACPI
extern int intel_opregion_setup(struct drm_device *dev);
extern void intel_opregion_init(struct drm_device *dev);
extern void intel_opregion_fini(struct drm_device *dev);
extern int intel_opregion_setup(struct drm_i915_private *dev_priv);
extern void intel_opregion_register(struct drm_i915_private *dev_priv);
extern void intel_opregion_unregister(struct drm_i915_private *dev_priv);
extern void intel_opregion_asle_intr(struct drm_i915_private *dev_priv);
extern int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
bool enable);
extern int intel_opregion_notify_adapter(struct drm_device *dev,
extern int intel_opregion_notify_adapter(struct drm_i915_private *dev_priv,
pci_power_t state);
extern int intel_opregion_get_panel_type(struct drm_device *dev);
extern int intel_opregion_get_panel_type(struct drm_i915_private *dev_priv);
#else
static inline int intel_opregion_setup(struct drm_device *dev) { return 0; }
static inline void intel_opregion_init(struct drm_device *dev) { return; }
static inline void intel_opregion_fini(struct drm_device *dev) { return; }
static inline int intel_opregion_setup(struct drm_i915_private *dev) { return 0; }
static inline void intel_opregion_init(struct drm_i915_private *dev) { }
static inline void intel_opregion_fini(struct drm_i915_private *dev) { }
static inline void intel_opregion_asle_intr(struct drm_i915_private *dev_priv)
{
}
@ -3629,11 +3649,11 @@ intel_opregion_notify_encoder(struct intel_encoder *intel_encoder, bool enable)
return 0;
}
static inline int
intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
intel_opregion_notify_adapter(struct drm_i915_private *dev, pci_power_t state)
{
return 0;
}
static inline int intel_opregion_get_panel_type(struct drm_device *dev)
static inline int intel_opregion_get_panel_type(struct drm_i915_private *dev)
{
return -ENODEV;
}

View file

@ -2692,7 +2692,7 @@ void __i915_add_request(struct drm_i915_gem_request *request,
}
static bool i915_context_is_banned(struct drm_i915_private *dev_priv,
const struct intel_context *ctx)
const struct i915_gem_context *ctx)
{
unsigned long elapsed;
@ -2717,7 +2717,7 @@ static bool i915_context_is_banned(struct drm_i915_private *dev_priv,
}
static void i915_set_reset_status(struct drm_i915_private *dev_priv,
struct intel_context *ctx,
struct i915_gem_context *ctx,
const bool guilty)
{
struct i915_ctx_hang_stats *hs;
@ -2745,7 +2745,7 @@ void i915_gem_request_free(struct kref *req_ref)
static inline int
__i915_gem_request_alloc(struct intel_engine_cs *engine,
struct intel_context *ctx,
struct i915_gem_context *ctx,
struct drm_i915_gem_request **req_out)
{
struct drm_i915_private *dev_priv = engine->i915;
@ -2821,7 +2821,7 @@ __i915_gem_request_alloc(struct intel_engine_cs *engine,
*/
struct drm_i915_gem_request *
i915_gem_request_alloc(struct intel_engine_cs *engine,
struct intel_context *ctx)
struct i915_gem_context *ctx)
{
struct drm_i915_gem_request *req;
int err;
@ -4886,13 +4886,10 @@ i915_gem_init_hw(struct drm_device *dev)
intel_mocs_init_l3cc_table(dev);
/* We can't enable contexts until all firmware is loaded */
if (HAS_GUC_UCODE(dev)) {
ret = intel_guc_ucode_load(dev);
if (ret) {
DRM_ERROR("Failed to initialize GuC, error %d\n", ret);
ret = -EIO;
if (HAS_GUC(dev)) {
ret = intel_guc_setup(dev);
if (ret)
goto out;
}
}
/*

View file

@ -134,7 +134,7 @@ static int get_context_size(struct drm_i915_private *dev_priv)
return ret;
}
static void i915_gem_context_clean(struct intel_context *ctx)
static void i915_gem_context_clean(struct i915_gem_context *ctx)
{
struct i915_hw_ppgtt *ppgtt = ctx->ppgtt;
struct i915_vma *vma, *next;
@ -151,13 +151,12 @@ static void i915_gem_context_clean(struct intel_context *ctx)
void i915_gem_context_free(struct kref *ctx_ref)
{
struct intel_context *ctx = container_of(ctx_ref, typeof(*ctx), ref);
struct i915_gem_context *ctx = container_of(ctx_ref, typeof(*ctx), ref);
int i;
lockdep_assert_held(&ctx->i915->dev->struct_mutex);
trace_i915_context_free(ctx);
if (i915.enable_execlists)
intel_lr_context_free(ctx);
/*
* This context is going away and we need to remove all VMAs still
* around. This is to handle imported shared objects for which
@ -167,8 +166,19 @@ void i915_gem_context_free(struct kref *ctx_ref)
i915_ppgtt_put(ctx->ppgtt);
if (ctx->legacy_hw_ctx.rcs_state)
drm_gem_object_unreference(&ctx->legacy_hw_ctx.rcs_state->base);
for (i = 0; i < I915_NUM_ENGINES; i++) {
struct intel_context *ce = &ctx->engine[i];
if (!ce->state)
continue;
WARN_ON(ce->pin_count);
if (ce->ringbuf)
intel_ringbuffer_free(ce->ringbuf);
drm_gem_object_unreference(&ce->state->base);
}
list_del(&ctx->link);
ida_simple_remove(&ctx->i915->context_hw_ida, ctx->hw_id);
@ -181,6 +191,8 @@ i915_gem_alloc_context_obj(struct drm_device *dev, size_t size)
struct drm_i915_gem_object *obj;
int ret;
lockdep_assert_held(&dev->struct_mutex);
obj = i915_gem_object_create(dev, size);
if (IS_ERR(obj))
return obj;
@ -234,12 +246,12 @@ static int assign_hw_id(struct drm_i915_private *dev_priv, unsigned *out)
return 0;
}
static struct intel_context *
static struct i915_gem_context *
__create_hw_context(struct drm_device *dev,
struct drm_i915_file_private *file_priv)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_context *ctx;
struct i915_gem_context *ctx;
int ret;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
@ -263,7 +275,7 @@ __create_hw_context(struct drm_device *dev,
ret = PTR_ERR(obj);
goto err_out;
}
ctx->legacy_hw_ctx.rcs_state = obj;
ctx->engine[RCS].state = obj;
}
/* Default context will never have a file_priv */
@ -296,44 +308,27 @@ __create_hw_context(struct drm_device *dev,
* context state of the GPU for applications that don't utilize HW contexts, as
* well as an idle case.
*/
static struct intel_context *
static struct i915_gem_context *
i915_gem_create_context(struct drm_device *dev,
struct drm_i915_file_private *file_priv)
{
const bool is_global_default_ctx = file_priv == NULL;
struct intel_context *ctx;
int ret = 0;
struct i915_gem_context *ctx;
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
lockdep_assert_held(&dev->struct_mutex);
ctx = __create_hw_context(dev, file_priv);
if (IS_ERR(ctx))
return ctx;
if (is_global_default_ctx && ctx->legacy_hw_ctx.rcs_state) {
/* We may need to do things with the shrinker which
* require us to immediately switch back to the default
* context. This can cause a problem as pinning the
* default context also requires GTT space which may not
* be available. To avoid this we always pin the default
* context.
*/
ret = i915_gem_obj_ggtt_pin(ctx->legacy_hw_ctx.rcs_state,
get_context_alignment(to_i915(dev)), 0);
if (ret) {
DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret);
goto err_destroy;
}
}
if (USES_FULL_PPGTT(dev)) {
struct i915_hw_ppgtt *ppgtt = i915_ppgtt_create(dev, file_priv);
if (IS_ERR_OR_NULL(ppgtt)) {
if (IS_ERR(ppgtt)) {
DRM_DEBUG_DRIVER("PPGTT setup failed (%ld)\n",
PTR_ERR(ppgtt));
ret = PTR_ERR(ppgtt);
goto err_unpin;
idr_remove(&file_priv->context_idr, ctx->user_handle);
i915_gem_context_unreference(ctx);
return ERR_CAST(ppgtt);
}
ctx->ppgtt = ppgtt;
@ -342,24 +337,19 @@ i915_gem_create_context(struct drm_device *dev,
trace_i915_context_create(ctx);
return ctx;
err_unpin:
if (is_global_default_ctx && ctx->legacy_hw_ctx.rcs_state)
i915_gem_object_ggtt_unpin(ctx->legacy_hw_ctx.rcs_state);
err_destroy:
idr_remove(&file_priv->context_idr, ctx->user_handle);
i915_gem_context_unreference(ctx);
return ERR_PTR(ret);
}
static void i915_gem_context_unpin(struct intel_context *ctx,
static void i915_gem_context_unpin(struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
if (i915.enable_execlists) {
intel_lr_context_unpin(ctx, engine);
} else {
if (engine->id == RCS && ctx->legacy_hw_ctx.rcs_state)
i915_gem_object_ggtt_unpin(ctx->legacy_hw_ctx.rcs_state);
struct intel_context *ce = &ctx->engine[engine->id];
if (ce->state)
i915_gem_object_ggtt_unpin(ce->state);
i915_gem_context_unreference(ctx);
}
}
@ -368,8 +358,10 @@ void i915_gem_context_reset(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
lockdep_assert_held(&dev->struct_mutex);
if (i915.enable_execlists) {
struct intel_context *ctx;
struct i915_gem_context *ctx;
list_for_each_entry(ctx, &dev_priv->context_list, link)
intel_lr_context_reset(dev_priv, ctx);
@ -381,7 +373,7 @@ void i915_gem_context_reset(struct drm_device *dev)
int i915_gem_context_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_context *ctx;
struct i915_gem_context *ctx;
/* Init should only be called once per module load. Eventually the
* restriction on the context_disabled check can be loosened. */
@ -421,6 +413,26 @@ int i915_gem_context_init(struct drm_device *dev)
return PTR_ERR(ctx);
}
if (!i915.enable_execlists && ctx->engine[RCS].state) {
int ret;
/* We may need to do things with the shrinker which
* require us to immediately switch back to the default
* context. This can cause a problem as pinning the
* default context also requires GTT space which may not
* be available. To avoid this we always pin the default
* context.
*/
ret = i915_gem_obj_ggtt_pin(ctx->engine[RCS].state,
get_context_alignment(dev_priv), 0);
if (ret) {
DRM_ERROR("Failed to pinned default global context (error %d)\n",
ret);
i915_gem_context_unreference(ctx);
return ret;
}
}
dev_priv->kernel_context = ctx;
DRM_DEBUG_DRIVER("%s context support initialized\n",
@ -433,26 +445,32 @@ void i915_gem_context_lost(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
for_each_engine(engine, dev_priv) {
if (engine->last_context == NULL)
continue;
lockdep_assert_held(&dev_priv->dev->struct_mutex);
i915_gem_context_unpin(engine->last_context, engine);
engine->last_context = NULL;
for_each_engine(engine, dev_priv) {
if (engine->last_context) {
i915_gem_context_unpin(engine->last_context, engine);
engine->last_context = NULL;
}
/* Force the GPU state to be reinitialised on enabling */
dev_priv->kernel_context->engine[engine->id].initialised =
engine->init_context == NULL;
}
/* Force the GPU state to be reinitialised on enabling */
dev_priv->kernel_context->legacy_hw_ctx.initialized = false;
dev_priv->kernel_context->remap_slice = ALL_L3_SLICES(dev_priv);
}
void i915_gem_context_fini(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_context *dctx = dev_priv->kernel_context;
struct i915_gem_context *dctx = dev_priv->kernel_context;
if (dctx->legacy_hw_ctx.rcs_state)
i915_gem_object_ggtt_unpin(dctx->legacy_hw_ctx.rcs_state);
lockdep_assert_held(&dev->struct_mutex);
if (!i915.enable_execlists && dctx->engine[RCS].state)
i915_gem_object_ggtt_unpin(dctx->engine[RCS].state);
i915_gem_context_unreference(dctx);
dev_priv->kernel_context = NULL;
@ -462,8 +480,9 @@ void i915_gem_context_fini(struct drm_device *dev)
static int context_idr_cleanup(int id, void *p, void *data)
{
struct intel_context *ctx = p;
struct i915_gem_context *ctx = p;
ctx->file_priv = ERR_PTR(-EBADF);
i915_gem_context_unreference(ctx);
return 0;
}
@ -471,7 +490,7 @@ static int context_idr_cleanup(int id, void *p, void *data)
int i915_gem_context_open(struct drm_device *dev, struct drm_file *file)
{
struct drm_i915_file_private *file_priv = file->driver_priv;
struct intel_context *ctx;
struct i915_gem_context *ctx;
idr_init(&file_priv->context_idr);
@ -491,22 +510,12 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
{
struct drm_i915_file_private *file_priv = file->driver_priv;
lockdep_assert_held(&dev->struct_mutex);
idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
idr_destroy(&file_priv->context_idr);
}
struct intel_context *
i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
{
struct intel_context *ctx;
ctx = (struct intel_context *)idr_find(&file_priv->context_idr, id);
if (!ctx)
return ERR_PTR(-ENOENT);
return ctx;
}
static inline int
mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
{
@ -569,7 +578,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 hw_flags)
intel_ring_emit(engine, MI_NOOP);
intel_ring_emit(engine, MI_SET_CONTEXT);
intel_ring_emit(engine,
i915_gem_obj_ggtt_offset(req->ctx->legacy_hw_ctx.rcs_state) |
i915_gem_obj_ggtt_offset(req->ctx->engine[RCS].state) |
flags);
/*
* w/a: MI_SET_CONTEXT must always be followed by MI_NOOP
@ -641,12 +650,12 @@ static int remap_l3(struct drm_i915_gem_request *req, int slice)
static inline bool skip_rcs_switch(struct i915_hw_ppgtt *ppgtt,
struct intel_engine_cs *engine,
struct intel_context *to)
struct i915_gem_context *to)
{
if (to->remap_slice)
return false;
if (!to->legacy_hw_ctx.initialized)
if (!to->engine[RCS].initialised)
return false;
if (ppgtt && (intel_engine_flag(engine) & ppgtt->pd_dirty_rings))
@ -658,7 +667,7 @@ static inline bool skip_rcs_switch(struct i915_hw_ppgtt *ppgtt,
static bool
needs_pd_load_pre(struct i915_hw_ppgtt *ppgtt,
struct intel_engine_cs *engine,
struct intel_context *to)
struct i915_gem_context *to)
{
if (!ppgtt)
return false;
@ -683,7 +692,7 @@ needs_pd_load_pre(struct i915_hw_ppgtt *ppgtt,
static bool
needs_pd_load_post(struct i915_hw_ppgtt *ppgtt,
struct intel_context *to,
struct i915_gem_context *to,
u32 hw_flags)
{
if (!ppgtt)
@ -700,10 +709,10 @@ needs_pd_load_post(struct i915_hw_ppgtt *ppgtt,
static int do_rcs_switch(struct drm_i915_gem_request *req)
{
struct intel_context *to = req->ctx;
struct i915_gem_context *to = req->ctx;
struct intel_engine_cs *engine = req->engine;
struct i915_hw_ppgtt *ppgtt = to->ppgtt ?: req->i915->mm.aliasing_ppgtt;
struct intel_context *from;
struct i915_gem_context *from;
u32 hw_flags;
int ret, i;
@ -711,7 +720,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
return 0;
/* Trying to pin first makes error handling easier. */
ret = i915_gem_obj_ggtt_pin(to->legacy_hw_ctx.rcs_state,
ret = i915_gem_obj_ggtt_pin(to->engine[RCS].state,
get_context_alignment(engine->i915),
0);
if (ret)
@ -734,7 +743,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
*
* XXX: We need a real interface to do this instead of trickery.
*/
ret = i915_gem_object_set_to_gtt_domain(to->legacy_hw_ctx.rcs_state, false);
ret = i915_gem_object_set_to_gtt_domain(to->engine[RCS].state, false);
if (ret)
goto unpin_out;
@ -749,7 +758,7 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
goto unpin_out;
}
if (!to->legacy_hw_ctx.initialized || i915_gem_context_is_default(to))
if (!to->engine[RCS].initialised || i915_gem_context_is_default(to))
/* NB: If we inhibit the restore, the context is not allowed to
* die because future work may end up depending on valid address
* space. This means we must enforce that a page table load
@ -773,8 +782,8 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
* MI_SET_CONTEXT instead of when the next seqno has completed.
*/
if (from != NULL) {
from->legacy_hw_ctx.rcs_state->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->legacy_hw_ctx.rcs_state), req);
from->engine[RCS].state->base.read_domains = I915_GEM_DOMAIN_INSTRUCTION;
i915_vma_move_to_active(i915_gem_obj_to_ggtt(from->engine[RCS].state), req);
/* As long as MI_SET_CONTEXT is serializing, ie. it flushes the
* whole damn pipeline, we don't need to explicitly mark the
* object dirty. The only exception is that the context must be
@ -782,10 +791,10 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
* able to defer doing this until we know the object would be
* swapped, but there is no way to do that yet.
*/
from->legacy_hw_ctx.rcs_state->dirty = 1;
from->engine[RCS].state->dirty = 1;
/* obj is kept alive until the next request by its active ref */
i915_gem_object_ggtt_unpin(from->legacy_hw_ctx.rcs_state);
i915_gem_object_ggtt_unpin(from->engine[RCS].state);
i915_gem_context_unreference(from);
}
i915_gem_context_reference(to);
@ -820,19 +829,19 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
to->remap_slice &= ~(1<<i);
}
if (!to->legacy_hw_ctx.initialized) {
if (!to->engine[RCS].initialised) {
if (engine->init_context) {
ret = engine->init_context(req);
if (ret)
return ret;
}
to->legacy_hw_ctx.initialized = true;
to->engine[RCS].initialised = true;
}
return 0;
unpin_out:
i915_gem_object_ggtt_unpin(to->legacy_hw_ctx.rcs_state);
i915_gem_object_ggtt_unpin(to->engine[RCS].state);
return ret;
}
@ -852,14 +861,12 @@ static int do_rcs_switch(struct drm_i915_gem_request *req)
int i915_switch_context(struct drm_i915_gem_request *req)
{
struct intel_engine_cs *engine = req->engine;
struct drm_i915_private *dev_priv = req->i915;
WARN_ON(i915.enable_execlists);
WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));
lockdep_assert_held(&req->i915->dev->struct_mutex);
if (engine->id != RCS ||
req->ctx->legacy_hw_ctx.rcs_state == NULL) {
struct intel_context *to = req->ctx;
if (!req->ctx->engine[engine->id].state) {
struct i915_gem_context *to = req->ctx;
struct i915_hw_ppgtt *ppgtt =
to->ppgtt ?: req->i915->mm.aliasing_ppgtt;
@ -897,7 +904,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_gem_context_create *args = data;
struct drm_i915_file_private *file_priv = file->driver_priv;
struct intel_context *ctx;
struct i915_gem_context *ctx;
int ret;
if (!contexts_enabled(dev))
@ -926,7 +933,7 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_gem_context_destroy *args = data;
struct drm_i915_file_private *file_priv = file->driver_priv;
struct intel_context *ctx;
struct i915_gem_context *ctx;
int ret;
if (args->pad != 0)
@ -939,13 +946,13 @@ int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
if (ret)
return ret;
ctx = i915_gem_context_get(file_priv, args->ctx_id);
ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
if (IS_ERR(ctx)) {
mutex_unlock(&dev->struct_mutex);
return PTR_ERR(ctx);
}
idr_remove(&ctx->file_priv->context_idr, ctx->user_handle);
idr_remove(&file_priv->context_idr, ctx->user_handle);
i915_gem_context_unreference(ctx);
mutex_unlock(&dev->struct_mutex);
@ -958,14 +965,14 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_file_private *file_priv = file->driver_priv;
struct drm_i915_gem_context_param *args = data;
struct intel_context *ctx;
struct i915_gem_context *ctx;
int ret;
ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;
ctx = i915_gem_context_get(file_priv, args->ctx_id);
ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
if (IS_ERR(ctx)) {
mutex_unlock(&dev->struct_mutex);
return PTR_ERR(ctx);
@ -1001,14 +1008,14 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data,
{
struct drm_i915_file_private *file_priv = file->driver_priv;
struct drm_i915_gem_context_param *args = data;
struct intel_context *ctx;
struct i915_gem_context *ctx;
int ret;
ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ret;
ctx = i915_gem_context_get(file_priv, args->ctx_id);
ctx = i915_gem_context_lookup(file_priv, args->ctx_id);
if (IS_ERR(ctx)) {
mutex_unlock(&dev->struct_mutex);
return PTR_ERR(ctx);
@ -1047,7 +1054,7 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_reset_stats *args = data;
struct i915_ctx_hang_stats *hs;
struct intel_context *ctx;
struct i915_gem_context *ctx;
int ret;
if (args->flags || args->pad)
@ -1060,7 +1067,7 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
if (ret)
return ret;
ctx = i915_gem_context_get(file->driver_priv, args->ctx_id);
ctx = i915_gem_context_lookup(file->driver_priv, args->ctx_id);
if (IS_ERR(ctx)) {
mutex_unlock(&dev->struct_mutex);
return PTR_ERR(ctx);

View file

@ -714,7 +714,7 @@ eb_vma_misplaced(struct i915_vma *vma)
static int
i915_gem_execbuffer_reserve(struct intel_engine_cs *engine,
struct list_head *vmas,
struct intel_context *ctx,
struct i915_gem_context *ctx,
bool *need_relocs)
{
struct drm_i915_gem_object *obj;
@ -826,7 +826,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
struct intel_engine_cs *engine,
struct eb_vmas *eb,
struct drm_i915_gem_exec_object2 *exec,
struct intel_context *ctx)
struct i915_gem_context *ctx)
{
struct drm_i915_gem_relocation_entry *reloc;
struct i915_address_space *vm;
@ -1063,17 +1063,17 @@ validate_exec_list(struct drm_device *dev,
return 0;
}
static struct intel_context *
static struct i915_gem_context *
i915_gem_validate_context(struct drm_device *dev, struct drm_file *file,
struct intel_engine_cs *engine, const u32 ctx_id)
{
struct intel_context *ctx = NULL;
struct i915_gem_context *ctx = NULL;
struct i915_ctx_hang_stats *hs;
if (engine->id != RCS && ctx_id != DEFAULT_CONTEXT_HANDLE)
return ERR_PTR(-EINVAL);
ctx = i915_gem_context_get(file->driver_priv, ctx_id);
ctx = i915_gem_context_lookup(file->driver_priv, ctx_id);
if (IS_ERR(ctx))
return ctx;
@ -1428,7 +1428,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
struct drm_i915_gem_object *batch_obj;
struct drm_i915_gem_exec_object2 shadow_exec_entry;
struct intel_engine_cs *engine;
struct intel_context *ctx;
struct i915_gem_context *ctx;
struct i915_address_space *vm;
struct i915_execbuffer_params params_master; /* XXX: will be removed later */
struct i915_execbuffer_params *params = &params_master;

View file

@ -360,10 +360,9 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
struct drm_i915_gem_object *client_obj = client->client_obj;
struct drm_i915_private *dev_priv = guc_to_i915(guc);
struct intel_engine_cs *engine;
struct intel_context *ctx = client->owner;
struct i915_gem_context *ctx = client->owner;
struct guc_context_desc desc;
struct sg_table *sg;
enum intel_engine_id id;
u32 gfx_addr;
memset(&desc, 0, sizeof(desc));
@ -373,10 +372,10 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
desc.priority = client->priority;
desc.db_id = client->doorbell_id;
for_each_engine_id(engine, dev_priv, id) {
for_each_engine(engine, dev_priv) {
struct intel_context *ce = &ctx->engine[engine->id];
struct guc_execlist_context *lrc = &desc.lrc[engine->guc_id];
struct drm_i915_gem_object *obj;
uint64_t ctx_desc;
/* TODO: We have a design issue to be solved here. Only when we
* receive the first batch, we know which engine is used by the
@ -385,20 +384,18 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
* for now who owns a GuC client. But for future owner of GuC
* client, need to make sure lrc is pinned prior to enter here.
*/
obj = ctx->engine[id].state;
if (!obj)
if (!ce->state)
break; /* XXX: continue? */
ctx_desc = intel_lr_context_descriptor(ctx, engine);
lrc->context_desc = (u32)ctx_desc;
lrc->context_desc = lower_32_bits(ce->lrc_desc);
/* The state page is after PPHWSP */
gfx_addr = i915_gem_obj_ggtt_offset(obj);
gfx_addr = i915_gem_obj_ggtt_offset(ce->state);
lrc->ring_lcra = gfx_addr + LRC_STATE_PN * PAGE_SIZE;
lrc->context_id = (client->ctx_index << GUC_ELC_CTXID_OFFSET) |
(engine->guc_id << GUC_ELC_ENGINE_OFFSET);
obj = ctx->engine[id].ringbuf->obj;
obj = ce->ringbuf->obj;
gfx_addr = i915_gem_obj_ggtt_offset(obj);
lrc->ring_begin = gfx_addr;
@ -426,7 +423,7 @@ static void guc_init_ctx_desc(struct intel_guc *guc,
desc.wq_size = client->wq_size;
/*
* XXX: Take LRCs from an existing intel_context if this is not an
* XXX: Take LRCs from an existing context if this is not an
* IsKMDCreatedContext client
*/
desc.desc_private = (uintptr_t)client;
@ -450,47 +447,64 @@ static void guc_fini_ctx_desc(struct intel_guc *guc,
sizeof(desc) * client->ctx_index);
}
int i915_guc_wq_check_space(struct i915_guc_client *gc)
/**
* i915_guc_wq_check_space() - check that the GuC can accept a request
* @request: request associated with the commands
*
* Return: 0 if space is available
* -EAGAIN if space is not currently available
*
* This function must be called (and must return 0) before a request
* is submitted to the GuC via i915_guc_submit() below. Once a result
* of 0 has been returned, it remains valid until (but only until)
* the next call to submit().
*
* This precheck allows the caller to determine in advance that space
* will be available for the next submission before committing resources
* to it, and helps avoid late failures with complicated recovery paths.
*/
int i915_guc_wq_check_space(struct drm_i915_gem_request *request)
{
const size_t wqi_size = sizeof(struct guc_wq_item);
struct i915_guc_client *gc = request->i915->guc.execbuf_client;
struct guc_process_desc *desc;
u32 size = sizeof(struct guc_wq_item);
int ret = -ETIMEDOUT, timeout_counter = 200;
u32 freespace;
if (!gc)
return 0;
GEM_BUG_ON(gc == NULL);
desc = gc->client_base + gc->proc_desc_offset;
while (timeout_counter-- > 0) {
if (CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size) >= size) {
ret = 0;
break;
}
freespace = CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size);
if (likely(freespace >= wqi_size))
return 0;
if (timeout_counter)
usleep_range(1000, 2000);
};
gc->no_wq_space += 1;
return ret;
return -EAGAIN;
}
static int guc_add_workqueue_item(struct i915_guc_client *gc,
struct drm_i915_gem_request *rq)
static void guc_add_workqueue_item(struct i915_guc_client *gc,
struct drm_i915_gem_request *rq)
{
/* wqi_len is in DWords, and does not include the one-word header */
const size_t wqi_size = sizeof(struct guc_wq_item);
const u32 wqi_len = wqi_size/sizeof(u32) - 1;
struct guc_process_desc *desc;
struct guc_wq_item *wqi;
void *base;
u32 tail, wq_len, wq_off, space;
u32 freespace, tail, wq_off, wq_page;
desc = gc->client_base + gc->proc_desc_offset;
space = CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size);
if (WARN_ON(space < sizeof(struct guc_wq_item)))
return -ENOSPC; /* shouldn't happen */
/* postincrement WQ tail for next time */
wq_off = gc->wq_tail;
gc->wq_tail += sizeof(struct guc_wq_item);
gc->wq_tail &= gc->wq_size - 1;
/* Free space is guaranteed, see i915_guc_wq_check_space() above */
freespace = CIRC_SPACE(gc->wq_tail, desc->head, gc->wq_size);
GEM_BUG_ON(freespace < wqi_size);
/* The GuC firmware wants the tail index in QWords, not bytes */
tail = rq->tail;
GEM_BUG_ON(tail & 7);
tail >>= 3;
GEM_BUG_ON(tail > WQ_RING_TAIL_MAX);
/* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we
* should not have the case where structure wqi is across page, neither
@ -499,19 +513,23 @@ static int guc_add_workqueue_item(struct i915_guc_client *gc,
* XXX: if not the case, we need save data to a temp wqi and copy it to
* workqueue buffer dw by dw.
*/
WARN_ON(sizeof(struct guc_wq_item) != 16);
WARN_ON(wq_off & 3);
BUILD_BUG_ON(wqi_size != 16);
/* wq starts from the page after doorbell / process_desc */
base = kmap_atomic(i915_gem_object_get_page(gc->client_obj,
(wq_off + GUC_DB_SIZE) >> PAGE_SHIFT));
/* postincrement WQ tail for next time */
wq_off = gc->wq_tail;
gc->wq_tail += wqi_size;
gc->wq_tail &= gc->wq_size - 1;
GEM_BUG_ON(wq_off & (wqi_size - 1));
/* WQ starts from the page after doorbell / process_desc */
wq_page = (wq_off + GUC_DB_SIZE) >> PAGE_SHIFT;
wq_off &= PAGE_SIZE - 1;
base = kmap_atomic(i915_gem_object_get_page(gc->client_obj, wq_page));
wqi = (struct guc_wq_item *)((char *)base + wq_off);
/* len does not include the header */
wq_len = sizeof(struct guc_wq_item) / sizeof(u32) - 1;
/* Now fill in the 4-word work queue item */
wqi->header = WQ_TYPE_INORDER |
(wq_len << WQ_LEN_SHIFT) |
(wqi_len << WQ_LEN_SHIFT) |
(rq->engine->guc_id << WQ_TARGET_SHIFT) |
WQ_NO_WCFLUSH_WAIT;
@ -519,48 +537,50 @@ static int guc_add_workqueue_item(struct i915_guc_client *gc,
wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx,
rq->engine);
/* The GuC firmware wants the tail index in QWords, not bytes */
tail = rq->ringbuf->tail >> 3;
wqi->ring_tail = tail << WQ_RING_TAIL_SHIFT;
wqi->fence_id = 0; /*XXX: what fence to be here */
wqi->fence_id = rq->seqno;
kunmap_atomic(base);
return 0;
}
/**
* i915_guc_submit() - Submit commands through GuC
* @client: the guc client where commands will go through
* @rq: request associated with the commands
*
* Return: 0 if succeed
* Return: 0 on success, otherwise an errno.
* (Note: nonzero really shouldn't happen!)
*
* The caller must have already called i915_guc_wq_check_space() above
* with a result of 0 (success) since the last request submission. This
* guarantees that there is space in the work queue for the new request,
* so enqueuing the item cannot fail.
*
* Bad Things Will Happen if the caller violates this protocol e.g. calls
* submit() when check() says there's no space, or calls submit() multiple
* times with no intervening check().
*
* The only error here arises if the doorbell hardware isn't functioning
* as expected, which really shouln't happen.
*/
int i915_guc_submit(struct i915_guc_client *client,
struct drm_i915_gem_request *rq)
int i915_guc_submit(struct drm_i915_gem_request *rq)
{
struct intel_guc *guc = client->guc;
unsigned int engine_id = rq->engine->guc_id;
int q_ret, b_ret;
struct intel_guc *guc = &rq->i915->guc;
struct i915_guc_client *client = guc->execbuf_client;
int b_ret;
q_ret = guc_add_workqueue_item(client, rq);
if (q_ret == 0)
b_ret = guc_ring_doorbell(client);
guc_add_workqueue_item(client, rq);
b_ret = guc_ring_doorbell(client);
client->submissions[engine_id] += 1;
if (q_ret) {
client->q_fail += 1;
client->retcode = q_ret;
} else if (b_ret) {
client->retcode = b_ret;
if (b_ret)
client->b_fail += 1;
client->retcode = q_ret = b_ret;
} else {
client->retcode = 0;
}
guc->submissions[engine_id] += 1;
guc->last_seqno[engine_id] = rq->seqno;
return q_ret;
return b_ret;
}
/*
@ -677,7 +697,7 @@ static void guc_client_free(struct drm_device *dev,
*/
static struct i915_guc_client *guc_client_alloc(struct drm_device *dev,
uint32_t priority,
struct intel_context *ctx)
struct i915_gem_context *ctx)
{
struct i915_guc_client *client;
struct drm_i915_private *dev_priv = dev->dev_private;
@ -915,11 +935,12 @@ int i915_guc_submission_enable(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc *guc = &dev_priv->guc;
struct intel_context *ctx = dev_priv->kernel_context;
struct i915_guc_client *client;
/* client for execbuf submission */
client = guc_client_alloc(dev, GUC_CTX_PRIORITY_KMD_NORMAL, ctx);
client = guc_client_alloc(dev,
GUC_CTX_PRIORITY_KMD_NORMAL,
dev_priv->kernel_context);
if (!client) {
DRM_ERROR("Failed to create execbuf guc_client\n");
return -ENOMEM;
@ -966,10 +987,10 @@ int intel_guc_suspend(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc *guc = &dev_priv->guc;
struct intel_context *ctx;
struct i915_gem_context *ctx;
u32 data[3];
if (!i915.enable_guc_submission)
if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS)
return 0;
ctx = dev_priv->kernel_context;
@ -992,10 +1013,10 @@ int intel_guc_resume(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc *guc = &dev_priv->guc;
struct intel_context *ctx;
struct i915_gem_context *ctx;
u32 data[3];
if (!i915.enable_guc_submission)
if (guc->guc_fw.guc_fw_load_status != GUC_FIRMWARE_SUCCESS)
return 0;
ctx = dev_priv->kernel_context;

View file

@ -364,19 +364,7 @@ void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv)
u32 gen6_sanitize_rps_pm_mask(struct drm_i915_private *dev_priv, u32 mask)
{
/*
* SNB,IVB can while VLV,CHV may hard hang on looping batchbuffer
* if GEN6_PM_UP_EI_EXPIRED is masked.
*
* TODO: verify if this can be reproduced on VLV,CHV.
*/
if (INTEL_INFO(dev_priv)->gen <= 7 && !IS_HASWELL(dev_priv))
mask &= ~GEN6_PM_RP_UP_EI_EXPIRED;
if (INTEL_INFO(dev_priv)->gen >= 8)
mask &= ~GEN8_PMINTR_REDIRECT_TO_NON_DISP;
return mask;
return (mask & ~dev_priv->rps.pm_intr_keep);
}
void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv)
@ -3797,6 +3785,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
uint32_t de_pipe_enables;
u32 de_port_masked = GEN8_AUX_CHANNEL_A;
u32 de_port_enables;
u32 de_misc_masked = GEN8_DE_MISC_GSE;
enum pipe pipe;
if (INTEL_INFO(dev_priv)->gen >= 9) {
@ -3832,6 +3821,7 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv)
de_pipe_enables);
GEN5_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables);
GEN5_IRQ_INIT(GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked);
}
static int gen8_irq_postinstall(struct drm_device *dev)
@ -4576,6 +4566,20 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
else
dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS;
dev_priv->rps.pm_intr_keep = 0;
/*
* SNB,IVB can while VLV,CHV may hard hang on looping batchbuffer
* if GEN6_PM_UP_EI_EXPIRED is masked.
*
* TODO: verify if this can be reproduced on VLV,CHV.
*/
if (INTEL_INFO(dev_priv)->gen <= 7 && !IS_HASWELL(dev_priv))
dev_priv->rps.pm_intr_keep |= GEN6_PM_RP_UP_EI_EXPIRED;
if (INTEL_INFO(dev_priv)->gen >= 8)
dev_priv->rps.pm_intr_keep |= GEN8_PMINTR_REDIRECT_TO_NON_DISP;
INIT_DELAYED_WORK(&dev_priv->gpu_error.hangcheck_work,
i915_hangcheck_elapsed);

View file

@ -54,7 +54,8 @@ struct i915_params i915 __read_mostly = {
.verbose_state_checks = 1,
.nuclear_pageflip = 0,
.edp_vswing = 0,
.enable_guc_submission = false,
.enable_guc_loading = 0,
.enable_guc_submission = 0,
.guc_log_level = -1,
.enable_dp_mst = true,
.inject_load_failure = 0,
@ -198,8 +199,15 @@ MODULE_PARM_DESC(edp_vswing,
"(0=use value from vbt [default], 1=low power swing(200mV),"
"2=default swing(400mV))");
module_param_named_unsafe(enable_guc_submission, i915.enable_guc_submission, bool, 0400);
MODULE_PARM_DESC(enable_guc_submission, "Enable GuC submission (default:false)");
module_param_named_unsafe(enable_guc_loading, i915.enable_guc_loading, int, 0400);
MODULE_PARM_DESC(enable_guc_loading,
"Enable GuC firmware loading "
"(-1=auto, 0=never [default], 1=if available, 2=required)");
module_param_named_unsafe(enable_guc_submission, i915.enable_guc_submission, int, 0400);
MODULE_PARM_DESC(enable_guc_submission,
"Enable GuC submission "
"(-1=auto, 0=never [default], 1=if available, 2=required)");
module_param_named(guc_log_level, i915.guc_log_level, int, 0400);
MODULE_PARM_DESC(guc_log_level,

View file

@ -45,6 +45,8 @@ struct i915_params {
int enable_ips;
int invert_brightness;
int enable_cmd_parser;
int enable_guc_loading;
int enable_guc_submission;
int guc_log_level;
int use_mmio_flip;
int mmio_debug;
@ -57,7 +59,6 @@ struct i915_params {
bool load_detect_test;
bool reset;
bool disable_display;
bool enable_guc_submission;
bool verbose_state_checks;
bool nuclear_pageflip;
bool enable_dp_mst;

View file

@ -7031,7 +7031,7 @@ enum skl_disp_power_wells {
#define VLV_RCEDATA _MMIO(0xA0BC)
#define GEN6_RC6pp_THRESHOLD _MMIO(0xA0C0)
#define GEN6_PMINTRMSK _MMIO(0xA168)
#define GEN8_PMINTR_REDIRECT_TO_NON_DISP (1<<31)
#define GEN8_PMINTR_REDIRECT_TO_NON_DISP (1<<31)
#define VLV_PWRDWNUPCTL _MMIO(0xA294)
#define GEN9_MEDIA_PG_IDLE_HYSTERESIS _MMIO(0xA0C4)
#define GEN9_RENDER_PG_IDLE_HYSTERESIS _MMIO(0xA0C8)

View file

@ -203,7 +203,7 @@ i915_l3_write(struct file *filp, struct kobject *kobj,
struct drm_minor *dminor = dev_to_drm_minor(dev);
struct drm_device *drm_dev = dminor->dev;
struct drm_i915_private *dev_priv = drm_dev->dev_private;
struct intel_context *ctx;
struct i915_gem_context *ctx;
u32 *temp = NULL; /* Just here to make handling failures easy */
int slice = (int)(uintptr_t)attr->private;
int ret;

View file

@ -734,12 +734,12 @@ DEFINE_EVENT(i915_ppgtt, i915_ppgtt_release,
* the context.
*/
DECLARE_EVENT_CLASS(i915_context,
TP_PROTO(struct intel_context *ctx),
TP_PROTO(struct i915_gem_context *ctx),
TP_ARGS(ctx),
TP_STRUCT__entry(
__field(u32, dev)
__field(struct intel_context *, ctx)
__field(struct i915_gem_context *, ctx)
__field(struct i915_address_space *, vm)
),
@ -754,12 +754,12 @@ DECLARE_EVENT_CLASS(i915_context,
)
DEFINE_EVENT(i915_context, i915_context_create,
TP_PROTO(struct intel_context *ctx),
TP_PROTO(struct i915_gem_context *ctx),
TP_ARGS(ctx)
);
DEFINE_EVENT(i915_context, i915_context_free,
TP_PROTO(struct intel_context *ctx),
TP_PROTO(struct i915_gem_context *ctx),
TP_ARGS(ctx)
);
@ -771,13 +771,13 @@ DEFINE_EVENT(i915_context, i915_context_free,
* called only if full ppgtt is enabled.
*/
TRACE_EVENT(switch_mm,
TP_PROTO(struct intel_engine_cs *engine, struct intel_context *to),
TP_PROTO(struct intel_engine_cs *engine, struct i915_gem_context *to),
TP_ARGS(engine, to),
TP_STRUCT__entry(
__field(u32, ring)
__field(struct intel_context *, to)
__field(struct i915_gem_context *, to)
__field(struct i915_address_space *, vm)
__field(u32, dev)
),

View file

@ -139,6 +139,11 @@ fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode,
else
panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC;
panel_fixed_mode->width_mm = (dvo_timing->himage_hi << 8) |
dvo_timing->himage_lo;
panel_fixed_mode->height_mm = (dvo_timing->vimage_hi << 8) |
dvo_timing->vimage_lo;
/* Some VBTs have bogus h/vtotal values */
if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal)
panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1;
@ -213,7 +218,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
dev_priv->vbt.lvds_dither = lvds_options->pixel_dither;
ret = intel_opregion_get_panel_type(dev_priv->dev);
ret = intel_opregion_get_panel_type(dev_priv);
if (ret >= 0) {
WARN_ON(ret > 0xf);
panel_type = ret;
@ -1206,7 +1211,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
}
if (bdb->version < 106) {
expected_size = 22;
} else if (bdb->version < 109) {
} else if (bdb->version < 111) {
expected_size = 27;
} else if (bdb->version < 195) {
BUILD_BUG_ON(sizeof(struct old_child_dev_config) != 33);

View file

@ -839,7 +839,7 @@ void intel_crt_init(struct drm_device *dev)
&intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
drm_encoder_init(dev, &crt->base.base, &intel_crt_enc_funcs,
DRM_MODE_ENCODER_DAC, NULL);
DRM_MODE_ENCODER_DAC, "CRT");
intel_connector_attach_encoder(intel_connector, &crt->base);

View file

@ -2347,7 +2347,7 @@ void intel_ddi_init(struct drm_device *dev, enum port port)
encoder = &intel_encoder->base;
drm_encoder_init(dev, encoder, &intel_ddi_funcs,
DRM_MODE_ENCODER_TMDS, NULL);
DRM_MODE_ENCODER_TMDS, "DDI %c", port_name(port));
intel_encoder->compute_config = intel_ddi_compute_config;
intel_encoder->enable = intel_enable_ddi;

File diff suppressed because it is too large Load diff

View file

@ -1578,6 +1578,27 @@ intel_dp_compute_config(struct intel_encoder *encoder,
&pipe_config->dp_m2_n2);
}
/*
* DPLL0 VCO may need to be adjusted to get the correct
* clock for eDP. This will affect cdclk as well.
*/
if (is_edp(intel_dp) &&
(IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))) {
int vco;
switch (pipe_config->port_clock / 2) {
case 108000:
case 216000:
vco = 8640000;
break;
default:
vco = 8100000;
break;
}
to_intel_atomic_state(pipe_config->base.state)->cdclk_pll_vco = vco;
}
if (!HAS_DDI(dev))
intel_dp_set_clock(encoder, pipe_config);
@ -5349,8 +5370,11 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
if (!fixed_mode && dev_priv->vbt.lfp_lvds_vbt_mode) {
fixed_mode = drm_mode_duplicate(dev,
dev_priv->vbt.lfp_lvds_vbt_mode);
if (fixed_mode)
if (fixed_mode) {
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
connector->display_info.width_mm = fixed_mode->width_mm;
connector->display_info.height_mm = fixed_mode->height_mm;
}
}
mutex_unlock(&dev->mode_config.mutex);
@ -5547,9 +5571,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
return false;
}
void
intel_dp_init(struct drm_device *dev,
i915_reg_t output_reg, enum port port)
bool intel_dp_init(struct drm_device *dev,
i915_reg_t output_reg,
enum port port)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_digital_port *intel_dig_port;
@ -5559,7 +5583,7 @@ intel_dp_init(struct drm_device *dev,
intel_dig_port = kzalloc(sizeof(*intel_dig_port), GFP_KERNEL);
if (!intel_dig_port)
return;
return false;
intel_connector = intel_connector_alloc();
if (!intel_connector)
@ -5569,7 +5593,7 @@ intel_dp_init(struct drm_device *dev,
encoder = &intel_encoder->base;
if (drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
DRM_MODE_ENCODER_TMDS, NULL))
DRM_MODE_ENCODER_TMDS, "DP %c", port_name(port)))
goto err_encoder_init;
intel_encoder->compute_config = intel_dp_compute_config;
@ -5616,7 +5640,7 @@ intel_dp_init(struct drm_device *dev,
if (!intel_dp_init_connector(intel_dig_port, intel_connector))
goto err_init_connector;
return;
return true;
err_init_connector:
drm_encoder_cleanup(encoder);
@ -5624,8 +5648,7 @@ intel_dp_init(struct drm_device *dev,
kfree(intel_connector);
err_connector_alloc:
kfree(intel_dig_port);
return;
return false;
}
void intel_dp_mst_suspend(struct drm_device *dev)

View file

@ -534,7 +534,7 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum
intel_mst->primary = intel_dig_port;
drm_encoder_init(dev, &intel_encoder->base, &intel_dp_mst_enc_funcs,
DRM_MODE_ENCODER_DPMST, NULL);
DRM_MODE_ENCODER_DPMST, "DP-MST %c", pipe_name(pipe));
intel_encoder->type = INTEL_OUTPUT_DP_MST;
intel_encoder->crtc_mask = 0x7;

View file

@ -208,8 +208,8 @@ intel_find_shared_dpll(struct intel_crtc *crtc,
if (memcmp(&crtc_state->dpll_hw_state,
&shared_dpll[i].hw_state,
sizeof(crtc_state->dpll_hw_state)) == 0) {
DRM_DEBUG_KMS("CRTC:%d sharing existing %s (crtc mask 0x%08x, active %x)\n",
crtc->base.base.id, pll->name,
DRM_DEBUG_KMS("[CRTC:%d:%s] sharing existing %s (crtc mask 0x%08x, active %x)\n",
crtc->base.base.id, crtc->base.name, pll->name,
shared_dpll[i].crtc_mask,
pll->active_mask);
return pll;
@ -220,8 +220,8 @@ intel_find_shared_dpll(struct intel_crtc *crtc,
for (i = range_min; i <= range_max; i++) {
pll = &dev_priv->shared_dplls[i];
if (shared_dpll[i].crtc_mask == 0) {
DRM_DEBUG_KMS("CRTC:%d allocated %s\n",
crtc->base.base.id, pll->name);
DRM_DEBUG_KMS("[CRTC:%d:%s] allocated %s\n",
crtc->base.base.id, crtc->base.name, pll->name);
return pll;
}
}
@ -358,14 +358,17 @@ ibx_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
i = (enum intel_dpll_id) crtc->pipe;
pll = &dev_priv->shared_dplls[i];
DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
crtc->base.base.id, pll->name);
DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
crtc->base.base.id, crtc->base.name, pll->name);
} else {
pll = intel_find_shared_dpll(crtc, crtc_state,
DPLL_ID_PCH_PLL_A,
DPLL_ID_PCH_PLL_B);
}
if (!pll)
return NULL;
/* reference the pll */
intel_reference_shared_dpll(pll, crtc_state);
@ -1236,9 +1239,6 @@ skl_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
case 162000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, 0);
break;
/* TBD: For DP link rates 2.16 GHz and 4.32 GHz, VCO is 8640 which
results in CDCLK change. Need to handle the change of CDCLK by
disabling pipes and re-enabling them */
case 108000:
ctrl1 |= DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, 0);
break;
@ -1613,8 +1613,8 @@ bxt_get_dpll(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state,
i = (enum intel_dpll_id) intel_dig_port->port;
pll = intel_get_shared_dpll_by_id(dev_priv, i);
DRM_DEBUG_KMS("CRTC:%d using pre-allocated %s\n",
crtc->base.base.id, pll->name);
DRM_DEBUG_KMS("[CRTC:%d:%s] using pre-allocated %s\n",
crtc->base.base.id, crtc->base.name, pll->name);
intel_reference_shared_dpll(pll, crtc_state);
@ -1633,18 +1633,10 @@ static const struct intel_shared_dpll_funcs bxt_ddi_pll_funcs = {
static void intel_ddi_pll_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
uint32_t val = I915_READ(LCPLL_CTL);
if (IS_SKYLAKE(dev) || IS_KABYLAKE(dev)) {
int cdclk_freq;
if (INTEL_GEN(dev_priv) < 9) {
uint32_t val = I915_READ(LCPLL_CTL);
cdclk_freq = dev_priv->display.get_display_clock_speed(dev);
dev_priv->skl_boot_cdclk = cdclk_freq;
if (skl_sanitize_cdclk(dev_priv))
DRM_DEBUG_KMS("Sanitized cdclk programmed by pre-os\n");
if (!(I915_READ(LCPLL1_CTL) & LCPLL_PLL_ENABLE))
DRM_ERROR("LCPLL1 is disabled\n");
} else if (!IS_BROXTON(dev_priv)) {
/*
* The LCPLL register should be turned on by the BIOS. For now
* let's just check its state and print errors in case

View file

@ -304,6 +304,9 @@ struct intel_atomic_state {
unsigned int active_crtcs;
unsigned int min_pixclk[I915_MAX_PIPES];
/* SKL/KBL Only */
unsigned int cdclk_pll_vco;
struct intel_shared_dpll_config shared_dpll[I915_NUM_PLLS];
/*
@ -1133,6 +1136,7 @@ void i915_audio_component_init(struct drm_i915_private *dev_priv);
void i915_audio_component_cleanup(struct drm_i915_private *dev_priv);
/* intel_display.c */
void skl_set_preferred_cdclk_vco(struct drm_i915_private *dev_priv, int vco);
void intel_update_rawclk(struct drm_i915_private *dev_priv);
int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
const char *name, u32 reg, int ref_freq);
@ -1259,7 +1263,6 @@ void hsw_enable_pc8(struct drm_i915_private *dev_priv);
void hsw_disable_pc8(struct drm_i915_private *dev_priv);
void broxton_init_cdclk(struct drm_i915_private *dev_priv);
void broxton_uninit_cdclk(struct drm_i915_private *dev_priv);
bool broxton_cdclk_verify_state(struct drm_i915_private *dev_priv);
void broxton_ddi_phy_init(struct drm_i915_private *dev_priv);
void broxton_ddi_phy_uninit(struct drm_i915_private *dev_priv);
void broxton_ddi_phy_verify_state(struct drm_i915_private *dev_priv);
@ -1268,8 +1271,8 @@ void bxt_enable_dc9(struct drm_i915_private *dev_priv);
void bxt_disable_dc9(struct drm_i915_private *dev_priv);
void gen9_enable_dc5(struct drm_i915_private *dev_priv);
void skl_init_cdclk(struct drm_i915_private *dev_priv);
int skl_sanitize_cdclk(struct drm_i915_private *dev_priv);
void skl_uninit_cdclk(struct drm_i915_private *dev_priv);
unsigned int skl_cdclk_get_vco(unsigned int freq);
void skl_enable_dc6(struct drm_i915_private *dev_priv);
void skl_disable_dc6(struct drm_i915_private *dev_priv);
void intel_dp_get_m_n(struct intel_crtc *crtc,
@ -1309,7 +1312,7 @@ void intel_csr_ucode_suspend(struct drm_i915_private *);
void intel_csr_ucode_resume(struct drm_i915_private *);
/* intel_dp.c */
void intel_dp_init(struct drm_device *dev, i915_reg_t output_reg, enum port port);
bool intel_dp_init(struct drm_device *dev, i915_reg_t output_reg, enum port port);
bool intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
struct intel_connector *intel_connector);
void intel_dp_set_link_params(struct intel_dp *intel_dp,

View file

@ -1450,7 +1450,7 @@ void intel_dsi_init(struct drm_device *dev)
connector = &intel_connector->base;
drm_encoder_init(dev, encoder, &intel_dsi_funcs, DRM_MODE_ENCODER_DSI,
NULL);
"DSI %c", port_name(port));
intel_encoder->compute_config = intel_dsi_compute_config;
intel_encoder->pre_enable = intel_dsi_pre_enable;
@ -1578,6 +1578,9 @@ void intel_dsi_init(struct drm_device *dev)
goto err;
}
connector->display_info.width_mm = fixed_mode->width_mm;
connector->display_info.height_mm = fixed_mode->height_mm;
intel_panel_init(&intel_connector->panel, fixed_mode, NULL);
intel_dsi_add_properties(intel_connector);

View file

@ -406,6 +406,18 @@ intel_dvo_get_current_mode(struct drm_connector *connector)
return mode;
}
static char intel_dvo_port_name(i915_reg_t dvo_reg)
{
if (i915_mmio_reg_equal(dvo_reg, DVOA))
return 'A';
else if (i915_mmio_reg_equal(dvo_reg, DVOB))
return 'B';
else if (i915_mmio_reg_equal(dvo_reg, DVOC))
return 'C';
else
return '?';
}
void intel_dvo_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@ -428,8 +440,6 @@ void intel_dvo_init(struct drm_device *dev)
intel_dvo->attached_connector = intel_connector;
intel_encoder = &intel_dvo->base;
drm_encoder_init(dev, &intel_encoder->base,
&intel_dvo_enc_funcs, encoder_type, NULL);
intel_encoder->disable = intel_disable_dvo;
intel_encoder->enable = intel_enable_dvo;
@ -496,6 +506,10 @@ void intel_dvo_init(struct drm_device *dev)
if (!dvoinit)
continue;
drm_encoder_init(dev, &intel_encoder->base,
&intel_dvo_enc_funcs, encoder_type,
"DVO %c", intel_dvo_port_name(dvo->dvo_reg));
intel_encoder->type = INTEL_OUTPUT_DVO;
intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
switch (dvo->type) {

View file

@ -490,10 +490,10 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
}
crtcs[i] = new_crtc;
DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n",
DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n",
connector->name,
pipe_name(to_intel_crtc(connector->state->crtc)->pipe),
connector->state->crtc->base.id,
connector->state->crtc->name,
modes[i]->hdisplay, modes[i]->vdisplay,
modes[i]->flags & DRM_MODE_FLAG_INTERLACE ? "i" :"");

View file

@ -48,14 +48,23 @@ struct drm_i915_gem_request;
* queue (a circular array of work items), again described in the process
* descriptor. Work queue pages are mapped momentarily as required.
*
* Finally, we also keep a few statistics here, including the number of
* submissions to each engine, and a record of the last submission failure
* (if any).
* We also keep a few statistics on failures. Ideally, these should all
* be zero!
* no_wq_space: times that the submission pre-check found no space was
* available in the work queue (note, the queue is shared,
* not per-engine). It is OK for this to be nonzero, but
* it should not be huge!
* q_fail: failed to enqueue a work item. This should never happen,
* because we check for space beforehand.
* b_fail: failed to ring the doorbell. This should never happen, unless
* somehow the hardware misbehaves, or maybe if the GuC firmware
* crashes? We probably need to reset the GPU to recover.
* retcode: errno from last guc_submit()
*/
struct i915_guc_client {
struct drm_i915_gem_object *client_obj;
void *client_base; /* first page (only) of above */
struct intel_context *owner;
struct i915_gem_context *owner;
struct intel_guc *guc;
uint32_t priority;
uint32_t ctx_index;
@ -71,12 +80,13 @@ struct i915_guc_client {
uint32_t wq_tail;
uint32_t unused; /* Was 'wq_head' */
/* GuC submission statistics & status */
uint64_t submissions[GUC_MAX_ENGINES_NUM];
uint32_t q_fail;
uint32_t no_wq_space;
uint32_t q_fail; /* No longer used */
uint32_t b_fail;
int retcode;
int spare; /* pad to 32 DWords */
/* Per-engine counts of GuC submissions */
uint64_t submissions[GUC_MAX_ENGINES_NUM];
};
enum intel_guc_fw_status {
@ -138,9 +148,9 @@ struct intel_guc {
};
/* intel_guc_loader.c */
extern void intel_guc_ucode_init(struct drm_device *dev);
extern int intel_guc_ucode_load(struct drm_device *dev);
extern void intel_guc_ucode_fini(struct drm_device *dev);
extern void intel_guc_init(struct drm_device *dev);
extern int intel_guc_setup(struct drm_device *dev);
extern void intel_guc_fini(struct drm_device *dev);
extern const char *intel_guc_fw_status_repr(enum intel_guc_fw_status status);
extern int intel_guc_suspend(struct drm_device *dev);
extern int intel_guc_resume(struct drm_device *dev);
@ -148,10 +158,9 @@ extern int intel_guc_resume(struct drm_device *dev);
/* i915_guc_submission.c */
int i915_guc_submission_init(struct drm_device *dev);
int i915_guc_submission_enable(struct drm_device *dev);
int i915_guc_submit(struct i915_guc_client *client,
struct drm_i915_gem_request *rq);
int i915_guc_wq_check_space(struct drm_i915_gem_request *rq);
int i915_guc_submit(struct drm_i915_gem_request *rq);
void i915_guc_submission_disable(struct drm_device *dev);
void i915_guc_submission_fini(struct drm_device *dev);
int i915_guc_wq_check_space(struct i915_guc_client *client);
#endif

View file

@ -71,7 +71,8 @@
#define WQ_WORKLOAD_TOUCH (2 << WQ_WORKLOAD_SHIFT)
#define WQ_RING_TAIL_SHIFT 20
#define WQ_RING_TAIL_MASK (0x7FF << WQ_RING_TAIL_SHIFT)
#define WQ_RING_TAIL_MAX 0x7FF /* 2^11 QWords */
#define WQ_RING_TAIL_MASK (WQ_RING_TAIL_MAX << WQ_RING_TAIL_SHIFT)
#define GUC_DOORBELL_ENABLED 1
#define GUC_DOORBELL_DISABLED 0

View file

@ -103,6 +103,7 @@ static void direct_interrupts_to_guc(struct drm_i915_private *dev_priv)
{
struct intel_engine_cs *engine;
int irqs;
u32 tmp;
/* tell all command streamers to forward interrupts and vblank to GuC */
irqs = _MASKED_FIELD(GFX_FORWARD_VBLANK_MASK, GFX_FORWARD_VBLANK_ALWAYS);
@ -117,6 +118,16 @@ static void direct_interrupts_to_guc(struct drm_i915_private *dev_priv)
I915_WRITE(GUC_BCS_RCS_IER, ~irqs);
I915_WRITE(GUC_VCS2_VCS1_IER, ~irqs);
I915_WRITE(GUC_WD_VECS_IER, ~irqs);
/*
* If GuC has routed PM interrupts to itself, don't keep it.
* and keep other interrupts those are unmasked by GuC.
*/
tmp = I915_READ(GEN6_PMINTRMSK);
if (tmp & GEN8_PMINTR_REDIRECT_TO_NON_DISP) {
dev_priv->rps.pm_intr_keep |= ~(tmp & ~GEN8_PMINTR_REDIRECT_TO_NON_DISP);
dev_priv->rps.pm_intr_keep &= ~GEN8_PMINTR_REDIRECT_TO_NON_DISP;
}
}
static u32 get_gttype(struct drm_i915_private *dev_priv)
@ -386,65 +397,58 @@ static int i915_reset_guc(struct drm_i915_private *dev_priv)
}
/**
* intel_guc_ucode_load() - load GuC uCode into the device
* intel_guc_setup() - finish preparing the GuC for activity
* @dev: drm device
*
* Called from gem_init_hw() during driver loading and also after a GPU reset.
*
* The main action required here it to load the GuC uCode into the device.
* The firmware image should have already been fetched into memory by the
* earlier call to intel_guc_ucode_init(), so here we need only check that
* is succeeded, and then transfer the image to the h/w.
* earlier call to intel_guc_init(), so here we need only check that worked,
* and then transfer the image to the h/w.
*
* Return: non-zero code on error
*/
int intel_guc_ucode_load(struct drm_device *dev)
int intel_guc_setup(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
int retries, err = 0;
const char *fw_path = guc_fw->guc_fw_path;
int retries, ret, err;
if (!i915.enable_guc_submission)
return 0;
DRM_DEBUG_DRIVER("GuC fw status: path %s, fetch %s, load %s\n",
fw_path,
intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
/* Loading forbidden, or no firmware to load? */
if (!i915.enable_guc_loading) {
err = 0;
goto fail;
} else if (fw_path == NULL || *fw_path == '\0') {
if (*fw_path == '\0')
DRM_INFO("No GuC firmware known for this platform\n");
err = -ENODEV;
goto fail;
}
/* Fetch failed, or already fetched but failed to load? */
if (guc_fw->guc_fw_fetch_status != GUC_FIRMWARE_SUCCESS) {
err = -EIO;
goto fail;
} else if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_FAIL) {
err = -ENOEXEC;
goto fail;
}
direct_interrupts_to_host(dev_priv);
guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING;
DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n",
intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
intel_guc_fw_status_repr(guc_fw->guc_fw_load_status));
direct_interrupts_to_host(dev_priv);
if (guc_fw->guc_fw_fetch_status == GUC_FIRMWARE_NONE)
return 0;
if (guc_fw->guc_fw_fetch_status == GUC_FIRMWARE_SUCCESS &&
guc_fw->guc_fw_load_status == GUC_FIRMWARE_FAIL)
return -ENOEXEC;
guc_fw->guc_fw_load_status = GUC_FIRMWARE_PENDING;
DRM_DEBUG_DRIVER("GuC fw fetch status %s\n",
intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status));
switch (guc_fw->guc_fw_fetch_status) {
case GUC_FIRMWARE_FAIL:
/* something went wrong :( */
err = -EIO;
goto fail;
case GUC_FIRMWARE_NONE:
case GUC_FIRMWARE_PENDING:
default:
/* "can't happen" */
WARN_ONCE(1, "GuC fw %s invalid guc_fw_fetch_status %s [%d]\n",
guc_fw->guc_fw_path,
intel_guc_fw_status_repr(guc_fw->guc_fw_fetch_status),
guc_fw->guc_fw_fetch_status);
err = -ENXIO;
goto fail;
case GUC_FIRMWARE_SUCCESS:
break;
}
err = i915_guc_submission_init(dev);
if (err)
goto fail;
@ -462,7 +466,7 @@ int intel_guc_ucode_load(struct drm_device *dev)
*/
err = i915_reset_guc(dev_priv);
if (err) {
DRM_ERROR("GuC reset failed, err %d\n", err);
DRM_ERROR("GuC reset failed: %d\n", err);
goto fail;
}
@ -473,8 +477,8 @@ int intel_guc_ucode_load(struct drm_device *dev)
if (--retries == 0)
goto fail;
DRM_INFO("GuC fw load failed, err %d; will reset and "
"retry %d more time(s)\n", err, retries);
DRM_INFO("GuC fw load failed: %d; will reset and "
"retry %d more time(s)\n", err, retries);
}
guc_fw->guc_fw_load_status = GUC_FIRMWARE_SUCCESS;
@ -496,7 +500,6 @@ int intel_guc_ucode_load(struct drm_device *dev)
return 0;
fail:
DRM_ERROR("GuC firmware load failed, err %d\n", err);
if (guc_fw->guc_fw_load_status == GUC_FIRMWARE_PENDING)
guc_fw->guc_fw_load_status = GUC_FIRMWARE_FAIL;
@ -504,7 +507,41 @@ int intel_guc_ucode_load(struct drm_device *dev)
i915_guc_submission_disable(dev);
i915_guc_submission_fini(dev);
return err;
/*
* We've failed to load the firmware :(
*
* Decide whether to disable GuC submission and fall back to
* execlist mode, and whether to hide the error by returning
* zero or to return -EIO, which the caller will treat as a
* nonfatal error (i.e. it doesn't prevent driver load, but
* marks the GPU as wedged until reset).
*/
if (i915.enable_guc_loading > 1) {
ret = -EIO;
} else if (i915.enable_guc_submission > 1) {
ret = -EIO;
} else {
ret = 0;
}
if (err == 0)
DRM_INFO("GuC firmware load skipped\n");
else if (ret == -EIO)
DRM_ERROR("GuC firmware load failed: %d\n", err);
else
DRM_INFO("GuC firmware load failed: %d\n", err);
if (i915.enable_guc_submission) {
if (fw_path == NULL)
DRM_INFO("GuC submission without firmware not supported\n");
if (ret == 0)
DRM_INFO("Falling back to execlist mode\n");
else
DRM_ERROR("GuC init failed: %d\n", ret);
}
i915.enable_guc_submission = 0;
return ret;
}
static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
@ -629,22 +666,25 @@ static void guc_fw_fetch(struct drm_device *dev, struct intel_guc_fw *guc_fw)
}
/**
* intel_guc_ucode_init() - define parameters and fetch firmware
* intel_guc_init() - define parameters and fetch firmware
* @dev: drm device
*
* Called early during driver load, but after GEM is initialised.
*
* The firmware will be transferred to the GuC's memory later,
* when intel_guc_ucode_load() is called.
* when intel_guc_setup() is called.
*/
void intel_guc_ucode_init(struct drm_device *dev)
void intel_guc_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
const char *fw_path;
if (!HAS_GUC_SCHED(dev))
i915.enable_guc_submission = false;
/* A negative value means "use platform default" */
if (i915.enable_guc_loading < 0)
i915.enable_guc_loading = HAS_GUC_UCODE(dev);
if (i915.enable_guc_submission < 0)
i915.enable_guc_submission = HAS_GUC_SCHED(dev);
if (!HAS_GUC_UCODE(dev)) {
fw_path = NULL;
@ -657,26 +697,21 @@ void intel_guc_ucode_init(struct drm_device *dev)
guc_fw->guc_fw_major_wanted = 8;
guc_fw->guc_fw_minor_wanted = 7;
} else {
i915.enable_guc_submission = false;
fw_path = ""; /* unknown device */
}
if (!i915.enable_guc_submission)
return;
guc_fw->guc_dev = dev;
guc_fw->guc_fw_path = fw_path;
guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_NONE;
guc_fw->guc_fw_load_status = GUC_FIRMWARE_NONE;
/* Early (and silent) return if GuC loading is disabled */
if (!i915.enable_guc_loading)
return;
if (fw_path == NULL)
return;
if (*fw_path == '\0') {
DRM_ERROR("No GuC firmware known for this platform\n");
guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_FAIL;
if (*fw_path == '\0')
return;
}
guc_fw->guc_fw_fetch_status = GUC_FIRMWARE_PENDING;
DRM_DEBUG_DRIVER("GuC firmware pending, path %s\n", fw_path);
@ -685,10 +720,10 @@ void intel_guc_ucode_init(struct drm_device *dev)
}
/**
* intel_guc_ucode_fini() - clean up all allocated resources
* intel_guc_fini() - clean up all allocated resources
* @dev: drm device
*/
void intel_guc_ucode_fini(struct drm_device *dev)
void intel_guc_fini(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;

View file

@ -1945,7 +1945,7 @@ void intel_hdmi_init(struct drm_device *dev,
intel_encoder = &intel_dig_port->base;
drm_encoder_init(dev, &intel_encoder->base, &intel_hdmi_enc_funcs,
DRM_MODE_ENCODER_TMDS, NULL);
DRM_MODE_ENCODER_TMDS, "HDMI %c", port_name(port));
intel_encoder->compute_config = intel_hdmi_compute_config;
if (HAS_PCH_SPLIT(dev)) {

View file

@ -231,9 +231,9 @@ enum {
/* Typical size of the average request (2 pipecontrols and a MI_BB) */
#define EXECLISTS_REQUEST_SIZE 64 /* bytes */
static int execlists_context_deferred_alloc(struct intel_context *ctx,
static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
struct intel_engine_cs *engine);
static int intel_lr_context_pin(struct intel_context *ctx,
static int intel_lr_context_pin(struct i915_gem_context *ctx,
struct intel_engine_cs *engine);
/**
@ -302,7 +302,7 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *engine)
* descriptor for a pinned context
*
* @ctx: Context to work on
* @ring: Engine the descriptor will be used with
* @engine: Engine the descriptor will be used with
*
* The context descriptor encodes various attributes of a context,
* including its GTT address and some flags. Because it's fairly
@ -317,22 +317,23 @@ logical_ring_init_platform_invariants(struct intel_engine_cs *engine)
* bits 55-63: group ID, currently unused and set to 0
*/
static void
intel_lr_context_descriptor_update(struct intel_context *ctx,
intel_lr_context_descriptor_update(struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
struct intel_context *ce = &ctx->engine[engine->id];
u64 desc;
BUILD_BUG_ON(MAX_CONTEXT_HW_ID > (1<<GEN8_CTX_ID_WIDTH));
desc = engine->ctx_desc_template; /* bits 0-11 */
desc |= ctx->engine[engine->id].lrc_vma->node.start + /* bits 12-31 */
LRC_PPHWSP_PN * PAGE_SIZE;
desc |= ce->lrc_vma->node.start + LRC_PPHWSP_PN * PAGE_SIZE;
/* bits 12-31 */
desc |= (u64)ctx->hw_id << GEN8_CTX_ID_SHIFT; /* bits 32-52 */
ctx->engine[engine->id].lrc_desc = desc;
ce->lrc_desc = desc;
}
uint64_t intel_lr_context_descriptor(struct intel_context *ctx,
uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
return ctx->engine[engine->id].lrc_desc;
@ -676,6 +677,7 @@ static int execlists_move_to_gpu(struct drm_i915_gem_request *req,
int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request)
{
struct intel_engine_cs *engine = request->engine;
struct intel_context *ce = &request->ctx->engine[engine->id];
int ret;
/* Flush enough space to reduce the likelihood of waiting after
@ -684,13 +686,13 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request
*/
request->reserved_space += EXECLISTS_REQUEST_SIZE;
if (request->ctx->engine[engine->id].state == NULL) {
if (!ce->state) {
ret = execlists_context_deferred_alloc(request->ctx, engine);
if (ret)
return ret;
}
request->ringbuf = request->ctx->engine[engine->id].ringbuf;
request->ringbuf = ce->ringbuf;
if (i915.enable_guc_submission) {
/*
@ -698,9 +700,7 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request
* going any further, as the i915_add_request() call
* later on mustn't fail ...
*/
struct intel_guc *guc = &request->i915->guc;
ret = i915_guc_wq_check_space(guc->execbuf_client);
ret = i915_guc_wq_check_space(request);
if (ret)
return ret;
}
@ -713,12 +713,12 @@ int intel_logical_ring_alloc_request_extras(struct drm_i915_gem_request *request
if (ret)
goto err_unpin;
if (!request->ctx->engine[engine->id].initialised) {
if (!ce->initialised) {
ret = engine->init_context(request);
if (ret)
goto err_unpin;
request->ctx->engine[engine->id].initialised = true;
ce->initialised = true;
}
/* Note that after this point, we have committed to using
@ -749,7 +749,6 @@ static int
intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
{
struct intel_ringbuffer *ringbuf = request->ringbuf;
struct drm_i915_private *dev_priv = request->i915;
struct intel_engine_cs *engine = request->engine;
intel_logical_ring_advance(ringbuf);
@ -777,8 +776,8 @@ intel_logical_ring_advance_and_submit(struct drm_i915_gem_request *request)
request->previous_context = engine->last_context;
engine->last_context = request->ctx;
if (dev_priv->guc.execbuf_client)
i915_guc_submit(dev_priv->guc.execbuf_client, request);
if (i915.enable_guc_submission)
i915_guc_submit(request);
else
execlists_context_queue(request);
@ -934,28 +933,26 @@ int logical_ring_flush_all_caches(struct drm_i915_gem_request *req)
return 0;
}
static int intel_lr_context_pin(struct intel_context *ctx,
static int intel_lr_context_pin(struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
struct drm_i915_private *dev_priv = ctx->i915;
struct drm_i915_gem_object *ctx_obj;
struct intel_ringbuffer *ringbuf;
struct intel_context *ce = &ctx->engine[engine->id];
void *vaddr;
u32 *lrc_reg_state;
int ret;
lockdep_assert_held(&ctx->i915->dev->struct_mutex);
if (ctx->engine[engine->id].pin_count++)
if (ce->pin_count++)
return 0;
ctx_obj = ctx->engine[engine->id].state;
ret = i915_gem_obj_ggtt_pin(ctx_obj, GEN8_LR_CONTEXT_ALIGN,
PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
ret = i915_gem_obj_ggtt_pin(ce->state, GEN8_LR_CONTEXT_ALIGN,
PIN_OFFSET_BIAS | GUC_WOPCM_TOP);
if (ret)
goto err;
vaddr = i915_gem_object_pin_map(ctx_obj);
vaddr = i915_gem_object_pin_map(ce->state);
if (IS_ERR(vaddr)) {
ret = PTR_ERR(vaddr);
goto unpin_ctx_obj;
@ -963,17 +960,17 @@ static int intel_lr_context_pin(struct intel_context *ctx,
lrc_reg_state = vaddr + LRC_STATE_PN * PAGE_SIZE;
ringbuf = ctx->engine[engine->id].ringbuf;
ret = intel_pin_and_map_ringbuffer_obj(dev_priv, ringbuf);
ret = intel_pin_and_map_ringbuffer_obj(dev_priv, ce->ringbuf);
if (ret)
goto unpin_map;
i915_gem_context_reference(ctx);
ctx->engine[engine->id].lrc_vma = i915_gem_obj_to_ggtt(ctx_obj);
ce->lrc_vma = i915_gem_obj_to_ggtt(ce->state);
intel_lr_context_descriptor_update(ctx, engine);
lrc_reg_state[CTX_RING_BUFFER_START+1] = ringbuf->vma->node.start;
ctx->engine[engine->id].lrc_reg_state = lrc_reg_state;
ctx_obj->dirty = true;
lrc_reg_state[CTX_RING_BUFFER_START+1] = ce->ringbuf->vma->node.start;
ce->lrc_reg_state = lrc_reg_state;
ce->state->dirty = true;
/* Invalidate GuC TLB. */
if (i915.enable_guc_submission)
@ -982,34 +979,33 @@ static int intel_lr_context_pin(struct intel_context *ctx,
return 0;
unpin_map:
i915_gem_object_unpin_map(ctx_obj);
i915_gem_object_unpin_map(ce->state);
unpin_ctx_obj:
i915_gem_object_ggtt_unpin(ctx_obj);
i915_gem_object_ggtt_unpin(ce->state);
err:
ctx->engine[engine->id].pin_count = 0;
ce->pin_count = 0;
return ret;
}
void intel_lr_context_unpin(struct intel_context *ctx,
void intel_lr_context_unpin(struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
struct drm_i915_gem_object *ctx_obj;
struct intel_context *ce = &ctx->engine[engine->id];
lockdep_assert_held(&ctx->i915->dev->struct_mutex);
GEM_BUG_ON(ctx->engine[engine->id].pin_count == 0);
GEM_BUG_ON(ce->pin_count == 0);
if (--ctx->engine[engine->id].pin_count)
if (--ce->pin_count)
return;
intel_unpin_ringbuffer_obj(ctx->engine[engine->id].ringbuf);
intel_unpin_ringbuffer_obj(ce->ringbuf);
ctx_obj = ctx->engine[engine->id].state;
i915_gem_object_unpin_map(ctx_obj);
i915_gem_object_ggtt_unpin(ctx_obj);
i915_gem_object_unpin_map(ce->state);
i915_gem_object_ggtt_unpin(ce->state);
ctx->engine[engine->id].lrc_vma = NULL;
ctx->engine[engine->id].lrc_desc = 0;
ctx->engine[engine->id].lrc_reg_state = NULL;
ce->lrc_vma = NULL;
ce->lrc_desc = 0;
ce->lrc_reg_state = NULL;
i915_gem_context_unreference(ctx);
}
@ -2051,7 +2047,7 @@ logical_ring_setup(struct drm_device *dev, enum intel_engine_id id)
static int
logical_ring_init(struct intel_engine_cs *engine)
{
struct intel_context *dctx = engine->i915->kernel_context;
struct i915_gem_context *dctx = engine->i915->kernel_context;
int ret;
ret = i915_cmd_parser_init_ring(engine);
@ -2275,7 +2271,7 @@ static u32 intel_lr_indirect_ctx_offset(struct intel_engine_cs *engine)
}
static int
populate_lr_context(struct intel_context *ctx,
populate_lr_context(struct i915_gem_context *ctx,
struct drm_i915_gem_object *ctx_obj,
struct intel_engine_cs *engine,
struct intel_ringbuffer *ringbuf)
@ -2415,31 +2411,6 @@ populate_lr_context(struct intel_context *ctx,
return 0;
}
/**
* intel_lr_context_free() - free the LRC specific bits of a context
* @ctx: the LR context to free.
*
* The real context freeing is done in i915_gem_context_free: this only
* takes care of the bits that are LRC related: the per-engine backing
* objects and the logical ringbuffer.
*/
void intel_lr_context_free(struct intel_context *ctx)
{
int i;
for (i = I915_NUM_ENGINES; --i >= 0; ) {
struct intel_ringbuffer *ringbuf = ctx->engine[i].ringbuf;
struct drm_i915_gem_object *ctx_obj = ctx->engine[i].state;
if (!ctx_obj)
continue;
WARN_ON(ctx->engine[i].pin_count);
intel_ringbuffer_free(ringbuf);
drm_gem_object_unreference(&ctx_obj->base);
}
}
/**
* intel_lr_context_size() - return the size of the context for an engine
* @ring: which engine to find the context size for
@ -2491,16 +2462,16 @@ uint32_t intel_lr_context_size(struct intel_engine_cs *engine)
*
* Return: non-zero on error.
*/
static int execlists_context_deferred_alloc(struct intel_context *ctx,
static int execlists_context_deferred_alloc(struct i915_gem_context *ctx,
struct intel_engine_cs *engine)
{
struct drm_i915_gem_object *ctx_obj;
struct intel_context *ce = &ctx->engine[engine->id];
uint32_t context_size;
struct intel_ringbuffer *ringbuf;
int ret;
WARN_ON(ctx->legacy_hw_ctx.rcs_state != NULL);
WARN_ON(ctx->engine[engine->id].state);
WARN_ON(ce->state);
context_size = round_up(intel_lr_context_size(engine), 4096);
@ -2525,9 +2496,9 @@ static int execlists_context_deferred_alloc(struct intel_context *ctx,
goto error_ringbuf;
}
ctx->engine[engine->id].ringbuf = ringbuf;
ctx->engine[engine->id].state = ctx_obj;
ctx->engine[engine->id].initialised = engine->init_context == NULL;
ce->ringbuf = ringbuf;
ce->state = ctx_obj;
ce->initialised = engine->init_context == NULL;
return 0;
@ -2535,21 +2506,19 @@ static int execlists_context_deferred_alloc(struct intel_context *ctx,
intel_ringbuffer_free(ringbuf);
error_deref_obj:
drm_gem_object_unreference(&ctx_obj->base);
ctx->engine[engine->id].ringbuf = NULL;
ctx->engine[engine->id].state = NULL;
ce->ringbuf = NULL;
ce->state = NULL;
return ret;
}
void intel_lr_context_reset(struct drm_i915_private *dev_priv,
struct intel_context *ctx)
struct i915_gem_context *ctx)
{
struct intel_engine_cs *engine;
for_each_engine(engine, dev_priv) {
struct drm_i915_gem_object *ctx_obj =
ctx->engine[engine->id].state;
struct intel_ringbuffer *ringbuf =
ctx->engine[engine->id].ringbuf;
struct intel_context *ce = &ctx->engine[engine->id];
struct drm_i915_gem_object *ctx_obj = ce->state;
void *vaddr;
uint32_t *reg_state;
@ -2568,7 +2537,7 @@ void intel_lr_context_reset(struct drm_i915_private *dev_priv,
i915_gem_object_unpin_map(ctx_obj);
ringbuf->head = 0;
ringbuf->tail = 0;
ce->ringbuf->head = 0;
ce->ringbuf->tail = 0;
}
}

View file

@ -99,16 +99,17 @@ static inline void intel_logical_ring_emit_reg(struct intel_ringbuffer *ringbuf,
#define LRC_PPHWSP_PN (LRC_GUCSHR_PN + 1)
#define LRC_STATE_PN (LRC_PPHWSP_PN + 1)
void intel_lr_context_free(struct intel_context *ctx);
struct i915_gem_context;
uint32_t intel_lr_context_size(struct intel_engine_cs *engine);
void intel_lr_context_unpin(struct intel_context *ctx,
void intel_lr_context_unpin(struct i915_gem_context *ctx,
struct intel_engine_cs *engine);
struct drm_i915_private;
void intel_lr_context_reset(struct drm_i915_private *dev_priv,
struct intel_context *ctx);
uint64_t intel_lr_context_descriptor(struct intel_context *ctx,
struct i915_gem_context *ctx);
uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx,
struct intel_engine_cs *engine);
/* Execlists */

View file

@ -978,7 +978,7 @@ void intel_lvds_init(struct drm_device *dev)
DRM_MODE_CONNECTOR_LVDS);
drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
DRM_MODE_ENCODER_LVDS, NULL);
DRM_MODE_ENCODER_LVDS, "LVDS");
intel_encoder->enable = intel_enable_lvds;
intel_encoder->pre_enable = intel_pre_enable_lvds;
@ -1082,6 +1082,8 @@ void intel_lvds_init(struct drm_device *dev)
fixed_mode = drm_mode_duplicate(dev, dev_priv->vbt.lfp_lvds_vbt_mode);
if (fixed_mode) {
fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
connector->display_info.width_mm = fixed_mode->width_mm;
connector->display_info.height_mm = fixed_mode->height_mm;
goto out;
}
}

View file

@ -240,10 +240,11 @@ struct opregion_asle_ext {
#define MAX_DSLP 1500
static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
static int swsci(struct drm_i915_private *dev_priv,
u32 function, u32 parm, u32 *parm_out)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct opregion_swsci *swsci = dev_priv->opregion.swsci;
struct pci_dev *pdev = dev_priv->dev->pdev;
u32 main_function, sub_function, scic;
u16 swsci_val;
u32 dslp;
@ -293,16 +294,16 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
swsci->scic = scic;
/* Ensure SCI event is selected and event trigger is cleared. */
pci_read_config_word(dev->pdev, SWSCI, &swsci_val);
pci_read_config_word(pdev, SWSCI, &swsci_val);
if (!(swsci_val & SWSCI_SCISEL) || (swsci_val & SWSCI_GSSCIE)) {
swsci_val |= SWSCI_SCISEL;
swsci_val &= ~SWSCI_GSSCIE;
pci_write_config_word(dev->pdev, SWSCI, swsci_val);
pci_write_config_word(pdev, SWSCI, swsci_val);
}
/* Use event trigger to tell bios to check the mail. */
swsci_val |= SWSCI_GSSCIE;
pci_write_config_word(dev->pdev, SWSCI, swsci_val);
pci_write_config_word(pdev, SWSCI, swsci_val);
/* Poll for the result. */
#define C (((scic = swsci->scic) & SWSCI_SCIC_INDICATOR) == 0)
@ -336,13 +337,13 @@ static int swsci(struct drm_device *dev, u32 function, u32 parm, u32 *parm_out)
int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
bool enable)
{
struct drm_device *dev = intel_encoder->base.dev;
struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
u32 parm = 0;
u32 type = 0;
u32 port;
/* don't care about old stuff for now */
if (!HAS_DDI(dev))
if (!HAS_DDI(dev_priv))
return 0;
if (intel_encoder->type == INTEL_OUTPUT_DSI)
@ -382,7 +383,7 @@ int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
parm |= type << (16 + port * 3);
return swsci(dev, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL);
return swsci(dev_priv, SWSCI_SBCB_DISPLAY_POWER_STATE, parm, NULL);
}
static const struct {
@ -396,27 +397,28 @@ static const struct {
{ PCI_D3cold, 0x04 },
};
int intel_opregion_notify_adapter(struct drm_device *dev, pci_power_t state)
int intel_opregion_notify_adapter(struct drm_i915_private *dev_priv,
pci_power_t state)
{
int i;
if (!HAS_DDI(dev))
if (!HAS_DDI(dev_priv))
return 0;
for (i = 0; i < ARRAY_SIZE(power_state_map); i++) {
if (state == power_state_map[i].pci_power_state)
return swsci(dev, SWSCI_SBCB_ADAPTER_POWER_STATE,
return swsci(dev_priv, SWSCI_SBCB_ADAPTER_POWER_STATE,
power_state_map[i].parm, NULL);
}
return -EINVAL;
}
static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
static u32 asle_set_backlight(struct drm_i915_private *dev_priv, u32 bclp)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_connector *connector;
struct opregion_asle *asle = dev_priv->opregion.asle;
struct drm_device *dev = dev_priv->dev;
DRM_DEBUG_DRIVER("bclp = 0x%08x\n", bclp);
@ -449,7 +451,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
return 0;
}
static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
static u32 asle_set_als_illum(struct drm_i915_private *dev_priv, u32 alsi)
{
/* alsi is the current ALS reading in lux. 0 indicates below sensor
range, 0xffff indicates above sensor range. 1-0xfffe are valid */
@ -457,13 +459,13 @@ static u32 asle_set_als_illum(struct drm_device *dev, u32 alsi)
return ASLC_ALS_ILLUM_FAILED;
}
static u32 asle_set_pwm_freq(struct drm_device *dev, u32 pfmb)
static u32 asle_set_pwm_freq(struct drm_i915_private *dev_priv, u32 pfmb)
{
DRM_DEBUG_DRIVER("PWM freq is not supported\n");
return ASLC_PWM_FREQ_FAILED;
}
static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
static u32 asle_set_pfit(struct drm_i915_private *dev_priv, u32 pfit)
{
/* Panel fitting is currently controlled by the X code, so this is a
noop until modesetting support works fully */
@ -471,13 +473,13 @@ static u32 asle_set_pfit(struct drm_device *dev, u32 pfit)
return ASLC_PFIT_FAILED;
}
static u32 asle_set_supported_rotation_angles(struct drm_device *dev, u32 srot)
static u32 asle_set_supported_rotation_angles(struct drm_i915_private *dev_priv, u32 srot)
{
DRM_DEBUG_DRIVER("SROT is not supported\n");
return ASLC_ROTATION_ANGLES_FAILED;
}
static u32 asle_set_button_array(struct drm_device *dev, u32 iuer)
static u32 asle_set_button_array(struct drm_i915_private *dev_priv, u32 iuer)
{
if (!iuer)
DRM_DEBUG_DRIVER("Button array event is not supported (nothing)\n");
@ -495,7 +497,7 @@ static u32 asle_set_button_array(struct drm_device *dev, u32 iuer)
return ASLC_BUTTON_ARRAY_FAILED;
}
static u32 asle_set_convertible(struct drm_device *dev, u32 iuer)
static u32 asle_set_convertible(struct drm_i915_private *dev_priv, u32 iuer)
{
if (iuer & ASLE_IUER_CONVERTIBLE)
DRM_DEBUG_DRIVER("Convertible is not supported (clamshell)\n");
@ -505,7 +507,7 @@ static u32 asle_set_convertible(struct drm_device *dev, u32 iuer)
return ASLC_CONVERTIBLE_FAILED;
}
static u32 asle_set_docking(struct drm_device *dev, u32 iuer)
static u32 asle_set_docking(struct drm_i915_private *dev_priv, u32 iuer)
{
if (iuer & ASLE_IUER_DOCKING)
DRM_DEBUG_DRIVER("Docking is not supported (docked)\n");
@ -515,7 +517,7 @@ static u32 asle_set_docking(struct drm_device *dev, u32 iuer)
return ASLC_DOCKING_FAILED;
}
static u32 asle_isct_state(struct drm_device *dev)
static u32 asle_isct_state(struct drm_i915_private *dev_priv)
{
DRM_DEBUG_DRIVER("ISCT is not supported\n");
return ASLC_ISCT_STATE_FAILED;
@ -527,7 +529,6 @@ static void asle_work(struct work_struct *work)
container_of(work, struct intel_opregion, asle_work);
struct drm_i915_private *dev_priv =
container_of(opregion, struct drm_i915_private, opregion);
struct drm_device *dev = dev_priv->dev;
struct opregion_asle *asle = dev_priv->opregion.asle;
u32 aslc_stat = 0;
u32 aslc_req;
@ -544,32 +545,32 @@ static void asle_work(struct work_struct *work)
}
if (aslc_req & ASLC_SET_ALS_ILLUM)
aslc_stat |= asle_set_als_illum(dev, asle->alsi);
aslc_stat |= asle_set_als_illum(dev_priv, asle->alsi);
if (aslc_req & ASLC_SET_BACKLIGHT)
aslc_stat |= asle_set_backlight(dev, asle->bclp);
aslc_stat |= asle_set_backlight(dev_priv, asle->bclp);
if (aslc_req & ASLC_SET_PFIT)
aslc_stat |= asle_set_pfit(dev, asle->pfit);
aslc_stat |= asle_set_pfit(dev_priv, asle->pfit);
if (aslc_req & ASLC_SET_PWM_FREQ)
aslc_stat |= asle_set_pwm_freq(dev, asle->pfmb);
aslc_stat |= asle_set_pwm_freq(dev_priv, asle->pfmb);
if (aslc_req & ASLC_SUPPORTED_ROTATION_ANGLES)
aslc_stat |= asle_set_supported_rotation_angles(dev,
aslc_stat |= asle_set_supported_rotation_angles(dev_priv,
asle->srot);
if (aslc_req & ASLC_BUTTON_ARRAY)
aslc_stat |= asle_set_button_array(dev, asle->iuer);
aslc_stat |= asle_set_button_array(dev_priv, asle->iuer);
if (aslc_req & ASLC_CONVERTIBLE_INDICATOR)
aslc_stat |= asle_set_convertible(dev, asle->iuer);
aslc_stat |= asle_set_convertible(dev_priv, asle->iuer);
if (aslc_req & ASLC_DOCKING_INDICATOR)
aslc_stat |= asle_set_docking(dev, asle->iuer);
aslc_stat |= asle_set_docking(dev_priv, asle->iuer);
if (aslc_req & ASLC_ISCT_STATE_CHANGE)
aslc_stat |= asle_isct_state(dev);
aslc_stat |= asle_isct_state(dev_priv);
asle->aslc = aslc_stat;
}
@ -656,10 +657,10 @@ static void set_did(struct intel_opregion *opregion, int i, u32 val)
}
}
static void intel_didl_outputs(struct drm_device *dev)
static void intel_didl_outputs(struct drm_i915_private *dev_priv)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_opregion *opregion = &dev_priv->opregion;
struct pci_dev *pdev = dev_priv->dev->pdev;
struct drm_connector *connector;
acpi_handle handle;
struct acpi_device *acpi_dev, *acpi_cdev, *acpi_video_bus = NULL;
@ -668,7 +669,7 @@ static void intel_didl_outputs(struct drm_device *dev)
u32 temp, max_outputs;
int i = 0;
handle = ACPI_HANDLE(&dev->pdev->dev);
handle = ACPI_HANDLE(&pdev->dev);
if (!handle || acpi_bus_get_device(handle, &acpi_dev))
return;
@ -723,7 +724,7 @@ static void intel_didl_outputs(struct drm_device *dev)
blind_set:
i = 0;
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
list_for_each_entry(connector, &dev_priv->dev->mode_config.connector_list, head) {
int output_type = ACPI_OTHER_OUTPUT;
if (i >= max_outputs) {
DRM_DEBUG_KMS("More than %u outputs in connector list\n",
@ -759,9 +760,8 @@ static void intel_didl_outputs(struct drm_device *dev)
goto end;
}
static void intel_setup_cadls(struct drm_device *dev)
static void intel_setup_cadls(struct drm_i915_private *dev_priv)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_opregion *opregion = &dev_priv->opregion;
int i = 0;
u32 disp_id;
@ -778,17 +778,16 @@ static void intel_setup_cadls(struct drm_device *dev)
} while (++i < 8 && disp_id != 0);
}
void intel_opregion_init(struct drm_device *dev)
void intel_opregion_register(struct drm_i915_private *dev_priv)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_opregion *opregion = &dev_priv->opregion;
if (!opregion->header)
return;
if (opregion->acpi) {
intel_didl_outputs(dev);
intel_setup_cadls(dev);
intel_didl_outputs(dev_priv);
intel_setup_cadls(dev_priv);
/* Notify BIOS we are ready to handle ACPI video ext notifs.
* Right now, all the events are handled by the ACPI video module.
@ -806,9 +805,8 @@ void intel_opregion_init(struct drm_device *dev)
}
}
void intel_opregion_fini(struct drm_device *dev)
void intel_opregion_unregister(struct drm_i915_private *dev_priv)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_opregion *opregion = &dev_priv->opregion;
if (!opregion->header)
@ -840,9 +838,8 @@ void intel_opregion_fini(struct drm_device *dev)
opregion->lid_state = NULL;
}
static void swsci_setup(struct drm_device *dev)
static void swsci_setup(struct drm_i915_private *dev_priv)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_opregion *opregion = &dev_priv->opregion;
bool requested_callbacks = false;
u32 tmp;
@ -852,7 +849,7 @@ static void swsci_setup(struct drm_device *dev)
opregion->swsci_sbcb_sub_functions = 1;
/* We use GBDA to ask for supported GBDA calls. */
if (swsci(dev, SWSCI_GBDA_SUPPORTED_CALLS, 0, &tmp) == 0) {
if (swsci(dev_priv, SWSCI_GBDA_SUPPORTED_CALLS, 0, &tmp) == 0) {
/* make the bits match the sub-function codes */
tmp <<= 1;
opregion->swsci_gbda_sub_functions |= tmp;
@ -863,7 +860,7 @@ static void swsci_setup(struct drm_device *dev)
* must not call interfaces that are not specifically requested by the
* bios.
*/
if (swsci(dev, SWSCI_GBDA_REQUESTED_CALLBACKS, 0, &tmp) == 0) {
if (swsci(dev_priv, SWSCI_GBDA_REQUESTED_CALLBACKS, 0, &tmp) == 0) {
/* here, the bits already match sub-function codes */
opregion->swsci_sbcb_sub_functions |= tmp;
requested_callbacks = true;
@ -874,7 +871,7 @@ static void swsci_setup(struct drm_device *dev)
* the callback is _requested_. But we still can't call interfaces that
* are not requested.
*/
if (swsci(dev, SWSCI_SBCB_SUPPORTED_CALLBACKS, 0, &tmp) == 0) {
if (swsci(dev_priv, SWSCI_SBCB_SUPPORTED_CALLBACKS, 0, &tmp) == 0) {
/* make the bits match the sub-function codes */
u32 low = tmp & 0x7ff;
u32 high = tmp & ~0xfff; /* bit 11 is reserved */
@ -916,10 +913,10 @@ static const struct dmi_system_id intel_no_opregion_vbt[] = {
{ }
};
int intel_opregion_setup(struct drm_device *dev)
int intel_opregion_setup(struct drm_i915_private *dev_priv)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_opregion *opregion = &dev_priv->opregion;
struct pci_dev *pdev = dev_priv->dev->pdev;
u32 asls, mboxes;
char buf[sizeof(OPREGION_SIGNATURE)];
int err = 0;
@ -931,7 +928,7 @@ int intel_opregion_setup(struct drm_device *dev)
BUILD_BUG_ON(sizeof(struct opregion_asle) != 0x100);
BUILD_BUG_ON(sizeof(struct opregion_asle_ext) != 0x400);
pci_read_config_dword(dev->pdev, ASLS, &asls);
pci_read_config_dword(pdev, ASLS, &asls);
DRM_DEBUG_DRIVER("graphic opregion physical addr: 0x%x\n", asls);
if (asls == 0) {
DRM_DEBUG_DRIVER("ACPI OpRegion not supported!\n");
@ -963,7 +960,7 @@ int intel_opregion_setup(struct drm_device *dev)
if (mboxes & MBOX_SWSCI) {
DRM_DEBUG_DRIVER("SWSCI supported\n");
opregion->swsci = base + OPREGION_SWSCI_OFFSET;
swsci_setup(dev);
swsci_setup(dev_priv);
}
if (mboxes & MBOX_ASLE) {
@ -1012,12 +1009,12 @@ int intel_opregion_setup(struct drm_device *dev)
}
int
intel_opregion_get_panel_type(struct drm_device *dev)
intel_opregion_get_panel_type(struct drm_i915_private *dev_priv)
{
u32 panel_details;
int ret;
ret = swsci(dev, SWSCI_GBDA_PANEL_DETAILS, 0x0, &panel_details);
ret = swsci(dev_priv, SWSCI_GBDA_PANEL_DETAILS, 0x0, &panel_details);
if (ret) {
DRM_DEBUG_KMS("Failed to get panel details from OpRegion (%d)\n",
ret);

View file

@ -26,6 +26,7 @@
*/
#include <linux/cpufreq.h>
#include <drm/drm_plane_helper.h>
#include "i915_drv.h"
#include "intel_drv.h"
#include "../../../platform/x86/intel_ips.h"
@ -2949,6 +2950,46 @@ void skl_ddb_get_hw_state(struct drm_i915_private *dev_priv,
}
}
/*
* Determines the downscale amount of a plane for the purposes of watermark calculations.
* The bspec defines downscale amount as:
*
* """
* Horizontal down scale amount = maximum[1, Horizontal source size /
* Horizontal destination size]
* Vertical down scale amount = maximum[1, Vertical source size /
* Vertical destination size]
* Total down scale amount = Horizontal down scale amount *
* Vertical down scale amount
* """
*
* Return value is provided in 16.16 fixed point form to retain fractional part.
* Caller should take care of dividing & rounding off the value.
*/
static uint32_t
skl_plane_downscale_amount(const struct intel_plane_state *pstate)
{
uint32_t downscale_h, downscale_w;
uint32_t src_w, src_h, dst_w, dst_h;
if (WARN_ON(!pstate->visible))
return DRM_PLANE_HELPER_NO_SCALING;
/* n.b., src is 16.16 fixed point, dst is whole integer */
src_w = drm_rect_width(&pstate->src);
src_h = drm_rect_height(&pstate->src);
dst_w = drm_rect_width(&pstate->dst);
dst_h = drm_rect_height(&pstate->dst);
if (intel_rotation_90_or_270(pstate->base.rotation))
swap(dst_w, dst_h);
downscale_h = max(src_h / dst_h, (uint32_t)DRM_PLANE_HELPER_NO_SCALING);
downscale_w = max(src_w / dst_w, (uint32_t)DRM_PLANE_HELPER_NO_SCALING);
/* Provide result in 16.16 fixed point */
return (uint64_t)downscale_w * downscale_h >> 16;
}
static unsigned int
skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
const struct drm_plane_state *pstate,
@ -2956,6 +2997,7 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
{
struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
struct drm_framebuffer *fb = pstate->fb;
uint32_t down_scale_amount, data_rate;
uint32_t width = 0, height = 0;
unsigned format = fb ? fb->pixel_format : DRM_FORMAT_XRGB8888;
@ -2975,15 +3017,19 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
/* for planar format */
if (format == DRM_FORMAT_NV12) {
if (y) /* y-plane data rate */
return width * height *
data_rate = width * height *
drm_format_plane_cpp(format, 0);
else /* uv-plane data rate */
return (width / 2) * (height / 2) *
data_rate = (width / 2) * (height / 2) *
drm_format_plane_cpp(format, 1);
} else {
/* for packed formats */
data_rate = width * height * drm_format_plane_cpp(format, 0);
}
/* for packed formats */
return width * height * drm_format_plane_cpp(format, 0);
down_scale_amount = skl_plane_downscale_amount(intel_pstate);
return (uint64_t)data_rate * down_scale_amount >> 16;
}
/*
@ -3042,6 +3088,69 @@ skl_get_total_relative_data_rate(struct intel_crtc_state *intel_cstate)
return total_data_rate;
}
static uint16_t
skl_ddb_min_alloc(const struct drm_plane_state *pstate,
const int y)
{
struct drm_framebuffer *fb = pstate->fb;
struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
uint32_t src_w, src_h;
uint32_t min_scanlines = 8;
uint8_t plane_bpp;
if (WARN_ON(!fb))
return 0;
/* For packed formats, no y-plane, return 0 */
if (y && fb->pixel_format != DRM_FORMAT_NV12)
return 0;
/* For Non Y-tile return 8-blocks */
if (fb->modifier[0] != I915_FORMAT_MOD_Y_TILED &&
fb->modifier[0] != I915_FORMAT_MOD_Yf_TILED)
return 8;
src_w = drm_rect_width(&intel_pstate->src) >> 16;
src_h = drm_rect_height(&intel_pstate->src) >> 16;
if (intel_rotation_90_or_270(pstate->rotation))
swap(src_w, src_h);
/* Halve UV plane width and height for NV12 */
if (fb->pixel_format == DRM_FORMAT_NV12 && !y) {
src_w /= 2;
src_h /= 2;
}
if (fb->pixel_format == DRM_FORMAT_NV12 && !y)
plane_bpp = drm_format_plane_cpp(fb->pixel_format, 1);
else
plane_bpp = drm_format_plane_cpp(fb->pixel_format, 0);
if (intel_rotation_90_or_270(pstate->rotation)) {
switch (plane_bpp) {
case 1:
min_scanlines = 32;
break;
case 2:
min_scanlines = 16;
break;
case 4:
min_scanlines = 8;
break;
case 8:
min_scanlines = 4;
break;
default:
WARN(1, "Unsupported pixel depth %u for rotation",
plane_bpp);
min_scanlines = 32;
}
}
return DIV_ROUND_UP((4 * src_w * plane_bpp), 512) * min_scanlines/4 + 3;
}
static int
skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
struct skl_ddb_allocation *ddb /* out */)
@ -3104,11 +3213,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
continue;
}
minimum[id] = 8;
if (pstate->fb->pixel_format == DRM_FORMAT_NV12)
y_minimum[id] = 8;
else
y_minimum[id] = 0;
minimum[id] = skl_ddb_min_alloc(pstate, 0);
y_minimum[id] = skl_ddb_min_alloc(pstate, 1);
}
for (i = 0; i < PLANE_CURSOR; i++) {
@ -3225,6 +3331,30 @@ static uint32_t skl_wm_method2(uint32_t pixel_rate, uint32_t pipe_htotal,
return ret;
}
static uint32_t skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cstate,
struct intel_plane_state *pstate)
{
uint64_t adjusted_pixel_rate;
uint64_t downscale_amount;
uint64_t pixel_rate;
/* Shouldn't reach here on disabled planes... */
if (WARN_ON(!pstate->visible))
return 0;
/*
* Adjusted plane pixel rate is just the pipe's adjusted pixel rate
* with additional adjustments for plane-specific scaling.
*/
adjusted_pixel_rate = skl_pipe_pixel_rate(cstate);
downscale_amount = skl_plane_downscale_amount(pstate);
pixel_rate = adjusted_pixel_rate * downscale_amount >> 16;
WARN_ON(pixel_rate != clamp_t(uint32_t, pixel_rate, 0, ~0));
return pixel_rate;
}
static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
struct intel_crtc_state *cstate,
struct intel_plane_state *intel_pstate,
@ -3243,6 +3373,7 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
uint32_t selected_result;
uint8_t cpp;
uint32_t width = 0, height = 0;
uint32_t plane_pixel_rate;
if (latency == 0 || !cstate->base.active || !intel_pstate->visible) {
*enabled = false;
@ -3256,9 +3387,10 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
swap(width, height);
cpp = drm_format_plane_cpp(fb->pixel_format, 0);
method1 = skl_wm_method1(skl_pipe_pixel_rate(cstate),
cpp, latency);
method2 = skl_wm_method2(skl_pipe_pixel_rate(cstate),
plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate);
method1 = skl_wm_method1(plane_pixel_rate, cpp, latency);
method2 = skl_wm_method2(plane_pixel_rate,
cstate->base.adjusted_mode.crtc_htotal,
width,
cpp,
@ -4046,7 +4178,6 @@ void skl_wm_get_hw_state(struct drm_device *dev)
struct drm_i915_private *dev_priv = dev->dev_private;
struct skl_ddb_allocation *ddb = &dev_priv->wm.skl_hw.ddb;
struct drm_crtc *crtc;
struct intel_crtc *intel_crtc;
skl_ddb_get_hw_state(dev_priv, ddb);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
@ -4059,23 +4190,6 @@ void skl_wm_get_hw_state(struct drm_device *dev)
/* Easy/common case; just sanitize DDB now if everything off */
memset(ddb, 0, sizeof(*ddb));
}
/* Calculate plane data rates */
for_each_intel_crtc(dev, intel_crtc) {
struct intel_crtc_state *cstate = intel_crtc->config;
struct intel_plane *intel_plane;
for_each_intel_plane_on_crtc(dev, intel_crtc, intel_plane) {
const struct drm_plane_state *pstate =
intel_plane->base.state;
int id = skl_wm_plane_id(intel_plane);
cstate->wm.skl.plane_data_rate[id] =
skl_plane_relative_data_rate(cstate, pstate, 0);
cstate->wm.skl.plane_y_data_rate[id] =
skl_plane_relative_data_rate(cstate, pstate, 1);
}
}
}
static void ilk_pipe_wm_get_hw_state(struct drm_crtc *crtc)
@ -5039,7 +5153,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv)
for_each_engine(engine, dev_priv)
I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10);
if (HAS_GUC_UCODE(dev_priv))
if (HAS_GUC(dev_priv))
I915_WRITE(GUC_MAX_IDLE_COUNT, 0xA);
I915_WRITE(GEN6_RC_SLEEP, 0);

View file

@ -119,7 +119,7 @@ struct intel_ringbuffer {
u32 last_retired_head;
};
struct intel_context;
struct i915_gem_context;
struct drm_i915_reg_table;
/*
@ -310,7 +310,7 @@ struct intel_engine_cs {
wait_queue_head_t irq_queue;
struct intel_context *last_context;
struct i915_gem_context *last_context;
struct intel_ring_hangcheck hangcheck;

View file

@ -806,15 +806,27 @@ static bool gen9_dc_off_power_well_enabled(struct drm_i915_private *dev_priv,
return (I915_READ(DC_STATE_EN) & DC_STATE_EN_UPTO_DC5_DC6_MASK) == 0;
}
static void gen9_assert_dbuf_enabled(struct drm_i915_private *dev_priv)
{
u32 tmp = I915_READ(DBUF_CTL);
WARN((tmp & (DBUF_POWER_STATE | DBUF_POWER_REQUEST)) !=
(DBUF_POWER_STATE | DBUF_POWER_REQUEST),
"Unexpected DBuf power power state (0x%08x)\n", tmp);
}
static void gen9_dc_off_power_well_enable(struct drm_i915_private *dev_priv,
struct i915_power_well *power_well)
{
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
if (IS_BROXTON(dev_priv)) {
broxton_cdclk_verify_state(dev_priv);
WARN_ON(dev_priv->cdclk_freq !=
dev_priv->display.get_display_clock_speed(dev_priv->dev));
gen9_assert_dbuf_enabled(dev_priv);
if (IS_BROXTON(dev_priv))
broxton_ddi_phy_verify_state(dev_priv);
}
}
static void gen9_dc_off_power_well_disable(struct drm_i915_private *dev_priv,
@ -2176,6 +2188,28 @@ static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv)
mutex_unlock(&power_domains->lock);
}
static void gen9_dbuf_enable(struct drm_i915_private *dev_priv)
{
I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) | DBUF_POWER_REQUEST);
POSTING_READ(DBUF_CTL);
udelay(10);
if (!(I915_READ(DBUF_CTL) & DBUF_POWER_STATE))
DRM_ERROR("DBuf power enable timeout\n");
}
static void gen9_dbuf_disable(struct drm_i915_private *dev_priv)
{
I915_WRITE(DBUF_CTL, I915_READ(DBUF_CTL) & ~DBUF_POWER_REQUEST);
POSTING_READ(DBUF_CTL);
udelay(10);
if (I915_READ(DBUF_CTL) & DBUF_POWER_STATE)
DRM_ERROR("DBuf power disable timeout!\n");
}
static void skl_display_core_init(struct drm_i915_private *dev_priv,
bool resume)
{
@ -2200,12 +2234,11 @@ static void skl_display_core_init(struct drm_i915_private *dev_priv,
mutex_unlock(&power_domains->lock);
if (!resume)
return;
skl_init_cdclk(dev_priv);
if (dev_priv->csr.dmc_payload)
gen9_dbuf_enable(dev_priv);
if (resume && dev_priv->csr.dmc_payload)
intel_csr_load_program(dev_priv);
}
@ -2216,6 +2249,8 @@ static void skl_display_core_uninit(struct drm_i915_private *dev_priv)
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
gen9_dbuf_disable(dev_priv);
skl_uninit_cdclk(dev_priv);
/* The spec doesn't call for removing the reset handshake flag */
@ -2260,9 +2295,11 @@ void bxt_display_core_init(struct drm_i915_private *dev_priv,
mutex_unlock(&power_domains->lock);
broxton_init_cdclk(dev_priv);
gen9_dbuf_enable(dev_priv);
broxton_ddi_phy_init(dev_priv);
broxton_cdclk_verify_state(dev_priv);
broxton_ddi_phy_verify_state(dev_priv);
if (resume && dev_priv->csr.dmc_payload)
@ -2277,6 +2314,9 @@ void bxt_display_core_uninit(struct drm_i915_private *dev_priv)
gen9_set_dc_state(dev_priv, DC_STATE_DISABLE);
broxton_ddi_phy_uninit(dev_priv);
gen9_dbuf_disable(dev_priv);
broxton_uninit_cdclk(dev_priv);
/* The spec doesn't call for removing the reset handshake flag */

View file

@ -2981,7 +2981,7 @@ bool intel_sdvo_init(struct drm_device *dev,
intel_encoder = &intel_sdvo->base;
intel_encoder->type = INTEL_OUTPUT_SDVO;
drm_encoder_init(dev, &intel_encoder->base, &intel_sdvo_enc_funcs, 0,
NULL);
"SDVO %c", port_name(port));
/* Read the regs to test if we can talk to the device */
for (i = 0; i < 0x40; i++) {

View file

@ -1114,10 +1114,18 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
possible_crtcs = (1 << pipe);
ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
&intel_plane_funcs,
plane_formats, num_plane_formats,
DRM_PLANE_TYPE_OVERLAY, NULL);
if (INTEL_INFO(dev)->gen >= 9)
ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
&intel_plane_funcs,
plane_formats, num_plane_formats,
DRM_PLANE_TYPE_OVERLAY,
"plane %d%c", plane + 2, pipe_name(pipe));
else
ret = drm_universal_plane_init(dev, &intel_plane->base, possible_crtcs,
&intel_plane_funcs,
plane_formats, num_plane_formats,
DRM_PLANE_TYPE_OVERLAY,
"sprite %c", sprite_name(pipe, plane));
if (ret)
goto fail;

View file

@ -1591,7 +1591,7 @@ intel_tv_init(struct drm_device *dev)
DRM_MODE_CONNECTOR_SVIDEO);
drm_encoder_init(dev, &intel_encoder->base, &intel_tv_enc_funcs,
DRM_MODE_ENCODER_TVDAC, NULL);
DRM_MODE_ENCODER_TVDAC, "TV");
intel_encoder->compute_config = intel_tv_compute_config;
intel_encoder->get_config = intel_tv_get_config;

View file

@ -1715,7 +1715,7 @@ int intel_guc_reset(struct drm_i915_private *dev_priv)
int ret;
unsigned long irqflags;
if (!i915.enable_guc_submission)
if (!HAS_GUC(dev_priv))
return -EINVAL;
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);

View file

@ -403,9 +403,10 @@ struct lvds_dvo_timing {
u8 vsync_off:4;
u8 rsvd0:6;
u8 hsync_off_hi:2;
u8 h_image;
u8 v_image;
u8 max_hv;
u8 himage_lo;
u8 vimage_lo;
u8 vimage_hi:4;
u8 himage_hi:4;
u8 h_border;
u8 v_border;
u8 rsvd1:3;