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

- make modeset hw state checker atomic aware (Maarten)
- close races in gpu stuck detection/seqno reading (Chris)
- tons&tons of small improvements from Chris Wilson all over the gem code
- more dsi/bxt work from Ramalingam&Jani
- macro polish from Joonas
- guc fw loading fixes (Arun&Dave)
- vmap notifier (acked by Andrew) + i915 support by Chris Wilson
- create bottom half for execlist irq processing (Chris Wilson)
- vlv/chv pll cleanup (Ville)
- rework DP detection, especially sink detection (Shubhangi Shrivastava)
- make color manager support fully atomic (Maarten)
- avoid livelock on chv in execlist irq handler (Chris)

* tag 'drm-intel-next-2016-04-11' of git://anongit.freedesktop.org/drm-intel: (82 commits)
  drm/i915: Update DRIVER_DATE to 20160411
  drm/i915: Avoid allocating a vmap arena for a single page
  drm,i915: Introduce drm_malloc_gfp()
  drm/i915/shrinker: Restrict vmap purge to objects with vmaps
  drm/i915: Refactor duplicate object vmap functions
  drm/i915: Consolidate common error handling in intel_pin_and_map_ringbuffer_obj
  drm/i915/dmabuf: Tighten struct_mutex for unmap_dma_buf
  drm/i915: implement WaClearTdlStateAckDirtyBits
  drm/i915/bxt: Reversed polarity of PORT_PLL_REF_SEL bit
  drm/i915: Rename hw state checker to hw state verifier.
  drm/i915: Move modeset state verifier calls.
  drm/i915: Make modeset state verifier take crtc as argument.
  drm/i915: Replace manual barrier() with READ_ONCE() in HWS accessor
  drm/i915: Use simplest form for flushing the single cacheline in the HWS
  drm/i915: Harden detection of missed interrupts
  drm/i915: Separate out the seqno-barrier from engine->get_seqno
  drm/i915: Remove forcewake dance from seqno/irq barrier on legacy gen6+
  drm/i915: Fixup the free space logic in ring_prepare
  drm/i915: Simplify check for idleness in hangcheck
  drm/i915: Apply a mb between emitting the request and hangcheck
  ...
This commit is contained in:
Dave Airlie 2016-04-22 09:03:31 +10:00
commit 605b28c859
50 changed files with 1904 additions and 1227 deletions

View File

@ -134,6 +134,8 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
int pin_count = 0;
enum intel_engine_id id;
lockdep_assert_held(&obj->base.dev->struct_mutex);
seq_printf(m, "%pK: %s%s%s%s %8zdKiB %02x %02x [ ",
&obj->base,
obj->active ? "*" : " ",
@ -202,8 +204,8 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
uintptr_t list = (uintptr_t) node->info_ent->data;
struct list_head *head;
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_address_space *vm = &dev_priv->ggtt.base;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct i915_vma *vma;
u64 total_obj_size, total_gtt_size;
int count, ret;
@ -216,11 +218,11 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
switch (list) {
case ACTIVE_LIST:
seq_puts(m, "Active:\n");
head = &vm->active_list;
head = &ggtt->base.active_list;
break;
case INACTIVE_LIST:
seq_puts(m, "Inactive:\n");
head = &vm->inactive_list;
head = &ggtt->base.inactive_list;
break;
default:
mutex_unlock(&dev->struct_mutex);
@ -429,11 +431,11 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
{
struct drm_info_node *node = m->private;
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
u32 count, mappable_count, purgeable_count;
u64 size, mappable_size, purgeable_size;
struct drm_i915_gem_object *obj;
struct i915_address_space *vm = &dev_priv->ggtt.base;
struct drm_file *file;
struct i915_vma *vma;
int ret;
@ -452,12 +454,12 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
count, mappable_count, size, mappable_size);
size = count = mappable_size = mappable_count = 0;
count_vmas(&vm->active_list, vm_link);
count_vmas(&ggtt->base.active_list, vm_link);
seq_printf(m, " %u [%u] active objects, %llu [%llu] bytes\n",
count, mappable_count, size, mappable_size);
size = count = mappable_size = mappable_count = 0;
count_vmas(&vm->inactive_list, vm_link);
count_vmas(&ggtt->base.inactive_list, vm_link);
seq_printf(m, " %u [%u] inactive objects, %llu [%llu] bytes\n",
count, mappable_count, size, mappable_size);
@ -492,8 +494,7 @@ static int i915_gem_object_info(struct seq_file *m, void* data)
count, size);
seq_printf(m, "%llu [%llu] gtt total\n",
dev_priv->ggtt.base.total,
(u64)dev_priv->ggtt.mappable_end - dev_priv->ggtt.base.start);
ggtt->base.total, ggtt->mappable_end - ggtt->base.start);
seq_putc(m, '\n');
print_batch_pool_stats(m, dev_priv);
@ -597,7 +598,7 @@ static int i915_gem_pageflip_info(struct seq_file *m, void *data)
engine->name,
i915_gem_request_get_seqno(work->flip_queued_req),
dev_priv->next_seqno,
engine->get_seqno(engine, true),
engine->get_seqno(engine),
i915_gem_request_completed(work->flip_queued_req, true));
} else
seq_printf(m, "Flip not associated with any ring\n");
@ -727,10 +728,10 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
static void i915_ring_seqno_info(struct seq_file *m,
struct intel_engine_cs *engine)
{
if (engine->get_seqno) {
seq_printf(m, "Current sequence (%s): %x\n",
engine->name, engine->get_seqno(engine, false));
}
seq_printf(m, "Current sequence (%s): %x\n",
engine->name, engine->get_seqno(engine));
seq_printf(m, "Current user interrupts (%s): %x\n",
engine->name, READ_ONCE(engine->user_interrupts));
}
static int i915_gem_seqno_info(struct seq_file *m, void *data)
@ -1345,8 +1346,8 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
intel_runtime_pm_get(dev_priv);
for_each_engine_id(engine, dev_priv, id) {
seqno[id] = engine->get_seqno(engine, false);
acthd[id] = intel_ring_get_active_head(engine);
seqno[id] = engine->get_seqno(engine);
}
i915_get_extra_instdone(dev, instdone);
@ -1362,8 +1363,13 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused)
for_each_engine_id(engine, dev_priv, id) {
seq_printf(m, "%s:\n", engine->name);
seq_printf(m, "\tseqno = %x [current %x]\n",
engine->hangcheck.seqno, seqno[id]);
seq_printf(m, "\tseqno = %x [current %x, last %x]\n",
engine->hangcheck.seqno,
seqno[id],
engine->last_submitted_seqno);
seq_printf(m, "\tuser interrupts = %x [current %x]\n",
engine->hangcheck.user_interrupts,
READ_ONCE(engine->user_interrupts));
seq_printf(m, "\tACTHD = 0x%08llx [current 0x%08llx]\n",
(long long)engine->hangcheck.acthd,
(long long)acthd[id]);
@ -1895,6 +1901,11 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
struct drm_device *dev = node->minor->dev;
struct intel_framebuffer *fbdev_fb = NULL;
struct drm_framebuffer *drm_fb;
int ret;
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;
#ifdef CONFIG_DRM_FBDEV_EMULATION
if (to_i915(dev)->fbdev) {
@ -1929,6 +1940,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data)
seq_putc(m, '\n');
}
mutex_unlock(&dev->mode_config.fb_lock);
mutex_unlock(&dev->struct_mutex);
return 0;
}
@ -2093,7 +2105,6 @@ static int i915_execlists(struct seq_file *m, void *data)
for_each_engine(engine, dev_priv) {
struct drm_i915_gem_request *head_req = NULL;
int count = 0;
unsigned long flags;
seq_printf(m, "%s\n", engine->name);
@ -2120,13 +2131,13 @@ static int i915_execlists(struct seq_file *m, void *data)
i, status, ctx_id);
}
spin_lock_irqsave(&engine->execlist_lock, flags);
spin_lock_bh(&engine->execlist_lock);
list_for_each(cursor, &engine->execlist_queue)
count++;
head_req = list_first_entry_or_null(&engine->execlist_queue,
struct drm_i915_gem_request,
execlist_link);
spin_unlock_irqrestore(&engine->execlist_lock, flags);
spin_unlock_bh(&engine->execlist_lock);
seq_printf(m, "\t%d requests in queue\n", count);
if (head_req) {
@ -2409,7 +2420,7 @@ static int i915_guc_load_status_info(struct seq_file *m, void *data)
struct intel_guc_fw *guc_fw = &dev_priv->guc.guc_fw;
u32 tmp, i;
if (!HAS_GUC_UCODE(dev_priv->dev))
if (!HAS_GUC_UCODE(dev_priv))
return 0;
seq_printf(m, "GuC firmware status:\n");
@ -2483,7 +2494,7 @@ static int i915_guc_info(struct seq_file *m, void *data)
struct intel_engine_cs *engine;
u64 total = 0;
if (!HAS_GUC_SCHED(dev_priv->dev))
if (!HAS_GUC_SCHED(dev_priv))
return 0;
if (mutex_lock_interruptible(&dev->struct_mutex))
@ -2687,10 +2698,8 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused)
struct drm_device *dev = node->minor->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
if (!HAS_RUNTIME_PM(dev)) {
seq_puts(m, "not supported\n");
return 0;
}
if (!HAS_RUNTIME_PM(dev_priv))
seq_puts(m, "Runtime power management not supported\n");
seq_printf(m, "GPU idle: %s\n", yesno(!dev_priv->mm.busy));
seq_printf(m, "IRQs disabled: %s\n",
@ -2701,6 +2710,9 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused)
#else
seq_printf(m, "Device Power Management (CONFIG_PM) disabled\n");
#endif
seq_printf(m, "PCI device power state: %s [%d]\n",
pci_power_name(dev_priv->dev->pdev->current_state),
dev_priv->dev->pdev->current_state);
return 0;
}

View File

@ -493,9 +493,11 @@ static int i915_load_modeset_init(struct drm_device *dev)
* Some ports require correctly set-up hpd registers for detection to
* work properly (leading to ghost connected connector status), e.g. VGA
* on gm45. Hence we can only set up the initial fbdev config after hpd
* irqs are fully enabled. We protect the fbdev initial config scanning
* against hotplug events by waiting in intel_fbdev_output_poll_changed
* until the asynchronous thread has finished.
* irqs are fully enabled. Now we should scan for the initial config
* only once hotplug handling is enabled, but due to screwed-up locking
* around kms/fbdev init we can't protect the fdbev initial config
* scanning against hotplug events. Hence do this first and ignore the
* tiny window where we will loose hotplug notifactions.
*/
intel_fbdev_initial_config_async(dev);
@ -527,6 +529,7 @@ static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
{
struct apertures_struct *ap;
struct pci_dev *pdev = dev_priv->dev->pdev;
struct i915_ggtt *ggtt = &dev_priv->ggtt;
bool primary;
int ret;
@ -534,8 +537,8 @@ static int i915_kick_out_firmware_fb(struct drm_i915_private *dev_priv)
if (!ap)
return -ENOMEM;
ap->ranges[0].base = dev_priv->ggtt.mappable_base;
ap->ranges[0].size = dev_priv->ggtt.mappable_end;
ap->ranges[0].base = ggtt->mappable_base;
ap->ranges[0].size = ggtt->mappable_end;
primary =
pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW;
@ -1170,6 +1173,7 @@ static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv)
static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
struct i915_ggtt *ggtt = &dev_priv->ggtt;
uint32_t aperture_size;
int ret;
@ -1178,7 +1182,7 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
intel_device_info_runtime_init(dev);
ret = i915_gem_gtt_init(dev);
ret = i915_ggtt_init_hw(dev);
if (ret)
return ret;
@ -1187,13 +1191,13 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
ret = i915_kick_out_firmware_fb(dev_priv);
if (ret) {
DRM_ERROR("failed to remove conflicting framebuffer drivers\n");
goto out_gtt;
goto out_ggtt;
}
ret = i915_kick_out_vgacon(dev_priv);
if (ret) {
DRM_ERROR("failed to remove conflicting VGA console\n");
goto out_gtt;
goto out_ggtt;
}
pci_set_master(dev->pdev);
@ -1213,17 +1217,17 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
if (IS_BROADWATER(dev) || IS_CRESTLINE(dev))
dma_set_coherent_mask(&dev->pdev->dev, DMA_BIT_MASK(32));
aperture_size = dev_priv->ggtt.mappable_end;
aperture_size = ggtt->mappable_end;
dev_priv->ggtt.mappable =
io_mapping_create_wc(dev_priv->ggtt.mappable_base,
ggtt->mappable =
io_mapping_create_wc(ggtt->mappable_base,
aperture_size);
if (dev_priv->ggtt.mappable == NULL) {
if (!ggtt->mappable) {
ret = -EIO;
goto out_gtt;
goto out_ggtt;
}
dev_priv->ggtt.mtrr = arch_phys_wc_add(dev_priv->ggtt.mappable_base,
ggtt->mtrr = arch_phys_wc_add(ggtt->mappable_base,
aperture_size);
pm_qos_add_request(&dev_priv->pm_qos, PM_QOS_CPU_DMA_LATENCY,
@ -1253,8 +1257,8 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
return 0;
out_gtt:
i915_global_gtt_cleanup(dev);
out_ggtt:
i915_ggtt_cleanup_hw(dev);
return ret;
}
@ -1266,14 +1270,15 @@ static int i915_driver_init_hw(struct drm_i915_private *dev_priv)
static void i915_driver_cleanup_hw(struct drm_i915_private *dev_priv)
{
struct drm_device *dev = dev_priv->dev;
struct i915_ggtt *ggtt = &dev_priv->ggtt;
if (dev->pdev->msi_enabled)
pci_disable_msi(dev->pdev);
pm_qos_remove_request(&dev_priv->pm_qos);
arch_phys_wc_del(dev_priv->ggtt.mtrr);
io_mapping_free(dev_priv->ggtt.mappable);
i915_global_gtt_cleanup(dev);
arch_phys_wc_del(ggtt->mtrr);
io_mapping_free(ggtt->mappable);
i915_ggtt_cleanup_hw(dev);
}
/**

View File

@ -360,14 +360,12 @@ static const struct intel_device_info intel_broxton_info = {
static const struct intel_device_info intel_kabylake_info = {
BDW_FEATURES,
.is_preliminary = 1,
.is_kabylake = 1,
.gen = 9,
};
static const struct intel_device_info intel_kabylake_gt3_info = {
BDW_FEATURES,
.is_preliminary = 1,
.is_kabylake = 1,
.gen = 9,
.ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING,
@ -1402,7 +1400,7 @@ static int vlv_suspend_complete(struct drm_i915_private *dev_priv)
if (err)
goto err2;
if (!IS_CHERRYVIEW(dev_priv->dev))
if (!IS_CHERRYVIEW(dev_priv))
vlv_save_gunit_s0ix_state(dev_priv);
err = vlv_force_gfx_clock(dev_priv, false);
@ -1434,7 +1432,7 @@ static int vlv_resume_prepare(struct drm_i915_private *dev_priv,
*/
ret = vlv_force_gfx_clock(dev_priv, true);
if (!IS_CHERRYVIEW(dev_priv->dev))
if (!IS_CHERRYVIEW(dev_priv))
vlv_restore_gunit_s0ix_state(dev_priv);
err = vlv_allow_gt_wake(dev_priv, true);

View File

@ -60,7 +60,7 @@
#define DRIVER_NAME "i915"
#define DRIVER_DESC "Intel Graphics"
#define DRIVER_DATE "20160330"
#define DRIVER_DATE "20160411"
#undef WARN_ON
/* Many gcc seem to no see through this and fall over :( */
@ -495,6 +495,7 @@ struct drm_i915_error_state {
u32 cpu_ring_head;
u32 cpu_ring_tail;
u32 last_seqno;
u32 semaphore_seqno[I915_NUM_ENGINES - 1];
/* Register state */
@ -612,8 +613,8 @@ struct drm_i915_display_funcs {
/* display clock increase/decrease */
/* pll clock increase/decrease */
void (*load_csc_matrix)(struct drm_crtc *crtc);
void (*load_luts)(struct drm_crtc *crtc);
void (*load_csc_matrix)(struct drm_crtc_state *crtc_state);
void (*load_luts)(struct drm_crtc_state *crtc_state);
};
enum forcewake_domain_id {
@ -1118,6 +1119,7 @@ struct intel_gen6_power_mgmt {
u8 efficient_freq; /* AKA RPe. Pre-determined balanced frequency */
u8 rp1_freq; /* "less than" RP0 power/freqency */
u8 rp0_freq; /* Non-overclocked max frequency. */
u16 gpll_ref_freq; /* vlv/chv GPLL reference frequency */
u8 up_threshold; /* Current %busy required to uplock */
u8 down_threshold; /* Current %busy required to downclock */
@ -1257,6 +1259,7 @@ struct i915_gem_mm {
struct i915_hw_ppgtt *aliasing_ppgtt;
struct notifier_block oom_notifier;
struct notifier_block vmap_notifier;
struct shrinker shrinker;
bool shrinker_no_lock_stealing;
@ -1837,6 +1840,13 @@ struct drm_i915_private {
struct intel_shared_dpll shared_dplls[I915_NUM_PLLS];
const struct intel_dpll_mgr *dpll_mgr;
/*
* dpll_lock serializes intel_{prepare,enable,disable}_shared_dpll.
* Must be global rather than per dpll, because on some platforms
* plls share registers.
*/
struct mutex dpll_lock;
unsigned int active_crtcs;
unsigned int min_pixclk[I915_MAX_PIPES];
@ -1893,7 +1903,14 @@ struct drm_i915_private {
u32 fdi_rx_config;
/* Shadow for DISPLAY_PHY_CONTROL which can't be safely read */
u32 chv_phy_control;
/*
* Shadows for CHV DPLL_MD regs to keep the state
* checker somewhat working in the presence hardware
* crappiness (can't read out DPLL_MD for pipes B & C).
*/
u32 chv_dpll_md[I915_MAX_PIPES];
u32 suspend_count;
bool suspended_to_idle;
@ -2152,10 +2169,7 @@ struct drm_i915_gem_object {
struct scatterlist *sg;
int last;
} get_page;
/* prime dma-buf support */
void *dma_buf_vmapping;
int vmapping_count;
void *mapping;
/** Breadcrumb of last rendering to the buffer.
* There can only be one writer, but we allow for multiple readers.
@ -2732,6 +2746,7 @@ extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
extern int intel_gpu_reset(struct drm_device *dev, u32 engine_mask);
extern bool intel_has_gpu_reset(struct drm_device *dev);
extern int i915_reset(struct drm_device *dev);
extern int intel_guc_reset(struct drm_i915_private *dev_priv);
extern void intel_engine_init_hangcheck(struct intel_engine_cs *engine);
extern unsigned long i915_chipset_val(struct drm_i915_private *dev_priv);
extern unsigned long i915_mch_val(struct drm_i915_private *dev_priv);
@ -2970,12 +2985,44 @@ static inline void i915_gem_object_pin_pages(struct drm_i915_gem_object *obj)
BUG_ON(obj->pages == NULL);
obj->pages_pin_count++;
}
static inline void i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj)
{
BUG_ON(obj->pages_pin_count == 0);
obj->pages_pin_count--;
}
/**
* i915_gem_object_pin_map - return a contiguous mapping of the entire object
* @obj - the object to map into kernel address space
*
* Calls i915_gem_object_pin_pages() to prevent reaping of the object's
* pages and then returns a contiguous mapping of the backing storage into
* the kernel address space.
*
* The caller must hold the struct_mutex.
*
* Returns the pointer through which to access the backing storage.
*/
void *__must_check i915_gem_object_pin_map(struct drm_i915_gem_object *obj);
/**
* i915_gem_object_unpin_map - releases an earlier mapping
* @obj - the object to unmap
*
* After pinning the object and mapping its pages, once you are finished
* with your access, call i915_gem_object_unpin_map() to release the pin
* upon the mapping. Once the pin count reaches zero, that mapping may be
* removed.
*
* The caller must hold the struct_mutex.
*/
static inline void i915_gem_object_unpin_map(struct drm_i915_gem_object *obj)
{
lockdep_assert_held(&obj->base.dev->struct_mutex);
i915_gem_object_unpin_pages(obj);
}
int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
int i915_gem_object_sync(struct drm_i915_gem_object *obj,
struct intel_engine_cs *to,
@ -2999,15 +3046,19 @@ i915_seqno_passed(uint32_t seq1, uint32_t seq2)
static inline bool i915_gem_request_started(struct drm_i915_gem_request *req,
bool lazy_coherency)
{
u32 seqno = req->engine->get_seqno(req->engine, lazy_coherency);
return i915_seqno_passed(seqno, req->previous_seqno);
if (!lazy_coherency && req->engine->irq_seqno_barrier)
req->engine->irq_seqno_barrier(req->engine);
return i915_seqno_passed(req->engine->get_seqno(req->engine),
req->previous_seqno);
}
static inline bool i915_gem_request_completed(struct drm_i915_gem_request *req,
bool lazy_coherency)
{
u32 seqno = req->engine->get_seqno(req->engine, lazy_coherency);
return i915_seqno_passed(seqno, req->seqno);
if (!lazy_coherency && req->engine->irq_seqno_barrier)
req->engine->irq_seqno_barrier(req->engine);
return i915_seqno_passed(req->engine->get_seqno(req->engine),
req->seqno);
}
int __must_check i915_gem_get_seqno(struct drm_device *dev, u32 *seqno);
@ -3147,13 +3198,9 @@ i915_gem_obj_to_ggtt(struct drm_i915_gem_object *obj)
bool i915_gem_obj_is_pinned(struct drm_i915_gem_object *obj);
/* Some GGTT VM helpers */
#define i915_obj_to_ggtt(obj) \
(&((struct drm_i915_private *)(obj)->base.dev->dev_private)->ggtt.base)
static inline struct i915_hw_ppgtt *
i915_vm_to_ppgtt(struct i915_address_space *vm)
{
WARN_ON(i915_is_ggtt(vm));
return container_of(vm, struct i915_hw_ppgtt, base);
}
@ -3166,7 +3213,10 @@ static inline bool i915_gem_obj_ggtt_bound(struct drm_i915_gem_object *obj)
static inline unsigned long
i915_gem_obj_ggtt_size(struct drm_i915_gem_object *obj)
{
return i915_gem_obj_size(obj, i915_obj_to_ggtt(obj));
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
return i915_gem_obj_size(obj, &ggtt->base);
}
static inline int __must_check
@ -3174,7 +3224,10 @@ i915_gem_obj_ggtt_pin(struct drm_i915_gem_object *obj,
uint32_t alignment,
unsigned flags)
{
return i915_gem_object_pin(obj, i915_obj_to_ggtt(obj),
struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
return i915_gem_object_pin(obj, &ggtt->base,
alignment, flags | PIN_GLOBAL);
}
@ -3289,6 +3342,7 @@ unsigned long i915_gem_shrink(struct drm_i915_private *dev_priv,
#define I915_SHRINK_UNBOUND 0x2
#define I915_SHRINK_BOUND 0x4
#define I915_SHRINK_ACTIVE 0x8
#define I915_SHRINK_VMAPS 0x10
unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv);
void i915_gem_shrinker_init(struct drm_i915_private *dev_priv);
void i915_gem_shrinker_cleanup(struct drm_i915_private *dev_priv);
@ -3388,6 +3442,8 @@ bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv);
bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin);
bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port);
bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port);
bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv,
enum port port);
/* intel_opregion.c */
#ifdef CONFIG_ACPI

View File

@ -130,9 +130,9 @@ int
i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_get_aperture *args = data;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct drm_i915_gem_get_aperture *args = data;
struct i915_vma *vma;
size_t pinned;
@ -146,7 +146,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
pinned += vma->node.size;
mutex_unlock(&dev->struct_mutex);
args->aper_size = dev_priv->ggtt.base.total;
args->aper_size = ggtt->base.total;
args->aper_available_size = args->aper_size - pinned;
return 0;
@ -765,7 +765,8 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
struct drm_i915_gem_pwrite *args,
struct drm_file *file)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
ssize_t remain;
loff_t offset, page_base;
char __user *user_data;
@ -807,7 +808,7 @@ i915_gem_gtt_pwrite_fast(struct drm_device *dev,
* source page isn't available. Return the error and we'll
* retry in the slow path.
*/
if (fast_user_write(dev_priv->ggtt.mappable, page_base,
if (fast_user_write(ggtt->mappable, page_base,
page_offset, user_data, page_length)) {
ret = -EFAULT;
goto out_flush;
@ -1790,7 +1791,8 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{
struct drm_i915_gem_object *obj = to_intel_bo(vma->vm_private_data);
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct i915_ggtt_view view = i915_ggtt_view_normal;
pgoff_t page_offset;
unsigned long pfn;
@ -1825,7 +1827,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
}
/* Use a partial view if the object is bigger than the aperture. */
if (obj->base.size >= dev_priv->ggtt.mappable_end &&
if (obj->base.size >= ggtt->mappable_end &&
obj->tiling_mode == I915_TILING_NONE) {
static const unsigned int chunk_size = 256; // 1 MiB
@ -1853,7 +1855,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
goto unpin;
/* Finally, remap it using the new GTT offset */
pfn = dev_priv->ggtt.mappable_base +
pfn = ggtt->mappable_base +
i915_gem_obj_ggtt_offset_view(obj, &view);
pfn >>= PAGE_SHIFT;
@ -2227,6 +2229,14 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj)
* lists early. */
list_del(&obj->global_list);
if (obj->mapping) {
if (is_vmalloc_addr(obj->mapping))
vunmap(obj->mapping);
else
kunmap(kmap_to_page(obj->mapping));
obj->mapping = NULL;
}
ops->put_pages(obj);
obj->pages = NULL;
@ -2395,6 +2405,49 @@ i915_gem_object_get_pages(struct drm_i915_gem_object *obj)
return 0;
}
void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj)
{
int ret;
lockdep_assert_held(&obj->base.dev->struct_mutex);
ret = i915_gem_object_get_pages(obj);
if (ret)
return ERR_PTR(ret);
i915_gem_object_pin_pages(obj);
if (obj->mapping == NULL) {
struct page **pages;
pages = NULL;
if (obj->base.size == PAGE_SIZE)
obj->mapping = kmap(sg_page(obj->pages->sgl));
else
pages = drm_malloc_gfp(obj->base.size >> PAGE_SHIFT,
sizeof(*pages),
GFP_TEMPORARY);
if (pages != NULL) {
struct sg_page_iter sg_iter;
int n;
n = 0;
for_each_sg_page(obj->pages->sgl, &sg_iter,
obj->pages->nents, 0)
pages[n++] = sg_page_iter_page(&sg_iter);
obj->mapping = vmap(pages, n, 0, PAGE_KERNEL);
drm_free_large(pages);
}
if (obj->mapping == NULL) {
i915_gem_object_unpin_pages(obj);
return ERR_PTR(-ENOMEM);
}
}
return obj->mapping;
}
void i915_vma_move_to_active(struct i915_vma *vma,
struct drm_i915_gem_request *req)
{
@ -2463,7 +2516,7 @@ i915_gem_init_seqno(struct drm_device *dev, u32 seqno)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_engine_cs *engine;
int ret, j;
int ret;
/* Carefully retire all requests without writing to the rings */
for_each_engine(engine, dev_priv) {
@ -2474,13 +2527,9 @@ i915_gem_init_seqno(struct drm_device *dev, u32 seqno)
i915_gem_retire_requests(dev);
/* Finally reset hw state */
for_each_engine(engine, dev_priv) {
for_each_engine(engine, dev_priv)
intel_ring_init_seqno(engine, seqno);
for (j = 0; j < ARRAY_SIZE(engine->semaphore.sync_seqno); j++)
engine->semaphore.sync_seqno[j] = 0;
}
return 0;
}
@ -2574,6 +2623,28 @@ void __i915_add_request(struct drm_i915_gem_request *request,
WARN(ret, "*_ring_flush_all_caches failed: %d!\n", ret);
}
trace_i915_gem_request_add(request);
request->head = request_start;
/* Whilst this request exists, batch_obj will be on the
* active_list, and so will hold the active reference. Only when this
* request is retired will the the batch_obj be moved onto the
* inactive_list and lose its active reference. Hence we do not need
* to explicitly hold another reference here.
*/
request->batch_obj = obj;
/* Seal the request and mark it as pending execution. Note that
* we may inspect this state, without holding any locks, during
* hangcheck. Hence we apply the barrier to ensure that we do not
* see a more recent value in the hws than we are tracking.
*/
request->emitted_jiffies = jiffies;
request->previous_seqno = engine->last_submitted_seqno;
smp_store_mb(engine->last_submitted_seqno, request->seqno);
list_add_tail(&request->list, &engine->request_list);
/* Record the position of the start of the request so that
* should we detect the updated seqno part-way through the
* GPU processing the request, we never over-estimate the
@ -2591,23 +2662,6 @@ void __i915_add_request(struct drm_i915_gem_request *request,
/* Not allowed to fail! */
WARN(ret, "emit|add_request failed: %d!\n", ret);
request->head = request_start;
/* Whilst this request exists, batch_obj will be on the
* active_list, and so will hold the active reference. Only when this
* request is retired will the the batch_obj be moved onto the
* inactive_list and lose its active reference. Hence we do not need
* to explicitly hold another reference here.
*/
request->batch_obj = obj;
request->emitted_jiffies = jiffies;
request->previous_seqno = engine->last_submitted_seqno;
engine->last_submitted_seqno = request->seqno;
list_add_tail(&request->list, &engine->request_list);
trace_i915_gem_request_add(request);
i915_queue_hangcheck(engine->dev);
queue_delayed_work(dev_priv->wq,
@ -2837,13 +2891,15 @@ static void i915_gem_reset_engine_cleanup(struct drm_i915_private *dev_priv,
*/
if (i915.enable_execlists) {
spin_lock_irq(&engine->execlist_lock);
/* Ensure irq handler finishes or is cancelled. */
tasklet_kill(&engine->irq_tasklet);
spin_lock_bh(&engine->execlist_lock);
/* list_splice_tail_init checks for empty lists */
list_splice_tail_init(&engine->execlist_queue,
&engine->execlist_retired_req_list);
spin_unlock_bh(&engine->execlist_lock);
spin_unlock_irq(&engine->execlist_lock);
intel_execlists_retire_requests(engine);
}
@ -2875,6 +2931,8 @@ static void i915_gem_reset_engine_cleanup(struct drm_i915_private *dev_priv,
buffer->last_retired_head = buffer->tail;
intel_ring_update_space(buffer);
}
intel_ring_init_seqno(engine, engine->last_submitted_seqno);
}
void i915_gem_reset(struct drm_device *dev)
@ -2963,9 +3021,9 @@ i915_gem_retire_requests(struct drm_device *dev)
i915_gem_retire_requests_ring(engine);
idle &= list_empty(&engine->request_list);
if (i915.enable_execlists) {
spin_lock_irq(&engine->execlist_lock);
spin_lock_bh(&engine->execlist_lock);
idle &= list_empty(&engine->execlist_queue);
spin_unlock_irq(&engine->execlist_lock);
spin_unlock_bh(&engine->execlist_lock);
intel_execlists_retire_requests(engine);
}
@ -3455,7 +3513,8 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
uint64_t flags)
{
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
u32 fence_alignment, unfenced_alignment;
u32 search_flag, alloc_flag;
u64 start, end;
@ -3502,7 +3561,7 @@ i915_gem_object_bind_to_vm(struct drm_i915_gem_object *obj,
start = flags & PIN_OFFSET_BIAS ? flags & PIN_OFFSET_MASK : 0;
end = vm->total;
if (flags & PIN_MAPPABLE)
end = min_t(u64, end, dev_priv->ggtt.mappable_end);
end = min_t(u64, end, ggtt->mappable_end);
if (flags & PIN_ZONE_4G)
end = min_t(u64, end, (1ULL << 32) - PAGE_SIZE);
@ -3709,6 +3768,9 @@ i915_gem_object_flush_cpu_write_domain(struct drm_i915_gem_object *obj)
int
i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
{
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
uint32_t old_write_domain, old_read_domains;
struct i915_vma *vma;
int ret;
@ -3763,7 +3825,7 @@ i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj, bool write)
vma = i915_gem_obj_to_ggtt(obj);
if (vma && drm_mm_node_allocated(&vma->node) && !obj->active)
list_move_tail(&vma->vm_link,
&to_i915(obj->base.dev)->ggtt.base.inactive_list);
&ggtt->base.inactive_list);
return 0;
}
@ -4232,9 +4294,6 @@ i915_gem_object_do_pin(struct drm_i915_gem_object *obj,
vma = ggtt_view ? i915_gem_obj_to_ggtt_view(obj, ggtt_view) :
i915_gem_obj_to_vma(obj, vm);
if (IS_ERR(vma))
return PTR_ERR(vma);
if (vma) {
if (WARN_ON(vma->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
return -EBUSY;
@ -4297,10 +4356,13 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj,
uint32_t alignment,
uint64_t flags)
{
if (WARN_ONCE(!view, "no view specified"))
return -EINVAL;
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
return i915_gem_object_do_pin(obj, i915_obj_to_ggtt(obj), view,
BUG_ON(!view);
return i915_gem_object_do_pin(obj, &ggtt->base, view,
alignment, flags | PIN_GLOBAL);
}
@ -4612,14 +4674,15 @@ struct i915_vma *i915_gem_obj_to_vma(struct drm_i915_gem_object *obj,
struct i915_vma *i915_gem_obj_to_ggtt_view(struct drm_i915_gem_object *obj,
const struct i915_ggtt_view *view)
{
struct i915_address_space *ggtt = i915_obj_to_ggtt(obj);
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct i915_vma *vma;
if (WARN_ONCE(!view, "no view specified"))
return ERR_PTR(-EINVAL);
BUG_ON(!view);
list_for_each_entry(vma, &obj->vma_list, obj_link)
if (vma->vm == ggtt &&
if (vma->vm == &ggtt->base &&
i915_ggtt_view_equal(&vma->ggtt_view, view))
return vma;
return NULL;
@ -4964,7 +5027,7 @@ int i915_gem_init(struct drm_device *dev)
if (ret)
goto out_unlock;
i915_gem_init_global_gtt(dev);
i915_gem_init_ggtt(dev);
ret = i915_gem_context_init(dev);
if (ret)
@ -5212,11 +5275,12 @@ u64 i915_gem_obj_offset(struct drm_i915_gem_object *o,
u64 i915_gem_obj_ggtt_offset_view(struct drm_i915_gem_object *o,
const struct i915_ggtt_view *view)
{
struct i915_address_space *ggtt = i915_obj_to_ggtt(o);
struct drm_i915_private *dev_priv = to_i915(o->base.dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct i915_vma *vma;
list_for_each_entry(vma, &o->vma_list, obj_link)
if (vma->vm == ggtt &&
if (vma->vm == &ggtt->base &&
i915_ggtt_view_equal(&vma->ggtt_view, view))
return vma->node.start;
@ -5243,11 +5307,12 @@ bool i915_gem_obj_bound(struct drm_i915_gem_object *o,
bool i915_gem_obj_ggtt_bound_view(struct drm_i915_gem_object *o,
const struct i915_ggtt_view *view)
{
struct i915_address_space *ggtt = i915_obj_to_ggtt(o);
struct drm_i915_private *dev_priv = to_i915(o->base.dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct i915_vma *vma;
list_for_each_entry(vma, &o->vma_list, obj_link)
if (vma->vm == ggtt &&
if (vma->vm == &ggtt->base &&
i915_ggtt_view_equal(&vma->ggtt_view, view) &&
drm_mm_node_allocated(&vma->node))
return true;

View File

@ -95,14 +95,12 @@ static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment,
{
struct drm_i915_gem_object *obj = dma_buf_to_obj(attachment->dmabuf);
mutex_lock(&obj->base.dev->struct_mutex);
dma_unmap_sg(attachment->dev, sg->sgl, sg->nents, dir);
sg_free_table(sg);
kfree(sg);
mutex_lock(&obj->base.dev->struct_mutex);
i915_gem_object_unpin_pages(obj);
mutex_unlock(&obj->base.dev->struct_mutex);
}
@ -110,51 +108,17 @@ static void *i915_gem_dmabuf_vmap(struct dma_buf *dma_buf)
{
struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf);
struct drm_device *dev = obj->base.dev;
struct sg_page_iter sg_iter;
struct page **pages;
int ret, i;
void *addr;
int ret;
ret = i915_mutex_lock_interruptible(dev);
if (ret)
return ERR_PTR(ret);
if (obj->dma_buf_vmapping) {
obj->vmapping_count++;
goto out_unlock;
}
ret = i915_gem_object_get_pages(obj);
if (ret)
goto err;
i915_gem_object_pin_pages(obj);
ret = -ENOMEM;
pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
if (pages == NULL)
goto err_unpin;
i = 0;
for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0)
pages[i++] = sg_page_iter_page(&sg_iter);
obj->dma_buf_vmapping = vmap(pages, i, 0, PAGE_KERNEL);
drm_free_large(pages);
if (!obj->dma_buf_vmapping)
goto err_unpin;
obj->vmapping_count = 1;
out_unlock:
addr = i915_gem_object_pin_map(obj);
mutex_unlock(&dev->struct_mutex);
return obj->dma_buf_vmapping;
err_unpin:
i915_gem_object_unpin_pages(obj);
err:
mutex_unlock(&dev->struct_mutex);
return ERR_PTR(ret);
return addr;
}
static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
@ -163,12 +127,7 @@ static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr)
struct drm_device *dev = obj->base.dev;
mutex_lock(&dev->struct_mutex);
if (--obj->vmapping_count == 0) {
vunmap(obj->dma_buf_vmapping);
obj->dma_buf_vmapping = NULL;
i915_gem_object_unpin_pages(obj);
}
i915_gem_object_unpin_map(obj);
mutex_unlock(&dev->struct_mutex);
}

View File

@ -313,7 +313,8 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj,
uint64_t target_offset)
{
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
uint64_t delta = relocation_target(reloc, target_offset);
uint64_t offset;
void __iomem *reloc_page;
@ -330,7 +331,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj,
/* Map the page containing the relocation we're going to perform. */
offset = i915_gem_obj_ggtt_offset(obj);
offset += reloc->offset;
reloc_page = io_mapping_map_atomic_wc(dev_priv->ggtt.mappable,
reloc_page = io_mapping_map_atomic_wc(ggtt->mappable,
offset & PAGE_MASK);
iowrite32(lower_32_bits(delta), reloc_page + offset_in_page(offset));
@ -340,7 +341,7 @@ relocate_entry_gtt(struct drm_i915_gem_object *obj,
if (offset_in_page(offset) == 0) {
io_mapping_unmap_atomic(reloc_page);
reloc_page =
io_mapping_map_atomic_wc(dev_priv->ggtt.mappable,
io_mapping_map_atomic_wc(ggtt->mappable,
offset);
}
@ -1431,7 +1432,8 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
struct drm_i915_gem_execbuffer2 *args,
struct drm_i915_gem_exec_object2 *exec)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct drm_i915_gem_request *req = NULL;
struct eb_vmas *eb;
struct drm_i915_gem_object *batch_obj;
@ -1504,7 +1506,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
if (ctx->ppgtt)
vm = &ctx->ppgtt->base;
else
vm = &dev_priv->ggtt.base;
vm = &ggtt->base;
memset(&params_master, 0x00, sizeof(params_master));
@ -1781,11 +1783,9 @@ i915_gem_execbuffer2(struct drm_device *dev, void *data,
return -EINVAL;
}
exec2_list = kmalloc(sizeof(*exec2_list)*args->buffer_count,
GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
if (exec2_list == NULL)
exec2_list = drm_malloc_ab(sizeof(*exec2_list),
args->buffer_count);
exec2_list = drm_malloc_gfp(args->buffer_count,
sizeof(*exec2_list),
GFP_TEMPORARY);
if (exec2_list == NULL) {
DRM_DEBUG("Failed to allocate exec list for %d buffers\n",
args->buffer_count);

View File

@ -706,8 +706,7 @@ static void gen8_ppgtt_clear_pte_range(struct i915_address_space *vm,
uint64_t length,
gen8_pte_t scratch_pte)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
gen8_pte_t *pt_vaddr;
unsigned pdpe = gen8_pdpe_index(start);
unsigned pde = gen8_pde_index(start);
@ -762,8 +761,7 @@ static void gen8_ppgtt_clear_range(struct i915_address_space *vm,
uint64_t length,
bool use_scratch)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
gen8_pte_t scratch_pte = gen8_pte_encode(px_dma(vm->scratch_page),
I915_CACHE_LLC, use_scratch);
@ -788,8 +786,7 @@ gen8_ppgtt_insert_pte_entries(struct i915_address_space *vm,
uint64_t start,
enum i915_cache_level cache_level)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
gen8_pte_t *pt_vaddr;
unsigned pdpe = gen8_pdpe_index(start);
unsigned pde = gen8_pde_index(start);
@ -829,8 +826,7 @@ static void gen8_ppgtt_insert_entries(struct i915_address_space *vm,
enum i915_cache_level cache_level,
u32 unused)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
struct sg_page_iter sg_iter;
__sg_page_iter_start(&sg_iter, pages->sgl, sg_nents(pages->sgl), 0);
@ -981,8 +977,7 @@ static void gen8_ppgtt_cleanup_4lvl(struct i915_hw_ppgtt *ppgtt)
static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
if (intel_vgpu_active(vm->dev))
gen8_ppgtt_notify_vgt(ppgtt, false);
@ -1216,8 +1211,7 @@ static int gen8_alloc_va_range_3lvl(struct i915_address_space *vm,
uint64_t start,
uint64_t length)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
unsigned long *new_page_dirs, *new_page_tables;
struct drm_device *dev = vm->dev;
struct i915_page_directory *pd;
@ -1329,8 +1323,7 @@ static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm,
uint64_t length)
{
DECLARE_BITMAP(new_pdps, GEN8_PML4ES_PER_PML4);
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
struct i915_page_directory_pointer *pdp;
uint64_t pml4e;
int ret = 0;
@ -1376,8 +1369,7 @@ static int gen8_alloc_va_range_4lvl(struct i915_address_space *vm,
static int gen8_alloc_va_range(struct i915_address_space *vm,
uint64_t start, uint64_t length)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
if (USES_FULL_48BIT_PPGTT(vm->dev))
return gen8_alloc_va_range_4lvl(vm, &ppgtt->pml4, start, length);
@ -1629,6 +1621,7 @@ static void gen6_write_page_range(struct drm_i915_private *dev_priv,
struct i915_page_directory *pd,
uint32_t start, uint32_t length)
{
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct i915_page_table *pt;
uint32_t pde, temp;
@ -1637,7 +1630,7 @@ static void gen6_write_page_range(struct drm_i915_private *dev_priv,
/* Make sure write is complete before other code can use this page
* table. Also require for WC mapped PTEs */
readl(dev_priv->ggtt.gsm);
readl(ggtt->gsm);
}
static uint32_t get_pd_offset(struct i915_hw_ppgtt *ppgtt)
@ -1794,8 +1787,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm,
uint64_t length,
bool use_scratch)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
gen6_pte_t *pt_vaddr, scratch_pte;
unsigned first_entry = start >> PAGE_SHIFT;
unsigned num_entries = length >> PAGE_SHIFT;
@ -1829,8 +1821,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm,
uint64_t start,
enum i915_cache_level cache_level, u32 flags)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
gen6_pte_t *pt_vaddr;
unsigned first_entry = start >> PAGE_SHIFT;
unsigned act_pt = first_entry / GEN6_PTES;
@ -1862,9 +1853,9 @@ static int gen6_alloc_va_range(struct i915_address_space *vm,
{
DECLARE_BITMAP(new_page_tables, I915_PDES);
struct drm_device *dev = vm->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
struct i915_page_table *pt;
uint32_t start, length, start_save, length_save;
uint32_t pde, temp;
@ -1930,7 +1921,7 @@ static int gen6_alloc_va_range(struct i915_address_space *vm,
/* Make sure write is complete before other code can use this page
* table. Also require for WC mapped PTEs */
readl(dev_priv->ggtt.gsm);
readl(ggtt->gsm);
mark_tlbs_dirty(ppgtt);
return 0;
@ -1976,8 +1967,7 @@ static void gen6_free_scratch(struct i915_address_space *vm)
static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
{
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt, base);
struct i915_hw_ppgtt *ppgtt = i915_vm_to_ppgtt(vm);
struct i915_page_table *pt;
uint32_t pde;
@ -1995,7 +1985,8 @@ static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt)
{
struct i915_address_space *vm = &ppgtt->base;
struct drm_device *dev = ppgtt->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
bool retried = false;
int ret;
@ -2003,23 +1994,23 @@ static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt)
* allocator works in address space sizes, so it's multiplied by page
* size. We allocate at the top of the GTT to avoid fragmentation.
*/
BUG_ON(!drm_mm_initialized(&dev_priv->ggtt.base.mm));
BUG_ON(!drm_mm_initialized(&ggtt->base.mm));
ret = gen6_init_scratch(vm);
if (ret)
return ret;
alloc:
ret = drm_mm_insert_node_in_range_generic(&dev_priv->ggtt.base.mm,
ret = drm_mm_insert_node_in_range_generic(&ggtt->base.mm,
&ppgtt->node, GEN6_PD_SIZE,
GEN6_PD_ALIGN, 0,
0, dev_priv->ggtt.base.total,
0, ggtt->base.total,
DRM_MM_TOPDOWN);
if (ret == -ENOSPC && !retried) {
ret = i915_gem_evict_something(dev, &dev_priv->ggtt.base,
ret = i915_gem_evict_something(dev, &ggtt->base,
GEN6_PD_SIZE, GEN6_PD_ALIGN,
I915_CACHE_NONE,
0, dev_priv->ggtt.base.total,
0, ggtt->base.total,
0);
if (ret)
goto err_out;
@ -2032,7 +2023,7 @@ static int gen6_ppgtt_allocate_page_directories(struct i915_hw_ppgtt *ppgtt)
goto err_out;
if (ppgtt->node.start < dev_priv->ggtt.mappable_end)
if (ppgtt->node.start < ggtt->mappable_end)
DRM_DEBUG("Forced to use aperture for PDEs\n");
return 0;
@ -2060,10 +2051,11 @@ static void gen6_scratch_va_range(struct i915_hw_ppgtt *ppgtt,
static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
{
struct drm_device *dev = ppgtt->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
int ret;
ppgtt->base.pte_encode = dev_priv->ggtt.base.pte_encode;
ppgtt->base.pte_encode = ggtt->base.pte_encode;
if (IS_GEN6(dev)) {
ppgtt->switch_mm = gen6_mm_switch;
} else if (IS_HASWELL(dev)) {
@ -2093,7 +2085,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt)
ppgtt->pd.base.ggtt_offset =
ppgtt->node.start / PAGE_SIZE * sizeof(gen6_pte_t);
ppgtt->pd_addr = (gen6_pte_t __iomem *)dev_priv->ggtt.gsm +
ppgtt->pd_addr = (gen6_pte_t __iomem *)ggtt->gsm +
ppgtt->pd.base.ggtt_offset / sizeof(gen6_pte_t);
gen6_scratch_va_range(ppgtt, 0, ppgtt->base.total);
@ -2261,9 +2253,10 @@ static bool needs_idle_maps(struct drm_device *dev)
static bool do_idling(struct drm_i915_private *dev_priv)
{
struct i915_ggtt *ggtt = &dev_priv->ggtt;
bool ret = dev_priv->mm.interruptible;
if (unlikely(dev_priv->ggtt.do_idle_maps)) {
if (unlikely(ggtt->do_idle_maps)) {
dev_priv->mm.interruptible = false;
if (i915_gpu_idle(dev_priv->dev)) {
DRM_ERROR("Couldn't idle GPU\n");
@ -2277,7 +2270,9 @@ static bool do_idling(struct drm_i915_private *dev_priv)
static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible)
{
if (unlikely(dev_priv->ggtt.do_idle_maps))
struct i915_ggtt *ggtt = &dev_priv->ggtt;
if (unlikely(ggtt->do_idle_maps))
dev_priv->mm.interruptible = interruptible;
}
@ -2311,7 +2306,7 @@ void i915_check_and_clear_faults(struct drm_device *dev)
static void i915_ggtt_flush(struct drm_i915_private *dev_priv)
{
if (INTEL_INFO(dev_priv->dev)->gen < 6) {
if (INTEL_INFO(dev_priv)->gen < 6) {
intel_gtt_chipset_flush();
} else {
I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
@ -2321,7 +2316,8 @@ static void i915_ggtt_flush(struct drm_i915_private *dev_priv)
void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
/* Don't bother messing with faults pre GEN6 as we have little
* documentation supporting that it's a good idea.
@ -2331,10 +2327,8 @@ void i915_gem_suspend_gtt_mappings(struct drm_device *dev)
i915_check_and_clear_faults(dev);
dev_priv->ggtt.base.clear_range(&dev_priv->ggtt.base,
dev_priv->ggtt.base.start,
dev_priv->ggtt.base.total,
true);
ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total,
true);
i915_ggtt_flush(dev_priv);
}
@ -2364,10 +2358,11 @@ static void gen8_ggtt_insert_entries(struct i915_address_space *vm,
uint64_t start,
enum i915_cache_level level, u32 unused)
{
struct drm_i915_private *dev_priv = vm->dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(vm->dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
unsigned first_entry = start >> PAGE_SHIFT;
gen8_pte_t __iomem *gtt_entries =
(gen8_pte_t __iomem *)dev_priv->ggtt.gsm + first_entry;
(gen8_pte_t __iomem *)ggtt->gsm + first_entry;
int i = 0;
struct sg_page_iter sg_iter;
dma_addr_t addr = 0; /* shut up gcc */
@ -2441,10 +2436,11 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm,
uint64_t start,
enum i915_cache_level level, u32 flags)
{
struct drm_i915_private *dev_priv = vm->dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(vm->dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
unsigned first_entry = start >> PAGE_SHIFT;
gen6_pte_t __iomem *gtt_entries =
(gen6_pte_t __iomem *)dev_priv->ggtt.gsm + first_entry;
(gen6_pte_t __iomem *)ggtt->gsm + first_entry;
int i = 0;
struct sg_page_iter sg_iter;
dma_addr_t addr = 0;
@ -2484,12 +2480,13 @@ static void gen8_ggtt_clear_range(struct i915_address_space *vm,
uint64_t length,
bool use_scratch)
{
struct drm_i915_private *dev_priv = vm->dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(vm->dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
unsigned first_entry = start >> PAGE_SHIFT;
unsigned num_entries = length >> PAGE_SHIFT;
gen8_pte_t scratch_pte, __iomem *gtt_base =
(gen8_pte_t __iomem *) dev_priv->ggtt.gsm + first_entry;
const int max_entries = gtt_total_entries(dev_priv->ggtt) - first_entry;
(gen8_pte_t __iomem *)ggtt->gsm + first_entry;
const int max_entries = ggtt_total_entries(ggtt) - first_entry;
int i;
int rpm_atomic_seq;
@ -2515,12 +2512,13 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm,
uint64_t length,
bool use_scratch)
{
struct drm_i915_private *dev_priv = vm->dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(vm->dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
unsigned first_entry = start >> PAGE_SHIFT;
unsigned num_entries = length >> PAGE_SHIFT;
gen6_pte_t scratch_pte, __iomem *gtt_base =
(gen6_pte_t __iomem *) dev_priv->ggtt.gsm + first_entry;
const int max_entries = gtt_total_entries(dev_priv->ggtt) - first_entry;
(gen6_pte_t __iomem *)ggtt->gsm + first_entry;
const int max_entries = ggtt_total_entries(ggtt) - first_entry;
int i;
int rpm_atomic_seq;
@ -2713,8 +2711,8 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
* aperture. One page should be enough to keep any prefetching inside
* of the aperture.
*/
struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_address_space *ggtt_vm = &dev_priv->ggtt.base;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct drm_mm_node *entry;
struct drm_i915_gem_object *obj;
unsigned long hole_start, hole_end;
@ -2722,13 +2720,13 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
BUG_ON(mappable_end > end);
ggtt_vm->start = start;
ggtt->base.start = start;
/* Subtract the guard page before address space initialization to
* shrink the range used by drm_mm */
ggtt_vm->total = end - start - PAGE_SIZE;
i915_address_space_init(ggtt_vm, dev_priv);
ggtt_vm->total += PAGE_SIZE;
ggtt->base.total = end - start - PAGE_SIZE;
i915_address_space_init(&ggtt->base, dev_priv);
ggtt->base.total += PAGE_SIZE;
if (intel_vgpu_active(dev)) {
ret = intel_vgt_balloon(dev);
@ -2737,36 +2735,36 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
}
if (!HAS_LLC(dev))
ggtt_vm->mm.color_adjust = i915_gtt_color_adjust;
ggtt->base.mm.color_adjust = i915_gtt_color_adjust;
/* Mark any preallocated objects as occupied */
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
struct i915_vma *vma = i915_gem_obj_to_vma(obj, ggtt_vm);
struct i915_vma *vma = i915_gem_obj_to_vma(obj, &ggtt->base);
DRM_DEBUG_KMS("reserving preallocated space: %llx + %zx\n",
i915_gem_obj_ggtt_offset(obj), obj->base.size);
WARN_ON(i915_gem_obj_ggtt_bound(obj));
ret = drm_mm_reserve_node(&ggtt_vm->mm, &vma->node);
ret = drm_mm_reserve_node(&ggtt->base.mm, &vma->node);
if (ret) {
DRM_DEBUG_KMS("Reservation failed: %i\n", ret);
return ret;
}
vma->bound |= GLOBAL_BIND;
__i915_vma_set_map_and_fenceable(vma);
list_add_tail(&vma->vm_link, &ggtt_vm->inactive_list);
list_add_tail(&vma->vm_link, &ggtt->base.inactive_list);
}
/* Clear any non-preallocated blocks */
drm_mm_for_each_hole(entry, &ggtt_vm->mm, hole_start, hole_end) {
drm_mm_for_each_hole(entry, &ggtt->base.mm, hole_start, hole_end) {
DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n",
hole_start, hole_end);
ggtt_vm->clear_range(ggtt_vm, hole_start,
ggtt->base.clear_range(&ggtt->base, hole_start,
hole_end - hole_start, true);
}
/* And finally clear the reserved guard page */
ggtt_vm->clear_range(ggtt_vm, end - PAGE_SIZE, PAGE_SIZE, true);
ggtt->base.clear_range(&ggtt->base, end - PAGE_SIZE, PAGE_SIZE, true);
if (USES_PPGTT(dev) && !USES_FULL_PPGTT(dev)) {
struct i915_hw_ppgtt *ppgtt;
@ -2797,28 +2795,33 @@ static int i915_gem_setup_global_gtt(struct drm_device *dev,
true);
dev_priv->mm.aliasing_ppgtt = ppgtt;
WARN_ON(dev_priv->ggtt.base.bind_vma != ggtt_bind_vma);
dev_priv->ggtt.base.bind_vma = aliasing_gtt_bind_vma;
WARN_ON(ggtt->base.bind_vma != ggtt_bind_vma);
ggtt->base.bind_vma = aliasing_gtt_bind_vma;
}
return 0;
}
void i915_gem_init_global_gtt(struct drm_device *dev)
/**
* i915_gem_init_ggtt - Initialize GEM for Global GTT
* @dev: DRM device
*/
void i915_gem_init_ggtt(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u64 gtt_size, mappable_size;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
gtt_size = dev_priv->ggtt.base.total;
mappable_size = dev_priv->ggtt.mappable_end;
i915_gem_setup_global_gtt(dev, 0, mappable_size, gtt_size);
i915_gem_setup_global_gtt(dev, 0, ggtt->mappable_end, ggtt->base.total);
}
void i915_global_gtt_cleanup(struct drm_device *dev)
/**
* i915_ggtt_cleanup_hw - Clean up GGTT hardware initialization
* @dev: DRM device
*/
void i915_ggtt_cleanup_hw(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_address_space *vm = &dev_priv->ggtt.base;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
if (dev_priv->mm.aliasing_ppgtt) {
struct i915_hw_ppgtt *ppgtt = dev_priv->mm.aliasing_ppgtt;
@ -2828,15 +2831,15 @@ void i915_global_gtt_cleanup(struct drm_device *dev)
i915_gem_cleanup_stolen(dev);
if (drm_mm_initialized(&vm->mm)) {
if (drm_mm_initialized(&ggtt->base.mm)) {
if (intel_vgpu_active(dev))
intel_vgt_deballoon();
drm_mm_takedown(&vm->mm);
list_del(&vm->global_link);
drm_mm_takedown(&ggtt->base.mm);
list_del(&ggtt->base.global_link);
}
vm->cleanup(vm);
ggtt->base.cleanup(&ggtt->base);
}
static unsigned int gen6_get_total_gtt_size(u16 snb_gmch_ctl)
@ -2920,13 +2923,14 @@ static size_t gen9_get_stolen_size(u16 gen9_gmch_ctl)
static int ggtt_probe_common(struct drm_device *dev,
size_t gtt_size)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct i915_page_scratch *scratch_page;
phys_addr_t gtt_phys_addr;
phys_addr_t ggtt_phys_addr;
/* For Modern GENs the PTEs and register space are split in the BAR */
gtt_phys_addr = pci_resource_start(dev->pdev, 0) +
(pci_resource_len(dev->pdev, 0) / 2);
ggtt_phys_addr = pci_resource_start(dev->pdev, 0) +
(pci_resource_len(dev->pdev, 0) / 2);
/*
* On BXT writes larger than 64 bit to the GTT pagetable range will be
@ -2936,10 +2940,10 @@ static int ggtt_probe_common(struct drm_device *dev,
* readback check when writing GTT PTE entries.
*/
if (IS_BROXTON(dev))
dev_priv->ggtt.gsm = ioremap_nocache(gtt_phys_addr, gtt_size);
ggtt->gsm = ioremap_nocache(ggtt_phys_addr, gtt_size);
else
dev_priv->ggtt.gsm = ioremap_wc(gtt_phys_addr, gtt_size);
if (!dev_priv->ggtt.gsm) {
ggtt->gsm = ioremap_wc(ggtt_phys_addr, gtt_size);
if (!ggtt->gsm) {
DRM_ERROR("Failed to map the gtt page table\n");
return -ENOMEM;
}
@ -2948,11 +2952,11 @@ static int ggtt_probe_common(struct drm_device *dev,
if (IS_ERR(scratch_page)) {
DRM_ERROR("Scratch setup failed\n");
/* iounmap will also get called at remove, but meh */
iounmap(dev_priv->ggtt.gsm);
iounmap(ggtt->gsm);
return PTR_ERR(scratch_page);
}
dev_priv->ggtt.base.scratch_page = scratch_page;
ggtt->base.scratch_page = scratch_page;
return 0;
}
@ -2973,7 +2977,7 @@ static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv)
GEN8_PPAT(6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)) |
GEN8_PPAT(7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3));
if (!USES_PPGTT(dev_priv->dev))
if (!USES_PPGTT(dev_priv))
/* Spec: "For GGTT, there is NO pat_sel[2:0] from the entry,
* so RTL will always use the value corresponding to
* pat_sel = 000".
@ -3033,7 +3037,7 @@ static void chv_setup_private_ppat(struct drm_i915_private *dev_priv)
static int gen8_gmch_probe(struct i915_ggtt *ggtt)
{
struct drm_device *dev = ggtt->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
u16 snb_gmch_ctl;
int ret;
@ -3074,7 +3078,6 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)
ggtt->base.bind_vma = ggtt_bind_vma;
ggtt->base.unbind_vma = ggtt_unbind_vma;
return ret;
}
@ -3124,7 +3127,7 @@ static void gen6_gmch_remove(struct i915_address_space *vm)
static int i915_gmch_probe(struct i915_ggtt *ggtt)
{
struct drm_device *dev = ggtt->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
int ret;
ret = intel_gmch_probe(dev_priv->bridge_dev, dev_priv->dev->pdev, NULL);
@ -3153,9 +3156,13 @@ static void i915_gmch_remove(struct i915_address_space *vm)
intel_gmch_remove();
}
int i915_gem_gtt_init(struct drm_device *dev)
/**
* i915_ggtt_init_hw - Initialize GGTT hardware
* @dev: DRM device
*/
int i915_ggtt_init_hw(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
int ret;
@ -3224,33 +3231,30 @@ int i915_gem_gtt_init(struct drm_device *dev)
return 0;
out_gtt_cleanup:
ggtt->base.cleanup(&dev_priv->ggtt.base);
ggtt->base.cleanup(&ggtt->base);
return ret;
}
void i915_gem_restore_gtt_mappings(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct drm_i915_gem_object *obj;
struct i915_address_space *vm;
struct i915_vma *vma;
bool flush;
i915_check_and_clear_faults(dev);
/* First fill our portion of the GTT with scratch pages */
dev_priv->ggtt.base.clear_range(&dev_priv->ggtt.base,
dev_priv->ggtt.base.start,
dev_priv->ggtt.base.total,
true);
ggtt->base.clear_range(&ggtt->base, ggtt->base.start, ggtt->base.total,
true);
/* Cache flush objects bound into GGTT and rebind them. */
vm = &dev_priv->ggtt.base;
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
flush = false;
list_for_each_entry(vma, &obj->vma_list, obj_link) {
if (vma->vm != vm)
if (vma->vm != &ggtt->base)
continue;
WARN_ON(i915_vma_bind(vma, obj->cache_level,
@ -3273,15 +3277,17 @@ void i915_gem_restore_gtt_mappings(struct drm_device *dev)
}
if (USES_PPGTT(dev)) {
struct i915_address_space *vm;
list_for_each_entry(vm, &dev_priv->vm_list, global_link) {
/* TODO: Perhaps it shouldn't be gen6 specific */
struct i915_hw_ppgtt *ppgtt =
container_of(vm, struct i915_hw_ppgtt,
base);
struct i915_hw_ppgtt *ppgtt;
if (i915_is_ggtt(vm))
if (vm->is_ggtt)
ppgtt = dev_priv->mm.aliasing_ppgtt;
else
ppgtt = i915_vm_to_ppgtt(vm);
gen6_write_page_range(dev_priv, &ppgtt->pd,
0, ppgtt->base.total);
@ -3340,19 +3346,13 @@ struct i915_vma *
i915_gem_obj_lookup_or_create_ggtt_vma(struct drm_i915_gem_object *obj,
const struct i915_ggtt_view *view)
{
struct i915_address_space *ggtt = i915_obj_to_ggtt(obj);
struct i915_vma *vma;
if (WARN_ON(!view))
return ERR_PTR(-EINVAL);
vma = i915_gem_obj_to_ggtt_view(obj, view);
if (IS_ERR(vma))
return vma;
struct drm_device *dev = obj->base.dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct i915_vma *vma = i915_gem_obj_to_ggtt_view(obj, view);
if (!vma)
vma = __i915_gem_vma_create(obj, ggtt, view);
vma = __i915_gem_vma_create(obj, &ggtt->base, view);
return vma;
@ -3401,8 +3401,9 @@ intel_rotate_fb_obj_pages(struct intel_rotation_info *rot_info,
int ret = -ENOMEM;
/* Allocate a temporary list of source pages for random access. */
page_addr_list = drm_malloc_ab(obj->base.size / PAGE_SIZE,
sizeof(dma_addr_t));
page_addr_list = drm_malloc_gfp(obj->base.size / PAGE_SIZE,
sizeof(dma_addr_t),
GFP_TEMPORARY);
if (!page_addr_list)
return ERR_PTR(ret);

View File

@ -42,7 +42,7 @@ typedef uint64_t gen8_pde_t;
typedef uint64_t gen8_ppgtt_pdpe_t;
typedef uint64_t gen8_ppgtt_pml4e_t;
#define gtt_total_entries(gtt) ((gtt).base.total >> PAGE_SHIFT)
#define ggtt_total_entries(ggtt) ((ggtt)->base.total >> PAGE_SHIFT)
/* gen6-hsw has bit 11-4 for physical addr bit 39-32 */
#define GEN6_GTT_ADDR_ENCODE(addr) ((addr) | (((addr) >> 28) & 0xff0))
@ -513,10 +513,9 @@ i915_page_dir_dma_addr(const struct i915_hw_ppgtt *ppgtt, const unsigned n)
px_dma(ppgtt->base.scratch_pd);
}
int i915_gem_gtt_init(struct drm_device *dev);
void i915_gem_init_global_gtt(struct drm_device *dev);
void i915_global_gtt_cleanup(struct drm_device *dev);
int i915_ggtt_init_hw(struct drm_device *dev);
void i915_gem_init_ggtt(struct drm_device *dev);
void i915_ggtt_cleanup_hw(struct drm_device *dev);
int i915_ppgtt_init(struct drm_device *dev, struct i915_hw_ppgtt *ppgtt);
int i915_ppgtt_init_hw(struct drm_device *dev);

View File

@ -28,6 +28,7 @@
#include <linux/swap.h>
#include <linux/pci.h>
#include <linux/dma-buf.h>
#include <linux/vmalloc.h>
#include <drm/drmP.h>
#include <drm/i915_drm.h>
@ -166,6 +167,10 @@ i915_gem_shrink(struct drm_i915_private *dev_priv,
obj->madv != I915_MADV_DONTNEED)
continue;
if (flags & I915_SHRINK_VMAPS &&
!is_vmalloc_addr(obj->mapping))
continue;
if ((flags & I915_SHRINK_ACTIVE) == 0 && obj->active)
continue;
@ -246,7 +251,7 @@ i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc)
count = 0;
list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_list)
if (obj->pages_pin_count == 0)
if (can_release_pages(obj))
count += obj->base.size >> PAGE_SHIFT;
list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) {
@ -288,35 +293,56 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc)
return freed;
}
struct shrinker_lock_uninterruptible {
bool was_interruptible;
bool unlock;
};
static bool
i915_gem_shrinker_lock_uninterruptible(struct drm_i915_private *dev_priv,
struct shrinker_lock_uninterruptible *slu,
int timeout_ms)
{
unsigned long timeout = msecs_to_jiffies(timeout_ms) + 1;
while (!i915_gem_shrinker_lock(dev_priv->dev, &slu->unlock)) {
schedule_timeout_killable(1);
if (fatal_signal_pending(current))
return false;
if (--timeout == 0) {
pr_err("Unable to lock GPU to purge memory.\n");
return false;
}
}
slu->was_interruptible = dev_priv->mm.interruptible;
dev_priv->mm.interruptible = false;
return true;
}
static void
i915_gem_shrinker_unlock_uninterruptible(struct drm_i915_private *dev_priv,
struct shrinker_lock_uninterruptible *slu)
{
dev_priv->mm.interruptible = slu->was_interruptible;
if (slu->unlock)
mutex_unlock(&dev_priv->dev->struct_mutex);
}
static int
i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
{
struct drm_i915_private *dev_priv =
container_of(nb, struct drm_i915_private, mm.oom_notifier);
struct drm_device *dev = dev_priv->dev;
struct shrinker_lock_uninterruptible slu;
struct drm_i915_gem_object *obj;
unsigned long timeout = msecs_to_jiffies(5000) + 1;
unsigned long pinned, bound, unbound, freed_pages;
bool was_interruptible;
bool unlock;
while (!i915_gem_shrinker_lock(dev, &unlock) && --timeout) {
schedule_timeout_killable(1);
if (fatal_signal_pending(current))
return NOTIFY_DONE;
}
if (timeout == 0) {
pr_err("Unable to purge GPU memory due lock contention.\n");
if (!i915_gem_shrinker_lock_uninterruptible(dev_priv, &slu, 5000))
return NOTIFY_DONE;
}
was_interruptible = dev_priv->mm.interruptible;
dev_priv->mm.interruptible = false;
freed_pages = i915_gem_shrink_all(dev_priv);
dev_priv->mm.interruptible = was_interruptible;
/* Because we may be allocating inside our own driver, we cannot
* assert that there are no objects with pinned pages that are not
* being pointed to by hardware.
@ -341,8 +367,7 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
bound += obj->base.size;
}
if (unlock)
mutex_unlock(&dev->struct_mutex);
i915_gem_shrinker_unlock_uninterruptible(dev_priv, &slu);
if (freed_pages || unbound || bound)
pr_info("Purging GPU memory, %lu bytes freed, %lu bytes still pinned.\n",
@ -356,6 +381,29 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr)
return NOTIFY_DONE;
}
static int
i915_gem_shrinker_vmap(struct notifier_block *nb, unsigned long event, void *ptr)
{
struct drm_i915_private *dev_priv =
container_of(nb, struct drm_i915_private, mm.vmap_notifier);
struct shrinker_lock_uninterruptible slu;
unsigned long freed_pages;
if (!i915_gem_shrinker_lock_uninterruptible(dev_priv, &slu, 5000))
return NOTIFY_DONE;
freed_pages = i915_gem_shrink(dev_priv, -1UL,
I915_SHRINK_BOUND |
I915_SHRINK_UNBOUND |
I915_SHRINK_ACTIVE |
I915_SHRINK_VMAPS);
i915_gem_shrinker_unlock_uninterruptible(dev_priv, &slu);
*(unsigned long *)ptr += freed_pages;
return NOTIFY_DONE;
}
/**
* i915_gem_shrinker_init - Initialize i915 shrinker
* @dev_priv: i915 device
@ -371,6 +419,9 @@ void i915_gem_shrinker_init(struct drm_i915_private *dev_priv)
dev_priv->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom;
WARN_ON(register_oom_notifier(&dev_priv->mm.oom_notifier));
dev_priv->mm.vmap_notifier.notifier_call = i915_gem_shrinker_vmap;
WARN_ON(register_vmap_purge_notifier(&dev_priv->mm.vmap_notifier));
}
/**
@ -381,6 +432,7 @@ void i915_gem_shrinker_init(struct drm_i915_private *dev_priv)
*/
void i915_gem_shrinker_cleanup(struct drm_i915_private *dev_priv)
{
WARN_ON(unregister_vmap_purge_notifier(&dev_priv->mm.vmap_notifier));
WARN_ON(unregister_oom_notifier(&dev_priv->mm.oom_notifier));
unregister_shrinker(&dev_priv->mm.shrinker);
}

View File

@ -72,9 +72,11 @@ int i915_gem_stolen_insert_node(struct drm_i915_private *dev_priv,
struct drm_mm_node *node, u64 size,
unsigned alignment)
{
struct i915_ggtt *ggtt = &dev_priv->ggtt;
return i915_gem_stolen_insert_node_in_range(dev_priv, node, size,
alignment, 0,
dev_priv->ggtt.stolen_usable_size);
alignment, 0,
ggtt->stolen_usable_size);
}
void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
@ -87,7 +89,8 @@ void i915_gem_stolen_remove_node(struct drm_i915_private *dev_priv,
static unsigned long i915_stolen_to_physical(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct resource *r;
u32 base;
@ -134,7 +137,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
I85X_DRB3, &tmp);
tom = tmp * MB(32);
base = tom - tseg_size - dev_priv->ggtt.stolen_size;
base = tom - tseg_size - ggtt->stolen_size;
} else if (IS_845G(dev)) {
u32 tseg_size = 0;
u32 tom;
@ -158,7 +161,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
I830_DRB3, &tmp);
tom = tmp * MB(32);
base = tom - tseg_size - dev_priv->ggtt.stolen_size;
base = tom - tseg_size - ggtt->stolen_size;
} else if (IS_I830(dev)) {
u32 tseg_size = 0;
u32 tom;
@ -178,7 +181,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
I830_DRB3, &tmp);
tom = tmp * MB(32);
base = tom - tseg_size - dev_priv->ggtt.stolen_size;
base = tom - tseg_size - ggtt->stolen_size;
}
if (base == 0)
@ -189,41 +192,41 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
struct {
u32 start, end;
} stolen[2] = {
{ .start = base, .end = base + dev_priv->ggtt.stolen_size, },
{ .start = base, .end = base + dev_priv->ggtt.stolen_size, },
{ .start = base, .end = base + ggtt->stolen_size, },
{ .start = base, .end = base + ggtt->stolen_size, },
};
u64 gtt_start, gtt_end;
u64 ggtt_start, ggtt_end;
gtt_start = I915_READ(PGTBL_CTL);
ggtt_start = I915_READ(PGTBL_CTL);
if (IS_GEN4(dev))
gtt_start = (gtt_start & PGTBL_ADDRESS_LO_MASK) |
(gtt_start & PGTBL_ADDRESS_HI_MASK) << 28;
ggtt_start = (ggtt_start & PGTBL_ADDRESS_LO_MASK) |
(ggtt_start & PGTBL_ADDRESS_HI_MASK) << 28;
else
gtt_start &= PGTBL_ADDRESS_LO_MASK;
gtt_end = gtt_start + gtt_total_entries(dev_priv->ggtt) * 4;
ggtt_start &= PGTBL_ADDRESS_LO_MASK;
ggtt_end = ggtt_start + ggtt_total_entries(ggtt) * 4;
if (gtt_start >= stolen[0].start && gtt_start < stolen[0].end)
stolen[0].end = gtt_start;
if (gtt_end > stolen[1].start && gtt_end <= stolen[1].end)
stolen[1].start = gtt_end;
if (ggtt_start >= stolen[0].start && ggtt_start < stolen[0].end)
stolen[0].end = ggtt_start;
if (ggtt_end > stolen[1].start && ggtt_end <= stolen[1].end)
stolen[1].start = ggtt_end;
/* pick the larger of the two chunks */
if (stolen[0].end - stolen[0].start >
stolen[1].end - stolen[1].start) {
base = stolen[0].start;
dev_priv->ggtt.stolen_size = stolen[0].end - stolen[0].start;
ggtt->stolen_size = stolen[0].end - stolen[0].start;
} else {
base = stolen[1].start;
dev_priv->ggtt.stolen_size = stolen[1].end - stolen[1].start;
ggtt->stolen_size = stolen[1].end - stolen[1].start;
}
if (stolen[0].start != stolen[1].start ||
stolen[0].end != stolen[1].end) {
DRM_DEBUG_KMS("GTT within stolen memory at 0x%llx-0x%llx\n",
(unsigned long long) gtt_start,
(unsigned long long) gtt_end - 1);
(unsigned long long)ggtt_start,
(unsigned long long)ggtt_end - 1);
DRM_DEBUG_KMS("Stolen memory adjusted to 0x%x-0x%x\n",
base, base + (u32) dev_priv->ggtt.stolen_size - 1);
base, base + (u32)ggtt->stolen_size - 1);
}
}
@ -233,7 +236,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
* kernel. So if the region is already marked as busy, something
* is seriously wrong.
*/
r = devm_request_mem_region(dev->dev, base, dev_priv->ggtt.stolen_size,
r = devm_request_mem_region(dev->dev, base, ggtt->stolen_size,
"Graphics Stolen Memory");
if (r == NULL) {
/*
@ -245,7 +248,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
* reservation starting from 1 instead of 0.
*/
r = devm_request_mem_region(dev->dev, base + 1,
dev_priv->ggtt.stolen_size - 1,
ggtt->stolen_size - 1,
"Graphics Stolen Memory");
/*
* GEN3 firmware likes to smash pci bridges into the stolen
@ -253,7 +256,7 @@ static unsigned long i915_stolen_to_physical(struct drm_device *dev)
*/
if (r == NULL && !IS_GEN3(dev)) {
DRM_ERROR("conflict detected with stolen region: [0x%08x - 0x%08x]\n",
base, base + (uint32_t)dev_priv->ggtt.stolen_size);
base, base + (uint32_t)ggtt->stolen_size);
base = 0;
}
}
@ -274,11 +277,12 @@ void i915_gem_cleanup_stolen(struct drm_device *dev)
static void g4x_get_stolen_reserved(struct drm_i915_private *dev_priv,
unsigned long *base, unsigned long *size)
{
struct i915_ggtt *ggtt = &dev_priv->ggtt;
uint32_t reg_val = I915_READ(IS_GM45(dev_priv) ?
CTG_STOLEN_RESERVED :
ELK_STOLEN_RESERVED);
unsigned long stolen_top = dev_priv->mm.stolen_base +
dev_priv->ggtt.stolen_size;
ggtt->stolen_size;
*base = (reg_val & G4X_STOLEN_RESERVED_ADDR2_MASK) << 16;
@ -369,10 +373,11 @@ static void gen8_get_stolen_reserved(struct drm_i915_private *dev_priv,
static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv,
unsigned long *base, unsigned long *size)
{
struct i915_ggtt *ggtt = &dev_priv->ggtt;
uint32_t reg_val = I915_READ(GEN6_STOLEN_RESERVED);
unsigned long stolen_top;
stolen_top = dev_priv->mm.stolen_base + dev_priv->ggtt.stolen_size;
stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size;
*base = reg_val & GEN6_STOLEN_RESERVED_ADDR_MASK;
@ -388,7 +393,8 @@ static void bdw_get_stolen_reserved(struct drm_i915_private *dev_priv,
int i915_gem_init_stolen(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
unsigned long reserved_total, reserved_base = 0, reserved_size;
unsigned long stolen_top;
@ -401,14 +407,14 @@ int i915_gem_init_stolen(struct drm_device *dev)
}
#endif
if (dev_priv->ggtt.stolen_size == 0)
if (ggtt->stolen_size == 0)
return 0;
dev_priv->mm.stolen_base = i915_stolen_to_physical(dev);
if (dev_priv->mm.stolen_base == 0)
return 0;
stolen_top = dev_priv->mm.stolen_base + dev_priv->ggtt.stolen_size;
stolen_top = dev_priv->mm.stolen_base + ggtt->stolen_size;
switch (INTEL_INFO(dev_priv)->gen) {
case 2:
@ -458,19 +464,18 @@ int i915_gem_init_stolen(struct drm_device *dev)
return 0;
}
dev_priv->ggtt.stolen_reserved_base = reserved_base;
dev_priv->ggtt.stolen_reserved_size = reserved_size;
ggtt->stolen_reserved_base = reserved_base;
ggtt->stolen_reserved_size = reserved_size;
/* It is possible for the reserved area to end before the end of stolen
* memory, so just consider the start. */
reserved_total = stolen_top - reserved_base;
DRM_DEBUG_KMS("Memory reserved for graphics device: %zuK, usable: %luK\n",
dev_priv->ggtt.stolen_size >> 10,
(dev_priv->ggtt.stolen_size - reserved_total) >> 10);
ggtt->stolen_size >> 10,
(ggtt->stolen_size - reserved_total) >> 10);
dev_priv->ggtt.stolen_usable_size = dev_priv->ggtt.stolen_size -
reserved_total;
ggtt->stolen_usable_size = ggtt->stolen_size - reserved_total;
/*
* Basic memrange allocator for stolen space.
@ -483,7 +488,7 @@ int i915_gem_init_stolen(struct drm_device *dev)
* i915_gem_stolen_insert_node_in_range(). We may want to fix the fbcon
* problem later.
*/
drm_mm_init(&dev_priv->mm.stolen, 0, dev_priv->ggtt.stolen_usable_size);
drm_mm_init(&dev_priv->mm.stolen, 0, ggtt->stolen_usable_size);
return 0;
}
@ -492,12 +497,13 @@ static struct sg_table *
i915_pages_create_for_stolen(struct drm_device *dev,
u32 offset, u32 size)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct sg_table *st;
struct scatterlist *sg;
DRM_DEBUG_DRIVER("offset=0x%x, size=%d\n", offset, size);
BUG_ON(offset > dev_priv->ggtt.stolen_size - size);
BUG_ON(offset > ggtt->stolen_size - size);
/* We hide that we have no struct page backing our stolen object
* by wrapping the contiguous physical allocation with a fake
@ -628,8 +634,8 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
u32 gtt_offset,
u32 size)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct i915_address_space *ggtt = &dev_priv->ggtt.base;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct drm_i915_gem_object *obj;
struct drm_mm_node *stolen;
struct i915_vma *vma;
@ -675,7 +681,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
if (gtt_offset == I915_GTT_OFFSET_NONE)
return obj;
vma = i915_gem_obj_lookup_or_create_vma(obj, ggtt);
vma = i915_gem_obj_lookup_or_create_vma(obj, &ggtt->base);
if (IS_ERR(vma)) {
ret = PTR_ERR(vma);
goto err;
@ -688,8 +694,8 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
*/
vma->node.start = gtt_offset;
vma->node.size = size;
if (drm_mm_initialized(&ggtt->mm)) {
ret = drm_mm_reserve_node(&ggtt->mm, &vma->node);
if (drm_mm_initialized(&ggtt->base.mm)) {
ret = drm_mm_reserve_node(&ggtt->base.mm, &vma->node);
if (ret) {
DRM_DEBUG_KMS("failed to allocate stolen GTT space\n");
goto err;
@ -697,7 +703,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
vma->bound |= GLOBAL_BIND;
__i915_vma_set_map_and_fenceable(vma);
list_add_tail(&vma->vm_link, &ggtt->inactive_list);
list_add_tail(&vma->vm_link, &ggtt->base.inactive_list);
}
list_add_tail(&obj->global_list, &dev_priv->mm.bound_list);

View File

@ -494,10 +494,7 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work)
ret = -ENOMEM;
pinned = 0;
pvec = kmalloc(npages*sizeof(struct page *),
GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
if (pvec == NULL)
pvec = drm_malloc_ab(npages, sizeof(struct page *));
pvec = drm_malloc_gfp(npages, sizeof(struct page *), GFP_TEMPORARY);
if (pvec != NULL) {
struct mm_struct *mm = obj->userptr.mm->mm;
@ -634,14 +631,11 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj)
pvec = NULL;
pinned = 0;
if (obj->userptr.mm->mm == current->mm) {
pvec = kmalloc(num_pages*sizeof(struct page *),
GFP_TEMPORARY | __GFP_NOWARN | __GFP_NORETRY);
pvec = drm_malloc_gfp(num_pages, sizeof(struct page *),
GFP_TEMPORARY);
if (pvec == NULL) {
pvec = drm_malloc_ab(num_pages, sizeof(struct page *));
if (pvec == NULL) {
__i915_gem_userptr_set_active(obj, false);
return -ENOMEM;
}
__i915_gem_userptr_set_active(obj, false);
return -ENOMEM;
}
pinned = __get_user_pages_fast(obj->userptr.ptr, num_pages,

View File

@ -296,6 +296,7 @@ static void i915_ring_error_state(struct drm_i915_error_state_buf *m,
}
}
err_printf(m, " seqno: 0x%08x\n", ring->seqno);
err_printf(m, " last_seqno: 0x%08x\n", ring->last_seqno);
err_printf(m, " waiting: %s\n", yesno(ring->waiting));
err_printf(m, " ring->head: 0x%08x\n", ring->cpu_ring_head);
err_printf(m, " ring->tail: 0x%08x\n", ring->cpu_ring_tail);
@ -627,6 +628,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
struct drm_i915_gem_object *src,
struct i915_address_space *vm)
{
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct drm_i915_error_object *dst;
struct i915_vma *vma = NULL;
int num_pages;
@ -653,7 +655,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
vma = i915_gem_obj_to_ggtt(src);
use_ggtt = (src->cache_level == I915_CACHE_NONE &&
vma && (vma->bound & GLOBAL_BIND) &&
reloc_offset + num_pages * PAGE_SIZE <= dev_priv->ggtt.mappable_end);
reloc_offset + num_pages * PAGE_SIZE <= ggtt->mappable_end);
/* Cannot access stolen address directly, try to use the aperture */
if (src->stolen) {
@ -663,12 +665,13 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
goto unwind;
reloc_offset = i915_gem_obj_ggtt_offset(src);
if (reloc_offset + num_pages * PAGE_SIZE > dev_priv->ggtt.mappable_end)
if (reloc_offset + num_pages * PAGE_SIZE > ggtt->mappable_end)
goto unwind;
}
/* Cannot access snooped pages through the aperture */
if (use_ggtt && src->cache_level != I915_CACHE_NONE && !HAS_LLC(dev_priv->dev))
if (use_ggtt && src->cache_level != I915_CACHE_NONE &&
!HAS_LLC(dev_priv))
goto unwind;
dst->page_count = num_pages;
@ -689,7 +692,7 @@ i915_error_object_create(struct drm_i915_private *dev_priv,
* captures what the GPU read.
*/
s = io_mapping_map_atomic_wc(dev_priv->ggtt.mappable,
s = io_mapping_map_atomic_wc(ggtt->mappable,
reloc_offset);
memcpy_fromio(d, s, PAGE_SIZE);
io_mapping_unmap_atomic(s);
@ -883,7 +886,7 @@ static void gen6_record_semaphore_state(struct drm_i915_private *dev_priv,
ering->semaphore_seqno[0] = engine->semaphore.sync_seqno[0];
ering->semaphore_seqno[1] = engine->semaphore.sync_seqno[1];
if (HAS_VEBOX(dev_priv->dev)) {
if (HAS_VEBOX(dev_priv)) {
ering->semaphore_mboxes[2] =
I915_READ(RING_SYNC_2(engine->mmio_base));
ering->semaphore_seqno[2] = engine->semaphore.sync_seqno[2];
@ -928,8 +931,9 @@ static void i915_record_ring_state(struct drm_device *dev,
ering->waiting = waitqueue_active(&engine->irq_queue);
ering->instpm = I915_READ(RING_INSTPM(engine->mmio_base));
ering->seqno = engine->get_seqno(engine, false);
ering->acthd = intel_ring_get_active_head(engine);
ering->seqno = engine->get_seqno(engine);
ering->last_seqno = engine->last_submitted_seqno;
ering->start = I915_READ_START(engine);
ering->head = I915_READ_HEAD(engine);
ering->tail = I915_READ_TAIL(engine);
@ -1015,7 +1019,8 @@ static void i915_gem_record_active_context(struct intel_engine_cs *engine,
static void i915_gem_record_rings(struct drm_device *dev,
struct drm_i915_error_state *error)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct drm_i915_gem_request *request;
int i, count;
@ -1038,7 +1043,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
vm = request->ctx && request->ctx->ppgtt ?
&request->ctx->ppgtt->base :
&dev_priv->ggtt.base;
&ggtt->base;
/* We need to copy these to an anonymous buffer
* as the simplest method to avoid being overwritten
@ -1049,7 +1054,7 @@ static void i915_gem_record_rings(struct drm_device *dev,
request->batch_obj,
vm);
if (HAS_BROKEN_CS_TLB(dev_priv->dev))
if (HAS_BROKEN_CS_TLB(dev_priv))
error->ring[i].wa_batchbuffer =
i915_error_ggtt_object_create(dev_priv,
engine->scratch.obj);

View File

@ -27,9 +27,12 @@
/* Definitions of GuC H/W registers, bits, etc */
#define GUC_STATUS _MMIO(0xc000)
#define GS_RESET_SHIFT 0
#define GS_MIA_IN_RESET (0x01 << GS_RESET_SHIFT)
#define GS_BOOTROM_SHIFT 1
#define GS_BOOTROM_MASK (0x7F << GS_BOOTROM_SHIFT)
#define GS_BOOTROM_RSA_FAILED (0x50 << GS_BOOTROM_SHIFT)
#define GS_BOOTROM_JUMP_PASSED (0x76 << GS_BOOTROM_SHIFT)
#define GS_UKERNEL_SHIFT 8
#define GS_UKERNEL_MASK (0xFF << GS_UKERNEL_SHIFT)
#define GS_UKERNEL_LAPIC_DONE (0x30 << GS_UKERNEL_SHIFT)
@ -37,7 +40,13 @@
#define GS_UKERNEL_READY (0xF0 << GS_UKERNEL_SHIFT)
#define GS_MIA_SHIFT 16
#define GS_MIA_MASK (0x07 << GS_MIA_SHIFT)
#define GS_MIA_CORE_STATE (1 << GS_MIA_SHIFT)
#define GS_MIA_CORE_STATE (0x01 << GS_MIA_SHIFT)
#define GS_MIA_HALT_REQUESTED (0x02 << GS_MIA_SHIFT)
#define GS_MIA_ISR_ENTRY (0x04 << GS_MIA_SHIFT)
#define GS_AUTH_STATUS_SHIFT 30
#define GS_AUTH_STATUS_MASK (0x03 << GS_AUTH_STATUS_SHIFT)
#define GS_AUTH_STATUS_BAD (0x01 << GS_AUTH_STATUS_SHIFT)
#define GS_AUTH_STATUS_GOOD (0x02 << GS_AUTH_STATUS_SHIFT)
#define SOFT_SCRATCH(n) _MMIO(0xc180 + (n) * 4)
#define SOFT_SCRATCH_COUNT 16

View File

@ -1000,6 +1000,7 @@ static void notify_ring(struct intel_engine_cs *engine)
return;
trace_i915_gem_request_notify(engine);
engine->user_interrupts++;
wake_up_all(&engine->irq_queue);
}
@ -1218,7 +1219,7 @@ static void ivybridge_parity_work(struct work_struct *work)
i915_reg_t reg;
slice--;
if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv->dev)))
if (WARN_ON_ONCE(slice >= NUM_L3_SLICES(dev_priv)))
break;
dev_priv->l3_parity.which_slice &= ~(1<<slice);
@ -1257,7 +1258,7 @@ static void ivybridge_parity_work(struct work_struct *work)
out:
WARN_ON(dev_priv->l3_parity.which_slice);
spin_lock_irq(&dev_priv->irq_lock);
gen5_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv->dev));
gen5_enable_gt_irq(dev_priv, GT_PARITY_ERROR(dev_priv));
spin_unlock_irq(&dev_priv->irq_lock);
mutex_unlock(&dev_priv->dev->struct_mutex);
@ -1323,7 +1324,7 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift)
if (iir & (GT_RENDER_USER_INTERRUPT << test_shift))
notify_ring(engine);
if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift))
intel_lrc_irq_handler(engine);
tasklet_schedule(&engine->irq_tasklet);
}
static irqreturn_t gen8_gt_irq_handler(struct drm_i915_private *dev_priv,
@ -1626,7 +1627,7 @@ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir)
if (INTEL_INFO(dev_priv)->gen >= 8)
return;
if (HAS_VEBOX(dev_priv->dev)) {
if (HAS_VEBOX(dev_priv)) {
if (pm_iir & PM_VEBOX_USER_INTERRUPT)
notify_ring(&dev_priv->engine[VECS]);
@ -1828,7 +1829,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
/* IRQs are synced during runtime_suspend, we don't require a wakeref */
disable_rpm_wakeref_asserts(dev_priv);
for (;;) {
do {
master_ctl = I915_READ(GEN8_MASTER_IRQ) & ~GEN8_MASTER_IRQ_CONTROL;
iir = I915_READ(VLV_IIR);
@ -1856,7 +1857,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg)
I915_WRITE(GEN8_MASTER_IRQ, DE_MASTER_IRQ_CONTROL);
POSTING_READ(GEN8_MASTER_IRQ);
}
} while (0);
enable_rpm_wakeref_asserts(dev_priv);
@ -2805,8 +2806,8 @@ static void gen8_disable_vblank(struct drm_device *dev, unsigned int pipe)
static bool
ring_idle(struct intel_engine_cs *engine, u32 seqno)
{
return (list_empty(&engine->request_list) ||
i915_seqno_passed(seqno, engine->last_submitted_seqno));
return i915_seqno_passed(seqno,
READ_ONCE(engine->last_submitted_seqno));
}
static bool
@ -2828,7 +2829,7 @@ semaphore_wait_to_signaller_ring(struct intel_engine_cs *engine, u32 ipehr,
struct drm_i915_private *dev_priv = engine->dev->dev_private;
struct intel_engine_cs *signaller;
if (INTEL_INFO(dev_priv->dev)->gen >= 8) {
if (INTEL_INFO(dev_priv)->gen >= 8) {
for_each_engine(signaller, dev_priv) {
if (engine == signaller)
continue;
@ -2941,7 +2942,7 @@ static int semaphore_passed(struct intel_engine_cs *engine)
if (signaller->hangcheck.deadlock >= I915_NUM_ENGINES)
return -1;
if (i915_seqno_passed(signaller->get_seqno(signaller, false), seqno))
if (i915_seqno_passed(signaller->get_seqno(signaller), seqno))
return 1;
/* cursory check for an unkickable deadlock */
@ -3054,6 +3055,24 @@ ring_stuck(struct intel_engine_cs *engine, u64 acthd)
return HANGCHECK_HUNG;
}
static unsigned kick_waiters(struct intel_engine_cs *engine)
{
struct drm_i915_private *i915 = to_i915(engine->dev);
unsigned user_interrupts = READ_ONCE(engine->user_interrupts);
if (engine->hangcheck.user_interrupts == user_interrupts &&
!test_and_set_bit(engine->id, &i915->gpu_error.missed_irq_rings)) {
if (!(i915->gpu_error.test_irq_rings & intel_engine_flag(engine)))
DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
engine->name);
else
DRM_INFO("Fake missed irq on %s\n",
engine->name);
wake_up_all(&engine->irq_queue);
}
return user_interrupts;
}
/*
* This is called when the chip hasn't reported back with completed
* batchbuffers in a long time. We keep track per ring seqno progress and
@ -3096,29 +3115,33 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
for_each_engine_id(engine, dev_priv, id) {
u64 acthd;
u32 seqno;
unsigned user_interrupts;
bool busy = true;
semaphore_clear_deadlocks(dev_priv);
seqno = engine->get_seqno(engine, false);
/* We don't strictly need an irq-barrier here, as we are not
* serving an interrupt request, be paranoid in case the
* barrier has side-effects (such as preventing a broken
* cacheline snoop) and so be sure that we can see the seqno
* advance. If the seqno should stick, due to a stale
* cacheline, we would erroneously declare the GPU hung.
*/
if (engine->irq_seqno_barrier)
engine->irq_seqno_barrier(engine);
acthd = intel_ring_get_active_head(engine);
seqno = engine->get_seqno(engine);
/* Reset stuck interrupts between batch advances */
user_interrupts = 0;
if (engine->hangcheck.seqno == seqno) {
if (ring_idle(engine, seqno)) {
engine->hangcheck.action = HANGCHECK_IDLE;
if (waitqueue_active(&engine->irq_queue)) {
/* Issue a wake-up to catch stuck h/w. */
if (!test_and_set_bit(engine->id, &dev_priv->gpu_error.missed_irq_rings)) {
if (!(dev_priv->gpu_error.test_irq_rings & intel_engine_flag(engine)))
DRM_ERROR("Hangcheck timer elapsed... %s idle\n",
engine->name);
else
DRM_INFO("Fake missed irq on %s\n",
engine->name);
wake_up_all(&engine->irq_queue);
}
/* Safeguard against driver failure */
user_interrupts = kick_waiters(engine);
engine->hangcheck.score += BUSY;
} else
busy = false;
@ -3169,7 +3192,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
engine->hangcheck.score = 0;
/* Clear head and subunit states on seqno movement */
engine->hangcheck.acthd = 0;
acthd = 0;
memset(engine->hangcheck.instdone, 0,
sizeof(engine->hangcheck.instdone));
@ -3177,6 +3200,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
engine->hangcheck.seqno = seqno;
engine->hangcheck.acthd = acthd;
engine->hangcheck.user_interrupts = user_interrupts;
busy_count += busy;
}
@ -3500,6 +3524,26 @@ static void bxt_hpd_irq_setup(struct drm_device *dev)
hotplug = I915_READ(PCH_PORT_HOTPLUG);
hotplug |= PORTC_HOTPLUG_ENABLE | PORTB_HOTPLUG_ENABLE |
PORTA_HOTPLUG_ENABLE;
DRM_DEBUG_KMS("Invert bit setting: hp_ctl:%x hp_port:%x\n",
hotplug, enabled_irqs);
hotplug &= ~BXT_DDI_HPD_INVERT_MASK;
/*
* For BXT invert bit has to be set based on AOB design
* for HPD detection logic, update it based on VBT fields.
*/
if ((enabled_irqs & BXT_DE_PORT_HP_DDIA) &&
intel_bios_is_port_hpd_inverted(dev_priv, PORT_A))
hotplug |= BXT_DDIA_HPD_INVERT;
if ((enabled_irqs & BXT_DE_PORT_HP_DDIB) &&
intel_bios_is_port_hpd_inverted(dev_priv, PORT_B))
hotplug |= BXT_DDIB_HPD_INVERT;
if ((enabled_irqs & BXT_DE_PORT_HP_DDIC) &&
intel_bios_is_port_hpd_inverted(dev_priv, PORT_C))
hotplug |= BXT_DDIC_HPD_INVERT;
I915_WRITE(PCH_PORT_HOTPLUG, hotplug);
}

View File

@ -165,6 +165,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define GEN6_GRDOM_MEDIA (1 << 2)
#define GEN6_GRDOM_BLT (1 << 3)
#define GEN6_GRDOM_VECS (1 << 4)
#define GEN9_GRDOM_GUC (1 << 5)
#define GEN8_GRDOM_MEDIA2 (1 << 7)
#define RING_PP_DIR_BASE(ring) _MMIO((ring)->mmio_base+0x228)
@ -627,6 +628,10 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
#define IOSF_PORT_GPIO_SC 0x48
#define IOSF_PORT_GPIO_SUS 0xa8
#define IOSF_PORT_CCU 0xa9
#define CHV_IOSF_PORT_GPIO_N 0x13
#define CHV_IOSF_PORT_GPIO_SE 0x48
#define CHV_IOSF_PORT_GPIO_E 0xa8
#define CHV_IOSF_PORT_GPIO_SW 0xb2
#define VLV_IOSF_DATA _MMIO(VLV_DISPLAY_BASE + 0x2104)
#define VLV_IOSF_ADDR _MMIO(VLV_DISPLAY_BASE + 0x2108)
@ -791,6 +796,7 @@ enum skl_disp_power_wells {
#define DSI_PLL_M1_DIV_SHIFT 0
#define DSI_PLL_M1_DIV_MASK (0x1ff << 0)
#define CCK_CZ_CLOCK_CONTROL 0x62
#define CCK_GPLL_CLOCK_CONTROL 0x67
#define CCK_DISPLAY_CLOCK_CONTROL 0x6b
#define CCK_DISPLAY_REF_CLOCK_CONTROL 0x6c
#define CCK_TRUNK_FORCE_ON (1 << 17)
@ -1324,6 +1330,7 @@ enum skl_disp_power_wells {
#define _PORT_CL1CM_DW0_A 0x162000
#define _PORT_CL1CM_DW0_BC 0x6C000
#define PHY_POWER_GOOD (1 << 16)
#define PHY_RESERVED (1 << 7)
#define BXT_PORT_CL1CM_DW0(phy) _BXT_PHY((phy), _PORT_CL1CM_DW0_BC, \
_PORT_CL1CM_DW0_A)
@ -1783,6 +1790,18 @@ enum skl_disp_power_wells {
#define GEN9_IZ_HASHING_MASK(slice) (0x3 << ((slice) * 2))
#define GEN9_IZ_HASHING(slice, val) ((val) << ((slice) * 2))
/* WaClearTdlStateAckDirtyBits */
#define GEN8_STATE_ACK _MMIO(0x20F0)
#define GEN9_STATE_ACK_SLICE1 _MMIO(0x20F8)
#define GEN9_STATE_ACK_SLICE2 _MMIO(0x2100)
#define GEN9_STATE_ACK_TDL0 (1 << 12)
#define GEN9_STATE_ACK_TDL1 (1 << 13)
#define GEN9_STATE_ACK_TDL2 (1 << 14)
#define GEN9_STATE_ACK_TDL3 (1 << 15)
#define GEN9_SUBSLICE_TDL_ACK_BITS \
(GEN9_STATE_ACK_TDL3 | GEN9_STATE_ACK_TDL2 | \
GEN9_STATE_ACK_TDL1 | GEN9_STATE_ACK_TDL0)
#define GFX_MODE _MMIO(0x2520)
#define GFX_MODE_GEN7 _MMIO(0x229c)
#define RING_MODE_GEN7(ring) _MMIO((ring)->mmio_base+0x29c)
@ -4785,6 +4804,10 @@ enum skl_disp_power_wells {
#define CBR_PND_DEADLINE_DISABLE (1<<31)
#define CBR_PWM_CLOCK_MUX_SELECT (1<<30)
#define CBR4_VLV _MMIO(VLV_DISPLAY_BASE + 0x70450)
#define CBR_DPLLBMD_PIPE_C (1<<29)
#define CBR_DPLLBMD_PIPE_B (1<<18)
/* FIFO watermark sizes etc */
#define G4X_FIFO_LINE_SIZE 64
#define I915_FIFO_LINE_SIZE 64
@ -6185,6 +6208,7 @@ enum skl_disp_power_wells {
/* digital port hotplug */
#define PCH_PORT_HOTPLUG _MMIO(0xc4030) /* SHOTPLUG_CTL */
#define PORTA_HOTPLUG_ENABLE (1 << 28) /* LPT:LP+ & BXT */
#define BXT_DDIA_HPD_INVERT (1 << 27)
#define PORTA_HOTPLUG_STATUS_MASK (3 << 24) /* SPT+ & BXT */
#define PORTA_HOTPLUG_NO_DETECT (0 << 24) /* SPT+ & BXT */
#define PORTA_HOTPLUG_SHORT_DETECT (1 << 24) /* SPT+ & BXT */
@ -6200,6 +6224,7 @@ enum skl_disp_power_wells {
#define PORTD_HOTPLUG_SHORT_DETECT (1 << 16)
#define PORTD_HOTPLUG_LONG_DETECT (2 << 16)
#define PORTC_HOTPLUG_ENABLE (1 << 12)
#define BXT_DDIC_HPD_INVERT (1 << 11)
#define PORTC_PULSE_DURATION_2ms (0 << 10) /* pre-LPT */
#define PORTC_PULSE_DURATION_4_5ms (1 << 10) /* pre-LPT */
#define PORTC_PULSE_DURATION_6ms (2 << 10) /* pre-LPT */
@ -6210,6 +6235,7 @@ enum skl_disp_power_wells {
#define PORTC_HOTPLUG_SHORT_DETECT (1 << 8)
#define PORTC_HOTPLUG_LONG_DETECT (2 << 8)
#define PORTB_HOTPLUG_ENABLE (1 << 4)
#define BXT_DDIB_HPD_INVERT (1 << 3)
#define PORTB_PULSE_DURATION_2ms (0 << 2) /* pre-LPT */
#define PORTB_PULSE_DURATION_4_5ms (1 << 2) /* pre-LPT */
#define PORTB_PULSE_DURATION_6ms (2 << 2) /* pre-LPT */
@ -6219,6 +6245,9 @@ enum skl_disp_power_wells {
#define PORTB_HOTPLUG_NO_DETECT (0 << 0)
#define PORTB_HOTPLUG_SHORT_DETECT (1 << 0)
#define PORTB_HOTPLUG_LONG_DETECT (2 << 0)
#define BXT_DDI_HPD_INVERT_MASK (BXT_DDIA_HPD_INVERT | \
BXT_DDIB_HPD_INVERT | \
BXT_DDIC_HPD_INVERT)
#define PCH_PORT_HOTPLUG2 _MMIO(0xc403C) /* SHOTPLUG_CTL2 SPT+ */
#define PORTE_HOTPLUG_ENABLE (1 << 4)

View File

@ -562,7 +562,7 @@ TRACE_EVENT(i915_gem_request_notify,
TP_fast_assign(
__entry->dev = engine->dev->primary->index;
__entry->ring = engine->id;
__entry->seqno = engine->get_seqno(engine, false);
__entry->seqno = engine->get_seqno(engine);
),
TP_printk("dev=%u, ring=%u, seqno=%u",

View File

@ -181,8 +181,8 @@ static int vgt_balloon_space(struct drm_mm *mm,
int intel_vgt_balloon(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_address_space *ggtt_vm = &dev_priv->ggtt.base;
unsigned long ggtt_vm_end = ggtt_vm->start + ggtt_vm->total;
struct i915_ggtt *ggtt = &dev_priv->ggtt;
unsigned long ggtt_end = ggtt->base.start + ggtt->base.total;
unsigned long mappable_base, mappable_size, mappable_end;
unsigned long unmappable_base, unmappable_size, unmappable_end;
@ -202,19 +202,19 @@ int intel_vgt_balloon(struct drm_device *dev)
DRM_INFO("Unmappable graphic memory: base 0x%lx size %ldKiB\n",
unmappable_base, unmappable_size / 1024);
if (mappable_base < ggtt_vm->start ||
mappable_end > dev_priv->ggtt.mappable_end ||
unmappable_base < dev_priv->ggtt.mappable_end ||
unmappable_end > ggtt_vm_end) {
if (mappable_base < ggtt->base.start ||
mappable_end > ggtt->mappable_end ||
unmappable_base < ggtt->mappable_end ||
unmappable_end > ggtt_end) {
DRM_ERROR("Invalid ballooning configuration!\n");
return -EINVAL;
}
/* Unmappable graphic memory ballooning */
if (unmappable_base > dev_priv->ggtt.mappable_end) {
ret = vgt_balloon_space(&ggtt_vm->mm,
if (unmappable_base > ggtt->mappable_end) {
ret = vgt_balloon_space(&ggtt->base.mm,
&bl_info.space[2],
dev_priv->ggtt.mappable_end,
ggtt->mappable_end,
unmappable_base);
if (ret)
@ -225,30 +225,30 @@ int intel_vgt_balloon(struct drm_device *dev)
* No need to partition out the last physical page,
* because it is reserved to the guard page.
*/
if (unmappable_end < ggtt_vm_end - PAGE_SIZE) {
ret = vgt_balloon_space(&ggtt_vm->mm,
if (unmappable_end < ggtt_end - PAGE_SIZE) {
ret = vgt_balloon_space(&ggtt->base.mm,
&bl_info.space[3],
unmappable_end,
ggtt_vm_end - PAGE_SIZE);
ggtt_end - PAGE_SIZE);
if (ret)
goto err;
}
/* Mappable graphic memory ballooning */
if (mappable_base > ggtt_vm->start) {
ret = vgt_balloon_space(&ggtt_vm->mm,
if (mappable_base > ggtt->base.start) {
ret = vgt_balloon_space(&ggtt->base.mm,
&bl_info.space[0],
ggtt_vm->start, mappable_base);
ggtt->base.start, mappable_base);
if (ret)
goto err;
}
if (mappable_end < dev_priv->ggtt.mappable_end) {
ret = vgt_balloon_space(&ggtt_vm->mm,
if (mappable_end < ggtt->mappable_end) {
ret = vgt_balloon_space(&ggtt->base.mm,
&bl_info.space[1],
mappable_end,
dev_priv->ggtt.mappable_end);
ggtt->mappable_end);
if (ret)
goto err;

View File

@ -373,7 +373,7 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder)
if (WARN_ON(port == PORT_A))
return;
if (HAS_PCH_IBX(dev_priv->dev)) {
if (HAS_PCH_IBX(dev_priv)) {
aud_config = IBX_AUD_CFG(pipe);
aud_cntrl_st2 = IBX_AUD_CNTL_ST2;
} else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {

View File

@ -1123,7 +1123,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,
}
/* Parse the I_boost config for SKL and above */
if (bdb->version >= 196 && (child->common.flags_1 & IBOOST_ENABLE)) {
if (bdb->version >= 196 && child->common.iboost) {
info->dp_boost_level = translate_iboost(child->common.iboost_level & 0xF);
DRM_DEBUG_KMS("VBT (e)DP boost level for port %c: %d\n",
port_name(port), info->dp_boost_level);
@ -1241,6 +1241,19 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
*/
memcpy(child_dev_ptr, p_child,
min_t(size_t, p_defs->child_dev_size, sizeof(*p_child)));
/*
* copied full block, now init values when they are not
* available in current version
*/
if (bdb->version < 196) {
/* Set default values for bits added from v196 */
child_dev_ptr->common.iboost = 0;
child_dev_ptr->common.hpd_invert = 0;
}
if (bdb->version < 192)
child_dev_ptr->common.lspcon = 0;
}
return;
}
@ -1585,3 +1598,47 @@ bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv,
return false;
}
/**
* intel_bios_is_port_hpd_inverted - is HPD inverted for %port
* @dev_priv: i915 device instance
* @port: port to check
*
* Return true if HPD should be inverted for %port.
*/
bool
intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv,
enum port port)
{
int i;
if (WARN_ON_ONCE(!IS_BROXTON(dev_priv)))
return false;
for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
if (!dev_priv->vbt.child_dev[i].common.hpd_invert)
continue;
switch (dev_priv->vbt.child_dev[i].common.dvo_port) {
case DVO_PORT_DPA:
case DVO_PORT_HDMIA:
if (port == PORT_A)
return true;
break;
case DVO_PORT_DPB:
case DVO_PORT_HDMIB:
if (port == PORT_B)
return true;
break;
case DVO_PORT_DPC:
case DVO_PORT_HDMIC:
if (port == PORT_C)
return true;
break;
default:
break;
}
}
return false;
}

View File

@ -92,10 +92,10 @@ static void ctm_mult_by_limited(uint64_t *result, int64_t *input)
}
/* Set up the pipe CSC unit. */
static void i9xx_load_csc_matrix(struct drm_crtc *crtc)
static void i9xx_load_csc_matrix(struct drm_crtc_state *crtc_state)
{
struct drm_crtc *crtc = crtc_state->crtc;
struct drm_device *dev = crtc->dev;
struct drm_crtc_state *crtc_state = crtc->state;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
int i, pipe = intel_crtc->pipe;
@ -203,10 +203,10 @@ static void i9xx_load_csc_matrix(struct drm_crtc *crtc)
/*
* Set up the pipe CSC unit on CherryView.
*/
static void cherryview_load_csc_matrix(struct drm_crtc *crtc)
static void cherryview_load_csc_matrix(struct drm_crtc_state *state)
{
struct drm_crtc *crtc = state->crtc;
struct drm_device *dev = crtc->dev;
struct drm_crtc_state *state = crtc->state;
struct drm_i915_private *dev_priv = dev->dev_private;
int pipe = to_intel_crtc(crtc)->pipe;
uint32_t mode;
@ -252,13 +252,13 @@ static void cherryview_load_csc_matrix(struct drm_crtc *crtc)
I915_WRITE(CGM_PIPE_MODE(pipe), mode);
}
void intel_color_set_csc(struct drm_crtc *crtc)
void intel_color_set_csc(struct drm_crtc_state *crtc_state)
{
struct drm_device *dev = crtc->dev;
struct drm_device *dev = crtc_state->crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
if (dev_priv->display.load_csc_matrix)
dev_priv->display.load_csc_matrix(crtc);
dev_priv->display.load_csc_matrix(crtc_state);
}
/* Loads the legacy palette/gamma unit for the CRTC. */
@ -303,19 +303,20 @@ static void i9xx_load_luts_internal(struct drm_crtc *crtc,
}
}
static void i9xx_load_luts(struct drm_crtc *crtc)
static void i9xx_load_luts(struct drm_crtc_state *crtc_state)
{
i9xx_load_luts_internal(crtc, crtc->state->gamma_lut);
i9xx_load_luts_internal(crtc_state->crtc, crtc_state->gamma_lut);
}
/* Loads the legacy palette/gamma unit for the CRTC on Haswell. */
static void haswell_load_luts(struct drm_crtc *crtc)
static void haswell_load_luts(struct drm_crtc_state *crtc_state)
{
struct drm_crtc *crtc = crtc_state->crtc;
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
struct intel_crtc_state *intel_crtc_state =
to_intel_crtc_state(crtc->state);
to_intel_crtc_state(crtc_state);
bool reenable_ips = false;
/*
@ -331,24 +332,24 @@ static void haswell_load_luts(struct drm_crtc *crtc)
intel_crtc_state->gamma_mode = GAMMA_MODE_MODE_8BIT;
I915_WRITE(GAMMA_MODE(intel_crtc->pipe), GAMMA_MODE_MODE_8BIT);
i9xx_load_luts(crtc);
i9xx_load_luts(crtc_state);
if (reenable_ips)
hsw_enable_ips(intel_crtc);
}
/* Loads the palette/gamma unit for the CRTC on Broadwell+. */
static void broadwell_load_luts(struct drm_crtc *crtc)
static void broadwell_load_luts(struct drm_crtc_state *state)
{
struct drm_crtc *crtc = state->crtc;
struct drm_device *dev = crtc->dev;
struct drm_crtc_state *state = crtc->state;
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_crtc_state *intel_state = to_intel_crtc_state(state);
enum pipe pipe = to_intel_crtc(crtc)->pipe;
uint32_t i, lut_size = INTEL_INFO(dev)->color.degamma_lut_size;
if (crtc_state_is_legacy(state)) {
haswell_load_luts(crtc);
haswell_load_luts(state);
return;
}
@ -421,11 +422,11 @@ static void broadwell_load_luts(struct drm_crtc *crtc)
}
/* Loads the palette/gamma unit for the CRTC on CherryView. */
static void cherryview_load_luts(struct drm_crtc *crtc)
static void cherryview_load_luts(struct drm_crtc_state *state)
{
struct drm_crtc *crtc = state->crtc;
struct drm_device *dev = crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_crtc_state *state = crtc->state;
enum pipe pipe = to_intel_crtc(crtc)->pipe;
struct drm_color_lut *lut;
uint32_t i, lut_size;
@ -481,16 +482,12 @@ static void cherryview_load_luts(struct drm_crtc *crtc)
i9xx_load_luts_internal(crtc, NULL);
}
void intel_color_load_luts(struct drm_crtc *crtc)
void intel_color_load_luts(struct drm_crtc_state *crtc_state)
{
struct drm_device *dev = crtc->dev;
struct drm_device *dev = crtc_state->crtc->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
/* The clocks have to be on to load the palette. */
if (!crtc->state->active)
return;
dev_priv->display.load_luts(crtc);
dev_priv->display.load_luts(crtc_state);
}
int intel_color_check(struct drm_crtc *crtc,

View File

@ -315,6 +315,9 @@ static void ddi_get_encoder_port(struct intel_encoder *intel_encoder,
*dig_port = enc_to_mst(encoder)->primary;
*port = (*dig_port)->port;
break;
default:
WARN(1, "Invalid DDI encoder type %d\n", intel_encoder->type);
/* fallthrough and treat as unknown */
case INTEL_OUTPUT_DISPLAYPORT:
case INTEL_OUTPUT_EDP:
case INTEL_OUTPUT_HDMI:
@ -326,9 +329,6 @@ static void ddi_get_encoder_port(struct intel_encoder *intel_encoder,
*dig_port = NULL;
*port = PORT_E;
break;
default:
WARN(1, "Invalid DDI encoder type %d\n", intel_encoder->type);
break;
}
}
@ -629,6 +629,10 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
break;
}
rx_ctl_val &= ~FDI_RX_ENABLE;
I915_WRITE(FDI_RX_CTL(PIPE_A), rx_ctl_val);
POSTING_READ(FDI_RX_CTL(PIPE_A));
temp = I915_READ(DDI_BUF_CTL(PORT_E));
temp &= ~DDI_BUF_CTL_ENABLE;
I915_WRITE(DDI_BUF_CTL(PORT_E), temp);
@ -643,10 +647,6 @@ void hsw_fdi_link_train(struct drm_crtc *crtc)
intel_wait_ddi_buf_idle(dev_priv, PORT_E);
rx_ctl_val &= ~FDI_RX_ENABLE;
I915_WRITE(FDI_RX_CTL(PIPE_A), rx_ctl_val);
POSTING_READ(FDI_RX_CTL(PIPE_A));
/* Reset FDI_RX_MISC pwrdn lanes */
temp = I915_READ(FDI_RX_MISC(PIPE_A));
temp &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
@ -1726,18 +1726,31 @@ static void broxton_phy_init(struct drm_i915_private *dev_priv,
enum dpio_phy phy)
{
enum port port;
uint32_t val;
u32 ports, val;
val = I915_READ(BXT_P_CR_GT_DISP_PWRON);
val |= GT_DISPLAY_POWER_ON(phy);
I915_WRITE(BXT_P_CR_GT_DISP_PWRON, val);
/* Considering 10ms timeout until BSpec is updated */
if (wait_for(I915_READ(BXT_PORT_CL1CM_DW0(phy)) & PHY_POWER_GOOD, 10))
/*
* The PHY registers start out inaccessible and respond to reads with
* all 1s. Eventually they become accessible as they power up, then
* the reserved bit will give the default 0. Poll on the reserved bit
* becoming 0 to find when the PHY is accessible.
* HW team confirmed that the time to reach phypowergood status is
* anywhere between 50 us and 100us.
*/
if (wait_for_us(((I915_READ(BXT_PORT_CL1CM_DW0(phy)) &
(PHY_RESERVED | PHY_POWER_GOOD)) == PHY_POWER_GOOD), 100)) {
DRM_ERROR("timeout during PHY%d power on\n", phy);
}
for (port = (phy == DPIO_PHY0 ? PORT_B : PORT_A);
port <= (phy == DPIO_PHY0 ? PORT_C : PORT_A); port++) {
if (phy == DPIO_PHY0)
ports = BIT(PORT_B) | BIT(PORT_C);
else
ports = BIT(PORT_A);
for_each_port_masked(port, ports) {
int lane;
for (lane = 0; lane < 4; lane++) {
@ -1898,12 +1911,18 @@ void intel_ddi_fdi_disable(struct drm_crtc *crtc)
struct intel_encoder *intel_encoder = intel_ddi_get_crtc_encoder(crtc);
uint32_t val;
intel_ddi_post_disable(intel_encoder);
/*
* Bspec lists this as both step 13 (before DDI_BUF_CTL disable)
* and step 18 (after clearing PORT_CLK_SEL). Based on a BUN,
* step 13 is the correct place for it. Step 18 is where it was
* originally before the BUN.
*/
val = I915_READ(FDI_RX_CTL(PIPE_A));
val &= ~FDI_RX_ENABLE;
I915_WRITE(FDI_RX_CTL(PIPE_A), val);
intel_ddi_post_disable(intel_encoder);
val = I915_READ(FDI_RX_MISC(PIPE_A));
val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK);
val |= FDI_RX_PWRDN_LANE1_VAL(2) | FDI_RX_PWRDN_LANE0_VAL(2);

File diff suppressed because it is too large Load Diff

View File

@ -129,6 +129,7 @@ static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
static void vlv_init_panel_power_sequencer(struct intel_dp *intel_dp);
static void vlv_steal_power_sequencer(struct drm_device *dev,
enum pipe pipe);
static void intel_dp_unset_edid(struct intel_dp *intel_dp);
static unsigned int intel_dp_unused_lane_mask(int lane_count)
{
@ -3787,6 +3788,27 @@ intel_dp_get_dpcd(struct intel_dp *intel_dp)
if (intel_dp->dpcd[DP_DPCD_REV] == 0)
return false; /* DPCD not present */
if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_SINK_COUNT,
&intel_dp->sink_count, 1) < 0)
return false;
/*
* Sink count can change between short pulse hpd hence
* a member variable in intel_dp will track any changes
* between short pulse interrupts.
*/
intel_dp->sink_count = DP_GET_SINK_COUNT(intel_dp->sink_count);
/*
* SINK_COUNT == 0 and DOWNSTREAM_PORT_PRESENT == 1 implies that
* a dongle is present but no display. Unless we require to know
* if a dongle is present or not, we don't need to update
* downstream port information. So, an early return here saves
* time from performing other operations which are not required.
*/
if (!intel_dp->sink_count)
return false;
/* Check if the panel supports PSR */
memset(intel_dp->psr_dpcd, 0, sizeof(intel_dp->psr_dpcd));
if (is_edp(intel_dp)) {
@ -4214,6 +4236,36 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
return -EINVAL;
}
static void
intel_dp_check_link_status(struct intel_dp *intel_dp)
{
struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
struct drm_device *dev = intel_dp_to_dev(intel_dp);
u8 link_status[DP_LINK_STATUS_SIZE];
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
if (!intel_dp_get_link_status(intel_dp, link_status)) {
DRM_ERROR("Failed to get link status\n");
return;
}
if (!intel_encoder->base.crtc)
return;
if (!to_intel_crtc(intel_encoder->base.crtc)->active)
return;
/* if link training is requested we should perform it always */
if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) ||
(!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {
DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
intel_encoder->base.name);
intel_dp_start_link_train(intel_dp);
intel_dp_stop_link_train(intel_dp);
}
}
/*
* According to DP spec
* 5.1.2:
@ -4221,16 +4273,19 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp)
* 2. Configure link according to Receiver Capabilities
* 3. Use Link Training from 2.5.3.3 and 3.5.1.3
* 4. Check link status on receipt of hot-plug interrupt
*
* intel_dp_short_pulse - handles short pulse interrupts
* when full detection is not required.
* Returns %true if short pulse is handled and full detection
* is NOT required and %false otherwise.
*/
static void
intel_dp_check_link_status(struct intel_dp *intel_dp)
static bool
intel_dp_short_pulse(struct intel_dp *intel_dp)
{
struct drm_device *dev = intel_dp_to_dev(intel_dp);
struct intel_encoder *intel_encoder = &dp_to_dig_port(intel_dp)->base;
u8 sink_irq_vector;
u8 link_status[DP_LINK_STATUS_SIZE];
WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
u8 old_sink_count = intel_dp->sink_count;
bool ret;
/*
* Clearing compliance test variables to allow capturing
@ -4240,20 +4295,17 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
intel_dp->compliance_test_type = 0;
intel_dp->compliance_test_data = 0;
if (!intel_encoder->base.crtc)
return;
/*
* Now read the DPCD to see if it's actually running
* If the current value of sink count doesn't match with
* the value that was stored earlier or dpcd read failed
* we need to do full detection
*/
ret = intel_dp_get_dpcd(intel_dp);
if (!to_intel_crtc(intel_encoder->base.crtc)->active)
return;
/* Try to read receiver status if the link appears to be up */
if (!intel_dp_get_link_status(intel_dp, link_status)) {
return;
}
/* Now read the DPCD to see if it's actually running */
if (!intel_dp_get_dpcd(intel_dp)) {
return;
if ((old_sink_count != intel_dp->sink_count) || !ret) {
/* No need to proceed if we are going to do full detect */
return false;
}
/* Try to read the source of the interrupt */
@ -4270,14 +4322,11 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
DRM_DEBUG_DRIVER("CP or sink specific irq unhandled\n");
}
/* if link training is requested we should perform it always */
if ((intel_dp->compliance_test_type == DP_TEST_LINK_TRAINING) ||
(!drm_dp_channel_eq_ok(link_status, intel_dp->lane_count))) {
DRM_DEBUG_KMS("%s: channel EQ not ok, retraining\n",
intel_encoder->base.name);
intel_dp_start_link_train(intel_dp);
intel_dp_stop_link_train(intel_dp);
}
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
intel_dp_check_link_status(intel_dp);
drm_modeset_unlock(&dev->mode_config.connection_mutex);
return true;
}
/* XXX this is probably wrong for multiple downstream ports */
@ -4297,14 +4346,9 @@ intel_dp_detect_dpcd(struct intel_dp *intel_dp)
/* If we're HPD-aware, SINK_COUNT changes dynamically */
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
intel_dp->downstream_ports[0] & DP_DS_PORT_HPD) {
uint8_t reg;
if (intel_dp_dpcd_read_wake(&intel_dp->aux, DP_SINK_COUNT,
&reg, 1) < 0)
return connector_status_unknown;
return DP_GET_SINK_COUNT(reg) ? connector_status_connected
: connector_status_disconnected;
return intel_dp->sink_count ?
connector_status_connected : connector_status_disconnected;
}
/* If no HPD, poke DDC gently */
@ -4513,6 +4557,7 @@ intel_dp_set_edid(struct intel_dp *intel_dp)
struct intel_connector *intel_connector = intel_dp->attached_connector;
struct edid *edid;
intel_dp_unset_edid(intel_dp);
edid = intel_dp_get_edid(intel_dp);
intel_connector->detect_edid = edid;
@ -4533,9 +4578,10 @@ intel_dp_unset_edid(struct intel_dp *intel_dp)
intel_dp->has_audio = false;
}
static enum drm_connector_status
intel_dp_detect(struct drm_connector *connector, bool force)
static void
intel_dp_long_pulse(struct intel_connector *intel_connector)
{
struct drm_connector *connector = &intel_connector->base;
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct intel_encoder *intel_encoder = &intel_dig_port->base;
@ -4545,17 +4591,6 @@ intel_dp_detect(struct drm_connector *connector, bool force)
bool ret;
u8 sink_irq_vector;
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
intel_dp_unset_edid(intel_dp);
if (intel_dp->is_mst) {
/* MST devices are disconnected from a monitor POV */
if (intel_encoder->type != INTEL_OUTPUT_EDP)
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
return connector_status_disconnected;
}
power_domain = intel_display_port_aux_power_domain(intel_encoder);
intel_display_power_get(to_i915(dev), power_domain);
@ -4576,16 +4611,30 @@ intel_dp_detect(struct drm_connector *connector, bool force)
goto out;
}
if (intel_encoder->type != INTEL_OUTPUT_EDP)
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
intel_dp_probe_oui(intel_dp);
ret = intel_dp_probe_mst(intel_dp);
if (ret) {
/* if we are in MST mode then this connector
won't appear connected or have anything with EDID on it */
if (intel_encoder->type != INTEL_OUTPUT_EDP)
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
/*
* If we are in MST mode then this connector
* won't appear connected or have anything
* with EDID on it
*/
status = connector_status_disconnected;
goto out;
} else if (connector->status == connector_status_connected) {
/*
* If display was connected already and is still connected
* check links status, there has been known issues of
* link loss triggerring long pulse!!!!
*/
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
intel_dp_check_link_status(intel_dp);
drm_modeset_unlock(&dev->mode_config.connection_mutex);
goto out;
}
/*
@ -4598,9 +4647,8 @@ intel_dp_detect(struct drm_connector *connector, bool force)
intel_dp_set_edid(intel_dp);
if (intel_encoder->type != INTEL_OUTPUT_EDP)
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
status = connector_status_connected;
intel_dp->detect_done = true;
/* Try to read the source of the interrupt */
if (intel_dp->dpcd[DP_DPCD_REV] >= 0x11 &&
@ -4617,8 +4665,54 @@ intel_dp_detect(struct drm_connector *connector, bool force)
}
out:
if (status != connector_status_connected) {
intel_dp_unset_edid(intel_dp);
/*
* If we were in MST mode, and device is not there,
* get out of MST mode
*/
if (intel_dp->is_mst) {
DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
intel_dp->is_mst = false;
drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
intel_dp->is_mst);
}
}
intel_display_power_put(to_i915(dev), power_domain);
return status;
return;
}
static enum drm_connector_status
intel_dp_detect(struct drm_connector *connector, bool force)
{
struct intel_dp *intel_dp = intel_attached_dp(connector);
struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
struct intel_encoder *intel_encoder = &intel_dig_port->base;
struct intel_connector *intel_connector = to_intel_connector(connector);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id, connector->name);
if (intel_dp->is_mst) {
/* MST devices are disconnected from a monitor POV */
intel_dp_unset_edid(intel_dp);
if (intel_encoder->type != INTEL_OUTPUT_EDP)
intel_encoder->type = INTEL_OUTPUT_DISPLAYPORT;
return connector_status_disconnected;
}
/* If full detect is not performed yet, do a full detect */
if (!intel_dp->detect_done)
intel_dp_long_pulse(intel_dp->attached_connector);
intel_dp->detect_done = false;
if (intel_connector->detect_edid)
return connector_status_connected;
else
return connector_status_disconnected;
}
static void
@ -4945,44 +5039,37 @@ intel_dp_hpd_pulse(struct intel_digital_port *intel_dig_port, bool long_hpd)
/* indicate that we need to restart link training */
intel_dp->train_set_valid = false;
if (!intel_digital_port_connected(dev_priv, intel_dig_port))
goto mst_fail;
intel_dp_long_pulse(intel_dp->attached_connector);
if (intel_dp->is_mst)
ret = IRQ_HANDLED;
goto put_power;
if (!intel_dp_get_dpcd(intel_dp)) {
goto mst_fail;
}
intel_dp_probe_oui(intel_dp);
if (!intel_dp_probe_mst(intel_dp)) {
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
intel_dp_check_link_status(intel_dp);
drm_modeset_unlock(&dev->mode_config.connection_mutex);
goto mst_fail;
}
} else {
if (intel_dp->is_mst) {
if (intel_dp_check_mst_status(intel_dp) == -EINVAL)
goto mst_fail;
if (intel_dp_check_mst_status(intel_dp) == -EINVAL) {
/*
* If we were in MST mode, and device is not
* there, get out of MST mode
*/
DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n",
intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
intel_dp->is_mst = false;
drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr,
intel_dp->is_mst);
goto put_power;
}
}
if (!intel_dp->is_mst) {
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
intel_dp_check_link_status(intel_dp);
drm_modeset_unlock(&dev->mode_config.connection_mutex);
if (!intel_dp_short_pulse(intel_dp)) {
intel_dp_long_pulse(intel_dp->attached_connector);
goto put_power;
}
}
}
ret = IRQ_HANDLED;
goto put_power;
mst_fail:
/* if we were in MST mode, and device is not there get out of MST mode */
if (intel_dp->is_mst) {
DRM_DEBUG_KMS("MST device may have disappeared %d vs %d\n", intel_dp->is_mst, intel_dp->mst_mgr.mst_state);
intel_dp->is_mst = false;
drm_dp_mst_topology_mgr_set_mst(&intel_dp->mst_mgr, intel_dp->is_mst);
}
put_power:
intel_display_power_put(dev_priv, power_domain);

View File

@ -89,14 +89,16 @@ void intel_prepare_shared_dpll(struct intel_crtc *crtc)
if (WARN_ON(pll == NULL))
return;
mutex_lock(&dev_priv->dpll_lock);
WARN_ON(!pll->config.crtc_mask);
if (pll->active_mask == 0) {
if (!pll->active_mask) {
DRM_DEBUG_DRIVER("setting up %s\n", pll->name);
WARN_ON(pll->on);
assert_shared_dpll_disabled(dev_priv, pll);
pll->funcs.mode_set(dev_priv, pll);
}
mutex_unlock(&dev_priv->dpll_lock);
}
/**
@ -113,14 +115,17 @@ void intel_enable_shared_dpll(struct intel_crtc *crtc)
struct drm_i915_private *dev_priv = dev->dev_private;
struct intel_shared_dpll *pll = crtc->config->shared_dpll;
unsigned crtc_mask = 1 << drm_crtc_index(&crtc->base);
unsigned old_mask = pll->active_mask;
unsigned old_mask;
if (WARN_ON(pll == NULL))
return;
mutex_lock(&dev_priv->dpll_lock);
old_mask = pll->active_mask;
if (WARN_ON(!(pll->config.crtc_mask & crtc_mask)) ||
WARN_ON(pll->active_mask & crtc_mask))
return;
goto out;
pll->active_mask |= crtc_mask;
@ -131,13 +136,16 @@ void intel_enable_shared_dpll(struct intel_crtc *crtc)
if (old_mask) {
WARN_ON(!pll->on);
assert_shared_dpll_enabled(dev_priv, pll);
return;
goto out;
}
WARN_ON(pll->on);
DRM_DEBUG_KMS("enabling %s\n", pll->name);
pll->funcs.enable(dev_priv, pll);
pll->on = true;
out:
mutex_unlock(&dev_priv->dpll_lock);
}
void intel_disable_shared_dpll(struct intel_crtc *crtc)
@ -154,8 +162,9 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc)
if (pll == NULL)
return;
mutex_lock(&dev_priv->dpll_lock);
if (WARN_ON(!(pll->active_mask & crtc_mask)))
return;
goto out;
DRM_DEBUG_KMS("disable %s (active %x, on? %d) for crtc %d\n",
pll->name, pll->active_mask, pll->on,
@ -166,11 +175,14 @@ void intel_disable_shared_dpll(struct intel_crtc *crtc)
pll->active_mask &= ~crtc_mask;
if (pll->active_mask)
return;
goto out;
DRM_DEBUG_KMS("disabling %s\n", pll->name);
pll->funcs.disable(dev_priv, pll);
pll->on = false;
out:
mutex_unlock(&dev_priv->dpll_lock);
}
static struct intel_shared_dpll *
@ -286,7 +298,7 @@ static void ibx_assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
u32 val;
bool enabled;
I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv->dev) || HAS_PCH_CPT(dev_priv->dev)));
I915_STATE_WARN_ON(!(HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)));
val = I915_READ(PCH_DREF_CONTROL);
enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
@ -1284,7 +1296,15 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv,
enum port port = (enum port)pll->id; /* 1:1 port->PLL mapping */
temp = I915_READ(BXT_PORT_PLL_ENABLE(port));
temp &= ~PORT_PLL_REF_SEL;
/*
* Definition of each bit polarity has been changed
* after A1 stepping
*/
if (IS_BXT_REVID(dev_priv, 0, BXT_REVID_A1))
temp &= ~PORT_PLL_REF_SEL;
else
temp |= PORT_PLL_REF_SEL;
/* Non-SSC reference */
I915_WRITE(BXT_PORT_PLL_ENABLE(port), temp);
@ -1750,6 +1770,7 @@ void intel_shared_dpll_init(struct drm_device *dev)
dev_priv->dpll_mgr = dpll_mgr;
dev_priv->num_shared_dpll = i;
mutex_init(&dev_priv->dpll_lock);
BUG_ON(dev_priv->num_shared_dpll > I915_NUM_PLLS);

View File

@ -796,7 +796,9 @@ struct intel_dp {
uint32_t DP;
int link_rate;
uint8_t lane_count;
uint8_t sink_count;
bool has_audio;
bool detect_done;
enum hdmi_force_audio force_audio;
bool limited_color_range;
bool color_range_auto;
@ -1102,6 +1104,8 @@ 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 */
int vlv_get_cck_clock(struct drm_i915_private *dev_priv,
const char *name, u32 reg, int ref_freq);
extern const struct drm_plane_funcs intel_plane_funcs;
void intel_init_display_hooks(struct drm_i915_private *dev_priv);
unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info);
@ -1669,7 +1673,7 @@ extern const struct drm_plane_helper_funcs intel_plane_helper_funcs;
/* intel_color.c */
void intel_color_init(struct drm_crtc *crtc);
int intel_color_check(struct drm_crtc *crtc, struct drm_crtc_state *state);
void intel_color_set_csc(struct drm_crtc *crtc);
void intel_color_load_luts(struct drm_crtc *crtc);
void intel_color_set_csc(struct drm_crtc_state *crtc_state);
void intel_color_load_luts(struct drm_crtc_state *crtc_state);
#endif /* __INTEL_DRV_H__ */

View File

@ -46,6 +46,24 @@ static const struct {
},
};
enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt)
{
/* It just so happens the VBT matches register contents. */
switch (fmt) {
case VID_MODE_FORMAT_RGB888:
return MIPI_DSI_FMT_RGB888;
case VID_MODE_FORMAT_RGB666:
return MIPI_DSI_FMT_RGB666;
case VID_MODE_FORMAT_RGB666_PACKED:
return MIPI_DSI_FMT_RGB666_PACKED;
case VID_MODE_FORMAT_RGB565:
return MIPI_DSI_FMT_RGB565;
default:
MISSING_CASE(fmt);
return MIPI_DSI_FMT_RGB666;
}
}
static void wait_for_dsi_fifo_empty(struct intel_dsi *intel_dsi, enum port port)
{
struct drm_encoder *encoder = &intel_dsi->base.base;
@ -740,14 +758,74 @@ static bool intel_dsi_get_hw_state(struct intel_encoder *encoder,
return active;
}
static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_device *dev = encoder->base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_display_mode *adjusted_mode =
&pipe_config->base.adjusted_mode;
struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base);
unsigned int bpp, fmt;
enum port port;
u16 vfp, vsync, vbp;
/*
* Atleast one port is active as encoder->get_config called only if
* encoder->get_hw_state() returns true.
*/
for_each_dsi_port(port, intel_dsi->ports) {
if (I915_READ(BXT_MIPI_PORT_CTRL(port)) & DPI_ENABLE)
break;
}
fmt = I915_READ(MIPI_DSI_FUNC_PRG(port)) & VID_MODE_FORMAT_MASK;
pipe_config->pipe_bpp =
mipi_dsi_pixel_format_to_bpp(
pixel_format_from_register_bits(fmt));
bpp = pipe_config->pipe_bpp;
/* In terms of pixels */
adjusted_mode->crtc_hdisplay =
I915_READ(BXT_MIPI_TRANS_HACTIVE(port));
adjusted_mode->crtc_vdisplay =
I915_READ(BXT_MIPI_TRANS_VACTIVE(port));
adjusted_mode->crtc_vtotal =
I915_READ(BXT_MIPI_TRANS_VTOTAL(port));
/*
* TODO: Retrieve hfp, hsync and hbp. Adjust them for dual link and
* calculate hsync_start, hsync_end, htotal and hblank_end
*/
/* vertical values are in terms of lines */
vfp = I915_READ(MIPI_VFP_COUNT(port));
vsync = I915_READ(MIPI_VSYNC_PADDING_COUNT(port));
vbp = I915_READ(MIPI_VBP_COUNT(port));
adjusted_mode->crtc_hblank_start = adjusted_mode->crtc_hdisplay;
adjusted_mode->crtc_vsync_start =
vfp + adjusted_mode->crtc_vdisplay;
adjusted_mode->crtc_vsync_end =
vsync + adjusted_mode->crtc_vsync_start;
adjusted_mode->crtc_vblank_start = adjusted_mode->crtc_vdisplay;
adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vtotal;
}
static void intel_dsi_get_config(struct intel_encoder *encoder,
struct intel_crtc_state *pipe_config)
{
struct drm_device *dev = encoder->base.dev;
u32 pclk;
DRM_DEBUG_KMS("\n");
pipe_config->has_dsi_encoder = true;
if (IS_BROXTON(dev))
bxt_dsi_get_pipe_config(encoder, pipe_config);
/*
* DPLL_MD is not used in case of DSI, reading will get some default value
* set dpll_md = 0

View File

@ -134,5 +134,6 @@ extern void intel_dsi_reset_clocks(struct intel_encoder *encoder,
enum port port);
struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id);
enum mipi_dsi_pixel_format pixel_format_from_register_bits(u32 fmt);
#endif /* _INTEL_DSI_H */

View File

@ -58,50 +58,41 @@ static inline struct vbt_panel *to_vbt_panel(struct drm_panel *panel)
#define NS_KHZ_RATIO 1000000
#define GPI0_NC_0_HV_DDI0_HPD 0x4130
#define GPIO_NC_0_HV_DDI0_PAD 0x4138
#define GPIO_NC_1_HV_DDI0_DDC_SDA 0x4120
#define GPIO_NC_1_HV_DDI0_DDC_SDA_PAD 0x4128
#define GPIO_NC_2_HV_DDI0_DDC_SCL 0x4110
#define GPIO_NC_2_HV_DDI0_DDC_SCL_PAD 0x4118
#define GPIO_NC_3_PANEL0_VDDEN 0x4140
#define GPIO_NC_3_PANEL0_VDDEN_PAD 0x4148
#define GPIO_NC_4_PANEL0_BLKEN 0x4150
#define GPIO_NC_4_PANEL0_BLKEN_PAD 0x4158
#define GPIO_NC_5_PANEL0_BLKCTL 0x4160
#define GPIO_NC_5_PANEL0_BLKCTL_PAD 0x4168
#define GPIO_NC_6_PCONF0 0x4180
#define GPIO_NC_6_PAD 0x4188
#define GPIO_NC_7_PCONF0 0x4190
#define GPIO_NC_7_PAD 0x4198
#define GPIO_NC_8_PCONF0 0x4170
#define GPIO_NC_8_PAD 0x4178
#define GPIO_NC_9_PCONF0 0x4100
#define GPIO_NC_9_PAD 0x4108
#define GPIO_NC_10_PCONF0 0x40E0
#define GPIO_NC_10_PAD 0x40E8
#define GPIO_NC_11_PCONF0 0x40F0
#define GPIO_NC_11_PAD 0x40F8
/* base offsets for gpio pads */
#define VLV_GPIO_NC_0_HV_DDI0_HPD 0x4130
#define VLV_GPIO_NC_1_HV_DDI0_DDC_SDA 0x4120
#define VLV_GPIO_NC_2_HV_DDI0_DDC_SCL 0x4110
#define VLV_GPIO_NC_3_PANEL0_VDDEN 0x4140
#define VLV_GPIO_NC_4_PANEL0_BKLTEN 0x4150
#define VLV_GPIO_NC_5_PANEL0_BKLTCTL 0x4160
#define VLV_GPIO_NC_6_HV_DDI1_HPD 0x4180
#define VLV_GPIO_NC_7_HV_DDI1_DDC_SDA 0x4190
#define VLV_GPIO_NC_8_HV_DDI1_DDC_SCL 0x4170
#define VLV_GPIO_NC_9_PANEL1_VDDEN 0x4100
#define VLV_GPIO_NC_10_PANEL1_BKLTEN 0x40E0
#define VLV_GPIO_NC_11_PANEL1_BKLTCTL 0x40F0
struct gpio_table {
u16 function_reg;
u16 pad_reg;
u8 init;
#define VLV_GPIO_PCONF0(base_offset) (base_offset)
#define VLV_GPIO_PAD_VAL(base_offset) ((base_offset) + 8)
struct gpio_map {
u16 base_offset;
bool init;
};
static struct gpio_table gtable[] = {
{ GPI0_NC_0_HV_DDI0_HPD, GPIO_NC_0_HV_DDI0_PAD, 0 },
{ GPIO_NC_1_HV_DDI0_DDC_SDA, GPIO_NC_1_HV_DDI0_DDC_SDA_PAD, 0 },
{ GPIO_NC_2_HV_DDI0_DDC_SCL, GPIO_NC_2_HV_DDI0_DDC_SCL_PAD, 0 },
{ GPIO_NC_3_PANEL0_VDDEN, GPIO_NC_3_PANEL0_VDDEN_PAD, 0 },
{ GPIO_NC_4_PANEL0_BLKEN, GPIO_NC_4_PANEL0_BLKEN_PAD, 0 },
{ GPIO_NC_5_PANEL0_BLKCTL, GPIO_NC_5_PANEL0_BLKCTL_PAD, 0 },
{ GPIO_NC_6_PCONF0, GPIO_NC_6_PAD, 0 },
{ GPIO_NC_7_PCONF0, GPIO_NC_7_PAD, 0 },
{ GPIO_NC_8_PCONF0, GPIO_NC_8_PAD, 0 },
{ GPIO_NC_9_PCONF0, GPIO_NC_9_PAD, 0 },
{ GPIO_NC_10_PCONF0, GPIO_NC_10_PAD, 0},
{ GPIO_NC_11_PCONF0, GPIO_NC_11_PAD, 0}
static struct gpio_map vlv_gpio_table[] = {
{ VLV_GPIO_NC_0_HV_DDI0_HPD },
{ VLV_GPIO_NC_1_HV_DDI0_DDC_SDA },
{ VLV_GPIO_NC_2_HV_DDI0_DDC_SCL },
{ VLV_GPIO_NC_3_PANEL0_VDDEN },
{ VLV_GPIO_NC_4_PANEL0_BKLTEN },
{ VLV_GPIO_NC_5_PANEL0_BKLTCTL },
{ VLV_GPIO_NC_6_HV_DDI1_HPD },
{ VLV_GPIO_NC_7_HV_DDI1_DDC_SDA },
{ VLV_GPIO_NC_8_HV_DDI1_DDC_SCL },
{ VLV_GPIO_NC_9_PANEL1_VDDEN },
{ VLV_GPIO_NC_10_PANEL1_BKLTEN },
{ VLV_GPIO_NC_11_PANEL1_BKLTCTL },
};
static inline enum port intel_dsi_seq_port_to_port(u8 port)
@ -196,56 +187,76 @@ static const u8 *mipi_exec_delay(struct intel_dsi *intel_dsi, const u8 *data)
return data;
}
static void vlv_exec_gpio(struct drm_i915_private *dev_priv,
u8 gpio_source, u8 gpio_index, bool value)
{
struct gpio_map *map;
u16 pconf0, padval;
u32 tmp;
u8 port;
if (gpio_index >= ARRAY_SIZE(vlv_gpio_table)) {
DRM_DEBUG_KMS("unknown gpio index %u\n", gpio_index);
return;
}
map = &vlv_gpio_table[gpio_index];
if (dev_priv->vbt.dsi.seq_version >= 3) {
DRM_DEBUG_KMS("GPIO element v3 not supported\n");
return;
} else {
if (gpio_source == 0) {
port = IOSF_PORT_GPIO_NC;
} else if (gpio_source == 1) {
port = IOSF_PORT_GPIO_SC;
} else {
DRM_DEBUG_KMS("unknown gpio source %u\n", gpio_source);
return;
}
}
pconf0 = VLV_GPIO_PCONF0(map->base_offset);
padval = VLV_GPIO_PAD_VAL(map->base_offset);
mutex_lock(&dev_priv->sb_lock);
if (!map->init) {
/* FIXME: remove constant below */
vlv_iosf_sb_write(dev_priv, port, pconf0, 0x2000CC00);
map->init = true;
}
tmp = 0x4 | value;
vlv_iosf_sb_write(dev_priv, port, padval, tmp);
mutex_unlock(&dev_priv->sb_lock);
}
static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
{
u8 gpio, action;
u16 function, pad;
u32 val;
struct drm_device *dev = intel_dsi->base.base.dev;
struct drm_i915_private *dev_priv = dev->dev_private;
u8 gpio_source, gpio_index;
bool value;
if (dev_priv->vbt.dsi.seq_version >= 3)
data++;
gpio = *data++;
gpio_index = *data++;
/* gpio source in sequence v2 only */
if (dev_priv->vbt.dsi.seq_version == 2)
gpio_source = (*data >> 1) & 3;
else
gpio_source = 0;
/* pull up/down */
action = *data++ & 1;
value = *data++ & 1;
if (gpio >= ARRAY_SIZE(gtable)) {
DRM_DEBUG_KMS("unknown gpio %u\n", gpio);
goto out;
}
if (!IS_VALLEYVIEW(dev_priv)) {
if (IS_VALLEYVIEW(dev_priv))
vlv_exec_gpio(dev_priv, gpio_source, gpio_index, value);
else
DRM_DEBUG_KMS("GPIO element not supported on this platform\n");
goto out;
}
if (dev_priv->vbt.dsi.seq_version >= 3) {
DRM_DEBUG_KMS("GPIO element v3 not supported\n");
goto out;
}
function = gtable[gpio].function_reg;
pad = gtable[gpio].pad_reg;
mutex_lock(&dev_priv->sb_lock);
if (!gtable[gpio].init) {
/* program the function */
/* FIXME: remove constant below */
vlv_iosf_sb_write(dev_priv, IOSF_PORT_GPIO_NC, function,
0x2000CC00);
gtable[gpio].init = 1;
}
val = 0x4 | action;
/* pull up/down */
vlv_iosf_sb_write(dev_priv, IOSF_PORT_GPIO_NC, pad, val);
mutex_unlock(&dev_priv->sb_lock);
out:
return data;
}
@ -412,25 +423,6 @@ static const struct drm_panel_funcs vbt_panel_funcs = {
.get_modes = vbt_panel_get_modes,
};
/* XXX: This should be done when parsing the VBT in intel_bios.c */
static enum mipi_dsi_pixel_format pixel_format_from_vbt(u32 fmt)
{
/* It just so happens the VBT matches register contents. */
switch (fmt) {
case VID_MODE_FORMAT_RGB888:
return MIPI_DSI_FMT_RGB888;
case VID_MODE_FORMAT_RGB666:
return MIPI_DSI_FMT_RGB666;
case VID_MODE_FORMAT_RGB666_PACKED:
return MIPI_DSI_FMT_RGB666_PACKED;
case VID_MODE_FORMAT_RGB565:
return MIPI_DSI_FMT_RGB565;
default:
MISSING_CASE(fmt);
return MIPI_DSI_FMT_RGB666;
}
}
struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id)
{
struct drm_device *dev = intel_dsi->base.base.dev;
@ -455,7 +447,9 @@ struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id)
intel_dsi->eotp_pkt = mipi_config->eot_pkt_disabled ? 0 : 1;
intel_dsi->clock_stop = mipi_config->enable_clk_stop ? 1 : 0;
intel_dsi->lane_count = mipi_config->lane_cnt + 1;
intel_dsi->pixel_format = pixel_format_from_vbt(mipi_config->videomode_color_format << 7);
intel_dsi->pixel_format =
pixel_format_from_register_bits(
mipi_config->videomode_color_format << 7);
bpp = mipi_dsi_pixel_format_to_bpp(intel_dsi->pixel_format);
intel_dsi->dual_link = mipi_config->dual_link;

View File

@ -506,6 +506,7 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv,
int size,
int fb_cpp)
{
struct i915_ggtt *ggtt = &dev_priv->ggtt;
int compression_threshold = 1;
int ret;
u64 end;
@ -516,9 +517,9 @@ static int find_compression_threshold(struct drm_i915_private *dev_priv,
* underruns, even if that range is not reserved by the BIOS. */
if (IS_BROADWELL(dev_priv) ||
IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv))
end = dev_priv->ggtt.stolen_size - 8 * 1024 * 1024;
end = ggtt->stolen_size - 8 * 1024 * 1024;
else
end = dev_priv->ggtt.stolen_usable_size;
end = ggtt->stolen_usable_size;
/* HACK: This code depends on what we will do in *_enable_fbc. If that
* code changes, this code needs to change as well.

View File

@ -122,6 +122,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
struct drm_framebuffer *fb;
struct drm_device *dev = helper->dev;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct drm_mode_fb_cmd2 mode_cmd = {};
struct drm_i915_gem_object *obj = NULL;
int size, ret;
@ -146,7 +147,7 @@ static int intelfb_alloc(struct drm_fb_helper *helper,
/* If the FB is too big, just don't use it since fbdev is not very
* important and we should probably use that space with FBC or other
* features. */
if (size * 2 < dev_priv->ggtt.stolen_usable_size)
if (size * 2 < ggtt->stolen_usable_size)
obj = i915_gem_object_create_stolen(dev, size);
if (obj == NULL)
obj = i915_gem_alloc_object(dev, size);
@ -181,7 +182,8 @@ static int intelfb_create(struct drm_fb_helper *helper,
container_of(helper, struct intel_fbdev, helper);
struct intel_framebuffer *intel_fb = ifbdev->fb;
struct drm_device *dev = helper->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct fb_info *info;
struct drm_framebuffer *fb;
struct drm_i915_gem_object *obj;
@ -244,13 +246,13 @@ static int intelfb_create(struct drm_fb_helper *helper,
/* setup aperture base/size for vesafb takeover */
info->apertures->ranges[0].base = dev->mode_config.fb_base;
info->apertures->ranges[0].size = dev_priv->ggtt.mappable_end;
info->apertures->ranges[0].size = ggtt->mappable_end;
info->fix.smem_start = dev->mode_config.fb_base + i915_gem_obj_ggtt_offset(obj);
info->fix.smem_len = size;
info->screen_base =
ioremap_wc(dev_priv->ggtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
ioremap_wc(ggtt->mappable_base + i915_gem_obj_ggtt_offset(obj),
size);
if (!info->screen_base) {
DRM_ERROR("Failed to remap framebuffer into virtual memory\n");
@ -808,8 +810,6 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
void intel_fbdev_output_poll_changed(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
async_synchronize_full();
if (dev_priv->fbdev)
drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
}
@ -821,7 +821,6 @@ void intel_fbdev_restore_mode(struct drm_device *dev)
struct intel_fbdev *ifbdev = dev_priv->fbdev;
struct drm_fb_helper *fb_helper;
async_synchronize_full();
if (!ifbdev)
return;

View File

@ -333,7 +333,7 @@ bool intel_set_pch_fifo_underrun_reporting(struct drm_i915_private *dev_priv,
old = !intel_crtc->pch_fifo_underrun_disabled;
intel_crtc->pch_fifo_underrun_disabled = !enable;
if (HAS_PCH_IBX(dev_priv->dev))
if (HAS_PCH_IBX(dev_priv))
ibx_set_fifo_underrun_reporting(dev_priv->dev, pch_transcoder,
enable);
else
@ -363,7 +363,7 @@ void intel_cpu_fifo_underrun_irq_handler(struct drm_i915_private *dev_priv,
return;
/* GMCH can't disable fifo underruns, filter them. */
if (HAS_GMCH_DISPLAY(dev_priv->dev) &&
if (HAS_GMCH_DISPLAY(dev_priv) &&
to_intel_crtc(crtc)->cpu_fifo_underrun_disabled)
return;

View File

@ -353,6 +353,24 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv)
return ret;
}
static int i915_reset_guc(struct drm_i915_private *dev_priv)
{
int ret;
u32 guc_status;
ret = intel_guc_reset(dev_priv);
if (ret) {
DRM_ERROR("GuC reset failed, ret = %d\n", ret);
return ret;
}
guc_status = I915_READ(GUC_STATUS);
WARN(!(guc_status & GS_MIA_IN_RESET),
"GuC status: 0x%x, MIA core expected to be in reset\n", guc_status);
return ret;
}
/**
* intel_guc_ucode_load() - load GuC uCode into the device
* @dev: drm device
@ -369,7 +387,7 @@ int intel_guc_ucode_load(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 err = 0;
int retries, err = 0;
if (!i915.enable_guc_submission)
return 0;
@ -417,9 +435,33 @@ int intel_guc_ucode_load(struct drm_device *dev)
if (err)
goto fail;
err = guc_ucode_xfer(dev_priv);
if (err)
goto fail;
/*
* WaEnableuKernelHeaderValidFix:skl,bxt
* For BXT, this is only upto B0 but below WA is required for later
* steppings also so this is extended as well.
*/
/* WaEnableGuCBootHashCheckNotSet:skl,bxt */
for (retries = 3; ; ) {
/*
* Always reset the GuC just before (re)loading, so
* that the state and timing are fairly predictable
*/
err = i915_reset_guc(dev_priv);
if (err) {
DRM_ERROR("GuC reset failed, err %d\n", err);
goto fail;
}
err = guc_ucode_xfer(dev_priv);
if (!err)
break;
if (--retries == 0)
goto fail;
DRM_INFO("GuC fw load failed, err %d; will reset and "
"retry %d more time(s)\n", err, retries);
}
guc_fw->guc_fw_load_status = GUC_FIRMWARE_SUCCESS;
@ -440,6 +482,7 @@ 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;

View File

@ -638,7 +638,7 @@ static bool intel_hdmi_set_gcp_infoframe(struct drm_encoder *encoder)
reg = HSW_TVIDEO_DIP_GCP(crtc->config->cpu_transcoder);
else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
reg = VLV_TVIDEO_DIP_GCP(crtc->pipe);
else if (HAS_PCH_SPLIT(dev_priv->dev))
else if (HAS_PCH_SPLIT(dev_priv))
reg = TVIDEO_DIP_GCP(crtc->pipe);
else
return false;

View File

@ -124,7 +124,7 @@ static void intel_i2c_quirk_set(struct drm_i915_private *dev_priv, bool enable)
u32 val;
/* When using bit bashing for I2C, this bit needs to be set to 1 */
if (!IS_PINEVIEW(dev_priv->dev))
if (!IS_PINEVIEW(dev_priv))
return;
val = I915_READ(DSPCLK_GATE_D);
@ -264,7 +264,7 @@ gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
u32 gmbus2 = 0;
DEFINE_WAIT(wait);
if (!HAS_GMBUS_IRQ(dev_priv->dev))
if (!HAS_GMBUS_IRQ(dev_priv))
gmbus4_irq_en = 0;
/* Important: The hw handles only the first bit, so set only one! Since
@ -300,7 +300,7 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv)
#define C ((I915_READ_NOTRACE(GMBUS2) & GMBUS_ACTIVE) == 0)
if (!HAS_GMBUS_IRQ(dev_priv->dev))
if (!HAS_GMBUS_IRQ(dev_priv))
return wait_for(C, 10);
/* Important: The hw handles only the first bit, so set only one! */

View File

@ -131,6 +131,7 @@
* preemption, but just sampling the new tail pointer).
*
*/
#include <linux/interrupt.h>
#include <drm/drmP.h>
#include <drm/i915_drm.h>
@ -418,20 +419,18 @@ static void execlists_submit_requests(struct drm_i915_gem_request *rq0,
{
struct drm_i915_private *dev_priv = rq0->i915;
/* BUG_ON(!irqs_disabled()); */
execlists_update_context(rq0);
if (rq1)
execlists_update_context(rq1);
spin_lock(&dev_priv->uncore.lock);
spin_lock_irq(&dev_priv->uncore.lock);
intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL);
execlists_elsp_write(rq0, rq1);
intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL);
spin_unlock(&dev_priv->uncore.lock);
spin_unlock_irq(&dev_priv->uncore.lock);
}
static void execlists_context_unqueue(struct intel_engine_cs *engine)
@ -538,13 +537,14 @@ get_context_status(struct intel_engine_cs *engine, unsigned int read_pointer,
/**
* intel_lrc_irq_handler() - handle Context Switch interrupts
* @ring: Engine Command Streamer to handle.
* @engine: Engine Command Streamer to handle.
*
* Check the unread Context Status Buffers and manage the submission of new
* contexts to the ELSP accordingly.
*/
void intel_lrc_irq_handler(struct intel_engine_cs *engine)
static void intel_lrc_irq_handler(unsigned long data)
{
struct intel_engine_cs *engine = (struct intel_engine_cs *)data;
struct drm_i915_private *dev_priv = engine->dev->dev_private;
u32 status_pointer;
unsigned int read_pointer, write_pointer;
@ -552,8 +552,7 @@ void intel_lrc_irq_handler(struct intel_engine_cs *engine)
unsigned int csb_read = 0, i;
unsigned int submit_contexts = 0;
spin_lock(&dev_priv->uncore.lock);
intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL);
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
status_pointer = I915_READ_FW(RING_CONTEXT_STATUS_PTR(engine));
@ -578,8 +577,7 @@ void intel_lrc_irq_handler(struct intel_engine_cs *engine)
_MASKED_FIELD(GEN8_CSB_READ_PTR_MASK,
engine->next_context_status_buffer << 8));
intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL);
spin_unlock(&dev_priv->uncore.lock);
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
spin_lock(&engine->execlist_lock);
@ -621,7 +619,7 @@ static void execlists_context_queue(struct drm_i915_gem_request *request)
i915_gem_request_reference(request);
spin_lock_irq(&engine->execlist_lock);
spin_lock_bh(&engine->execlist_lock);
list_for_each_entry(cursor, &engine->execlist_queue, execlist_link)
if (++num_elements > 2)
@ -646,7 +644,7 @@ static void execlists_context_queue(struct drm_i915_gem_request *request)
if (num_elements == 0)
execlists_context_unqueue(engine);
spin_unlock_irq(&engine->execlist_lock);
spin_unlock_bh(&engine->execlist_lock);
}
static int logical_ring_invalidate_all_caches(struct drm_i915_gem_request *req)
@ -856,11 +854,11 @@ static int logical_ring_prepare(struct drm_i915_gem_request *req, int bytes)
if (unlikely(total_bytes > remain_usable)) {
/*
* The base request will fit but the reserved space
* falls off the end. So only need to to wait for the
* reserved size after flushing out the remainder.
* falls off the end. So don't need an immediate wrap
* and only need to effectively wait for the reserved
* size space from the start of ringbuffer.
*/
wait_bytes = remain_actual + ringbuf->reserved_size;
need_wrap = true;
} else if (total_bytes > ringbuf->space) {
/* No wrapping required, just waiting. */
wait_bytes = total_bytes;
@ -1033,9 +1031,9 @@ void intel_execlists_retire_requests(struct intel_engine_cs *engine)
return;
INIT_LIST_HEAD(&retired_list);
spin_lock_irq(&engine->execlist_lock);
spin_lock_bh(&engine->execlist_lock);
list_replace_init(&engine->execlist_retired_req_list, &retired_list);
spin_unlock_irq(&engine->execlist_lock);
spin_unlock_bh(&engine->execlist_lock);
list_for_each_entry_safe(req, tmp, &retired_list, execlist_link) {
struct intel_context *ctx = req->ctx;
@ -1450,6 +1448,25 @@ static int gen9_init_perctx_bb(struct intel_engine_cs *engine,
wa_ctx_emit(batch, index, MI_NOOP);
}
/* WaClearTdlStateAckDirtyBits:bxt */
if (IS_BXT_REVID(dev, 0, BXT_REVID_B0)) {
wa_ctx_emit(batch, index, MI_LOAD_REGISTER_IMM(4));
wa_ctx_emit_reg(batch, index, GEN8_STATE_ACK);
wa_ctx_emit(batch, index, _MASKED_BIT_DISABLE(GEN9_SUBSLICE_TDL_ACK_BITS));
wa_ctx_emit_reg(batch, index, GEN9_STATE_ACK_SLICE1);
wa_ctx_emit(batch, index, _MASKED_BIT_DISABLE(GEN9_SUBSLICE_TDL_ACK_BITS));
wa_ctx_emit_reg(batch, index, GEN9_STATE_ACK_SLICE2);
wa_ctx_emit(batch, index, _MASKED_BIT_DISABLE(GEN9_SUBSLICE_TDL_ACK_BITS));
wa_ctx_emit_reg(batch, index, GEN7_ROW_CHICKEN2);
/* dummy write to CS, mask bits are 0 to ensure the register is not modified */
wa_ctx_emit(batch, index, 0x0);
wa_ctx_emit(batch, index, MI_NOOP);
}
/* WaDisableCtxRestoreArbitration:skl,bxt */
if (IS_SKL_REVID(dev, 0, SKL_REVID_D0) ||
IS_BXT_REVID(dev, 0, BXT_REVID_A1))
@ -1854,7 +1871,7 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request,
return 0;
}
static u32 gen8_get_seqno(struct intel_engine_cs *engine, bool lazy_coherency)
static u32 gen8_get_seqno(struct intel_engine_cs *engine)
{
return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
}
@ -1864,10 +1881,8 @@ static void gen8_set_seqno(struct intel_engine_cs *engine, u32 seqno)
intel_write_status_page(engine, I915_GEM_HWS_INDEX, seqno);
}
static u32 bxt_a_get_seqno(struct intel_engine_cs *engine,
bool lazy_coherency)
static void bxt_a_seqno_barrier(struct intel_engine_cs *engine)
{
/*
* On BXT A steppings there is a HW coherency issue whereby the
* MI_STORE_DATA_IMM storing the completed request's seqno
@ -1878,11 +1893,7 @@ static u32 bxt_a_get_seqno(struct intel_engine_cs *engine,
* bxt_a_set_seqno(), where we also do a clflush after the write. So
* this clflush in practice becomes an invalidate operation.
*/
if (!lazy_coherency)
intel_flush_status_page(engine, I915_GEM_HWS_INDEX);
return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
intel_flush_status_page(engine, I915_GEM_HWS_INDEX);
}
static void bxt_a_set_seqno(struct intel_engine_cs *engine, u32 seqno)
@ -2016,6 +2027,13 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine)
if (!intel_engine_initialized(engine))
return;
/*
* Tasklet cannot be active at this point due intel_mark_active/idle
* so this is just for documentation.
*/
if (WARN_ON(test_bit(TASKLET_STATE_SCHED, &engine->irq_tasklet.state)))
tasklet_kill(&engine->irq_tasklet);
dev_priv = engine->dev->dev_private;
if (engine->buffer) {
@ -2053,12 +2071,11 @@ logical_ring_default_vfuncs(struct drm_device *dev,
engine->irq_get = gen8_logical_ring_get_irq;
engine->irq_put = gen8_logical_ring_put_irq;
engine->emit_bb_start = gen8_emit_bb_start;
engine->get_seqno = gen8_get_seqno;
engine->set_seqno = gen8_set_seqno;
if (IS_BXT_REVID(dev, 0, BXT_REVID_A1)) {
engine->get_seqno = bxt_a_get_seqno;
engine->irq_seqno_barrier = bxt_a_seqno_barrier;
engine->set_seqno = bxt_a_set_seqno;
} else {
engine->get_seqno = gen8_get_seqno;
engine->set_seqno = gen8_set_seqno;
}
}
@ -2089,6 +2106,9 @@ logical_ring_init(struct drm_device *dev, struct intel_engine_cs *engine)
INIT_LIST_HEAD(&engine->execlist_retired_req_list);
spin_lock_init(&engine->execlist_lock);
tasklet_init(&engine->irq_tasklet,
intel_lrc_irq_handler, (unsigned long)engine);
logical_ring_init_platform_invariants(engine);
ret = i915_cmd_parser_init_ring(engine);

View File

@ -118,7 +118,6 @@ int intel_execlists_submission(struct i915_execbuffer_params *params,
struct drm_i915_gem_execbuffer2 *args,
struct list_head *vmas);
void intel_lrc_irq_handler(struct intel_engine_cs *engine);
void intel_execlists_retire_requests(struct intel_engine_cs *engine);
#endif /* _INTEL_LRC_H_ */

View File

@ -472,11 +472,8 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
* and as part of the cleanup in the hw state restore we also redisable
* the vga plane.
*/
if (!HAS_PCH_SPLIT(dev)) {
drm_modeset_lock_all(dev);
if (!HAS_PCH_SPLIT(dev))
intel_display_resume(dev);
drm_modeset_unlock_all(dev);
}
dev_priv->modeset_restore = MODESET_DONE;

View File

@ -190,13 +190,14 @@ struct intel_overlay {
static struct overlay_registers __iomem *
intel_overlay_map_regs(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(overlay->dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct overlay_registers __iomem *regs;
if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
regs = (struct overlay_registers __iomem *)overlay->reg_bo->phys_handle->vaddr;
else
regs = io_mapping_map_wc(dev_priv->ggtt.mappable,
regs = io_mapping_map_wc(ggtt->mappable,
i915_gem_obj_ggtt_offset(overlay->reg_bo));
return regs;
@ -1481,7 +1482,8 @@ struct intel_overlay_error_state {
static struct overlay_registers __iomem *
intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
{
struct drm_i915_private *dev_priv = overlay->dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(overlay->dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct overlay_registers __iomem *regs;
if (OVERLAY_NEEDS_PHYSICAL(overlay->dev))
@ -1490,7 +1492,7 @@ intel_overlay_map_regs_atomic(struct intel_overlay *overlay)
regs = (struct overlay_registers __iomem *)
overlay->reg_bo->phys_handle->vaddr;
else
regs = io_mapping_map_atomic_wc(dev_priv->ggtt.mappable,
regs = io_mapping_map_atomic_wc(ggtt->mappable,
i915_gem_obj_ggtt_offset(overlay->reg_bo));
return regs;

View File

@ -2937,25 +2937,28 @@ skl_plane_relative_data_rate(const struct intel_crtc_state *cstate,
const struct drm_plane_state *pstate,
int y)
{
struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc);
struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate);
struct drm_framebuffer *fb = pstate->fb;
uint32_t width = 0, height = 0;
width = drm_rect_width(&intel_pstate->src) >> 16;
height = drm_rect_height(&intel_pstate->src) >> 16;
if (intel_rotation_90_or_270(pstate->rotation))
swap(width, height);
/* for planar format */
if (fb->pixel_format == DRM_FORMAT_NV12) {
if (y) /* y-plane data rate */
return intel_crtc->config->pipe_src_w *
intel_crtc->config->pipe_src_h *
return width * height *
drm_format_plane_cpp(fb->pixel_format, 0);
else /* uv-plane data rate */
return (intel_crtc->config->pipe_src_w/2) *
(intel_crtc->config->pipe_src_h/2) *
return (width / 2) * (height / 2) *
drm_format_plane_cpp(fb->pixel_format, 1);
}
/* for packed formats */
return intel_crtc->config->pipe_src_w *
intel_crtc->config->pipe_src_h *
drm_format_plane_cpp(fb->pixel_format, 0);
return width * height * drm_format_plane_cpp(fb->pixel_format, 0);
}
/*
@ -3034,8 +3037,9 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
struct drm_framebuffer *fb = plane->state->fb;
int id = skl_wm_plane_id(intel_plane);
if (fb == NULL)
if (!to_intel_plane_state(plane->state)->visible)
continue;
if (plane->type == DRM_PLANE_TYPE_CURSOR)
continue;
@ -3061,7 +3065,7 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,
uint16_t plane_blocks, y_plane_blocks = 0;
int id = skl_wm_plane_id(intel_plane);
if (pstate->fb == NULL)
if (!to_intel_plane_state(pstate)->visible)
continue;
if (plane->type == DRM_PLANE_TYPE_CURSOR)
continue;
@ -3184,26 +3188,36 @@ static bool skl_compute_plane_wm(const struct drm_i915_private *dev_priv,
{
struct drm_plane *plane = &intel_plane->base;
struct drm_framebuffer *fb = plane->state->fb;
struct intel_plane_state *intel_pstate =
to_intel_plane_state(plane->state);
uint32_t latency = dev_priv->wm.skl_latency[level];
uint32_t method1, method2;
uint32_t plane_bytes_per_line, plane_blocks_per_line;
uint32_t res_blocks, res_lines;
uint32_t selected_result;
uint8_t cpp;
uint32_t width = 0, height = 0;
if (latency == 0 || !cstate->base.active || !fb)
if (latency == 0 || !cstate->base.active || !intel_pstate->visible)
return false;
width = drm_rect_width(&intel_pstate->src) >> 16;
height = drm_rect_height(&intel_pstate->src) >> 16;
if (intel_rotation_90_or_270(plane->state->rotation))
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),
cstate->base.adjusted_mode.crtc_htotal,
cstate->pipe_src_w,
cpp, fb->modifier[0],
width,
cpp,
fb->modifier[0],
latency);
plane_bytes_per_line = cstate->pipe_src_w * cpp;
plane_bytes_per_line = width * cpp;
plane_blocks_per_line = DIV_ROUND_UP(plane_bytes_per_line, 512);
if (fb->modifier[0] == I915_FORMAT_MOD_Y_TILED ||
@ -4288,7 +4302,7 @@ static u32 intel_rps_limits(struct drm_i915_private *dev_priv, u8 val)
* the hw runs at the minimal clock before selecting the desired
* frequency, if the down threshold expires in that window we will not
* receive a down interrupt. */
if (IS_GEN9(dev_priv->dev)) {
if (IS_GEN9(dev_priv)) {
limits = (dev_priv->rps.max_freq_softlimit) << 23;
if (val <= dev_priv->rps.min_freq_softlimit)
limits |= (dev_priv->rps.min_freq_softlimit) << 14;
@ -4630,7 +4644,8 @@ static void intel_print_rc6_info(struct drm_device *dev, u32 mode)
static bool bxt_check_bios_rc6_setup(const struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
bool enable_rc6 = true;
unsigned long rc6_ctx_base;
@ -4644,9 +4659,9 @@ static bool bxt_check_bios_rc6_setup(const struct drm_device *dev)
* for this check.
*/
rc6_ctx_base = I915_READ(RC6_CTX_BASE) & RC6_CTX_BASE_MASK;
if (!((rc6_ctx_base >= dev_priv->ggtt.stolen_reserved_base) &&
(rc6_ctx_base + PAGE_SIZE <= dev_priv->ggtt.stolen_reserved_base +
dev_priv->ggtt.stolen_reserved_size))) {
if (!((rc6_ctx_base >= ggtt->stolen_reserved_base) &&
(rc6_ctx_base + PAGE_SIZE <= ggtt->stolen_reserved_base +
ggtt->stolen_reserved_size))) {
DRM_DEBUG_KMS("RC6 Base address not as expected.\n");
enable_rc6 = false;
}
@ -4807,7 +4822,7 @@ static void gen9_enable_rps(struct drm_device *dev)
* Up/Down EI & threshold registers, as well as the RP_CONTROL,
* RP_INTERRUPT_LIMITS & RPNSWREQ registers */
dev_priv->rps.power = HIGH_POWER; /* force a reset */
gen6_set_rps(dev_priv->dev, dev_priv->rps.min_freq_softlimit);
gen6_set_rps(dev_priv->dev, dev_priv->rps.idle_freq);
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
}
@ -5287,9 +5302,9 @@ static void cherryview_check_pctx(struct drm_i915_private *dev_priv)
static void cherryview_setup_pctx(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long pctx_paddr, paddr;
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
unsigned long pctx_paddr, paddr;
u32 pcbr;
int pctx_size = 32*1024;
@ -5365,6 +5380,17 @@ static void valleyview_cleanup_pctx(struct drm_device *dev)
dev_priv->vlv_pctx = NULL;
}
static void vlv_init_gpll_ref_freq(struct drm_i915_private *dev_priv)
{
dev_priv->rps.gpll_ref_freq =
vlv_get_cck_clock(dev_priv, "GPLL ref",
CCK_GPLL_CLOCK_CONTROL,
dev_priv->czclk_freq);
DRM_DEBUG_DRIVER("GPLL reference freq: %d kHz\n",
dev_priv->rps.gpll_ref_freq);
}
static void valleyview_init_gt_powersave(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
@ -5372,6 +5398,8 @@ static void valleyview_init_gt_powersave(struct drm_device *dev)
valleyview_setup_pctx(dev);
vlv_init_gpll_ref_freq(dev_priv);
mutex_lock(&dev_priv->rps.hw_lock);
val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS);
@ -5429,6 +5457,8 @@ static void cherryview_init_gt_powersave(struct drm_device *dev)
cherryview_setup_pctx(dev);
vlv_init_gpll_ref_freq(dev_priv);
mutex_lock(&dev_priv->rps.hw_lock);
mutex_lock(&dev_priv->sb_lock);
@ -5579,10 +5609,10 @@ static void cherryview_enable_rps(struct drm_device *dev)
dev_priv->rps.cur_freq);
DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
dev_priv->rps.efficient_freq);
intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq),
dev_priv->rps.idle_freq);
valleyview_set_rps(dev_priv->dev, dev_priv->rps.efficient_freq);
valleyview_set_rps(dev_priv->dev, dev_priv->rps.idle_freq);
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
}
@ -5668,10 +5698,10 @@ static void valleyview_enable_rps(struct drm_device *dev)
dev_priv->rps.cur_freq);
DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n",
intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq),
dev_priv->rps.efficient_freq);
intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq),
dev_priv->rps.idle_freq);
valleyview_set_rps(dev_priv->dev, dev_priv->rps.efficient_freq);
valleyview_set_rps(dev_priv->dev, dev_priv->rps.idle_freq);
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
}
@ -7279,78 +7309,43 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u32 mbox, u32 val
return 0;
}
static int vlv_gpu_freq_div(unsigned int czclk_freq)
{
switch (czclk_freq) {
case 200:
return 10;
case 267:
return 12;
case 320:
case 333:
return 16;
case 400:
return 20;
default:
return -1;
}
}
static int byt_gpu_freq(struct drm_i915_private *dev_priv, int val)
{
int div, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
div = vlv_gpu_freq_div(czclk_freq);
if (div < 0)
return div;
return DIV_ROUND_CLOSEST(czclk_freq * (val + 6 - 0xbd), div);
/*
* N = val - 0xb7
* Slow = Fast = GPLL ref * N
*/
return DIV_ROUND_CLOSEST(dev_priv->rps.gpll_ref_freq * (val - 0xb7), 1000);
}
static int byt_freq_opcode(struct drm_i915_private *dev_priv, int val)
{
int mul, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
mul = vlv_gpu_freq_div(czclk_freq);
if (mul < 0)
return mul;
return DIV_ROUND_CLOSEST(mul * val, czclk_freq) + 0xbd - 6;
return DIV_ROUND_CLOSEST(1000 * val, dev_priv->rps.gpll_ref_freq) + 0xb7;
}
static int chv_gpu_freq(struct drm_i915_private *dev_priv, int val)
{
int div, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
div = vlv_gpu_freq_div(czclk_freq);
if (div < 0)
return div;
div /= 2;
return DIV_ROUND_CLOSEST(czclk_freq * val, 2 * div) / 2;
/*
* N = val / 2
* CU (slow) = CU2x (fast) / 2 = GPLL ref * N / 2
*/
return DIV_ROUND_CLOSEST(dev_priv->rps.gpll_ref_freq * val, 2 * 2 * 1000);
}
static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val)
{
int mul, czclk_freq = DIV_ROUND_CLOSEST(dev_priv->czclk_freq, 1000);
mul = vlv_gpu_freq_div(czclk_freq);
if (mul < 0)
return mul;
mul /= 2;
/* CHV needs even values */
return DIV_ROUND_CLOSEST(val * 2 * mul, czclk_freq) * 2;
return DIV_ROUND_CLOSEST(2 * 1000 * val, dev_priv->rps.gpll_ref_freq) * 2;
}
int intel_gpu_freq(struct drm_i915_private *dev_priv, int val)
{
if (IS_GEN9(dev_priv->dev))
if (IS_GEN9(dev_priv))
return DIV_ROUND_CLOSEST(val * GT_FREQUENCY_MULTIPLIER,
GEN9_FREQ_SCALER);
else if (IS_CHERRYVIEW(dev_priv->dev))
else if (IS_CHERRYVIEW(dev_priv))
return chv_gpu_freq(dev_priv, val);
else if (IS_VALLEYVIEW(dev_priv->dev))
else if (IS_VALLEYVIEW(dev_priv))
return byt_gpu_freq(dev_priv, val);
else
return val * GT_FREQUENCY_MULTIPLIER;
@ -7358,12 +7353,12 @@ int intel_gpu_freq(struct drm_i915_private *dev_priv, int val)
int intel_freq_opcode(struct drm_i915_private *dev_priv, int val)
{
if (IS_GEN9(dev_priv->dev))
if (IS_GEN9(dev_priv))
return DIV_ROUND_CLOSEST(val * GEN9_FREQ_SCALER,
GT_FREQUENCY_MULTIPLIER);
else if (IS_CHERRYVIEW(dev_priv->dev))
else if (IS_CHERRYVIEW(dev_priv))
return chv_freq_opcode(dev_priv, val);
else if (IS_VALLEYVIEW(dev_priv->dev))
else if (IS_VALLEYVIEW(dev_priv))
return byt_freq_opcode(dev_priv, val);
else
return DIV_ROUND_CLOSEST(val, GT_FREQUENCY_MULTIPLIER);

View File

@ -563,7 +563,7 @@ static void intel_psr_work(struct work_struct *work)
* PSR might take some time to get fully disabled
* and be ready for re-enable.
*/
if (HAS_DDI(dev_priv->dev)) {
if (HAS_DDI(dev_priv)) {
if (wait_for((I915_READ(EDP_PSR_STATUS_CTL) &
EDP_PSR_STATUS_STATE_MASK) == 0, 50)) {
DRM_ERROR("Timed out waiting for PSR Idle for re-enable\n");

View File

@ -1568,22 +1568,27 @@ pc_render_add_request(struct drm_i915_gem_request *req)
return 0;
}
static u32
gen6_ring_get_seqno(struct intel_engine_cs *engine, bool lazy_coherency)
static void
gen6_seqno_barrier(struct intel_engine_cs *engine)
{
/* Workaround to force correct ordering between irq and seqno writes on
* ivb (and maybe also on snb) by reading from a CS register (like
* ACTHD) before reading the status page. */
if (!lazy_coherency) {
struct drm_i915_private *dev_priv = engine->dev->dev_private;
POSTING_READ(RING_ACTHD(engine->mmio_base));
}
return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
* ACTHD) before reading the status page.
*
* Note that this effectively stalls the read by the time it takes to
* do a memory transaction, which more or less ensures that the write
* from the GPU has sufficient time to invalidate the CPU cacheline.
* Alternatively we could delay the interrupt from the CS ring to give
* the write time to land, but that would incur a delay after every
* batch i.e. much more frequent than a delay when waiting for the
* interrupt (with the same net latency).
*/
struct drm_i915_private *dev_priv = engine->dev->dev_private;
POSTING_READ_FW(RING_ACTHD(engine->mmio_base));
}
static u32
ring_get_seqno(struct intel_engine_cs *engine, bool lazy_coherency)
ring_get_seqno(struct intel_engine_cs *engine)
{
return intel_read_status_page(engine, I915_GEM_HWS_INDEX);
}
@ -1595,7 +1600,7 @@ ring_set_seqno(struct intel_engine_cs *engine, u32 seqno)
}
static u32
pc_render_get_seqno(struct intel_engine_cs *engine, bool lazy_coherency)
pc_render_get_seqno(struct intel_engine_cs *engine)
{
return engine->scratch.cpu_page[0];
}
@ -2078,39 +2083,18 @@ static int init_phys_status_page(struct intel_engine_cs *engine)
void intel_unpin_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
{
if (HAS_LLC(ringbuf->obj->base.dev) && !ringbuf->obj->stolen)
vunmap(ringbuf->virtual_start);
i915_gem_object_unpin_map(ringbuf->obj);
else
iounmap(ringbuf->virtual_start);
ringbuf->virtual_start = NULL;
ringbuf->vma = NULL;
i915_gem_object_ggtt_unpin(ringbuf->obj);
}
static u32 *vmap_obj(struct drm_i915_gem_object *obj)
{
struct sg_page_iter sg_iter;
struct page **pages;
void *addr;
int i;
pages = drm_malloc_ab(obj->base.size >> PAGE_SHIFT, sizeof(*pages));
if (pages == NULL)
return NULL;
i = 0;
for_each_sg_page(obj->pages->sgl, &sg_iter, obj->pages->nents, 0)
pages[i++] = sg_page_iter_page(&sg_iter);
addr = vmap(pages, i, 0, PAGE_KERNEL);
drm_free_large(pages);
return addr;
}
int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
struct intel_ringbuffer *ringbuf)
{
struct drm_i915_private *dev_priv = to_i915(dev);
struct i915_ggtt *ggtt = &dev_priv->ggtt;
struct drm_i915_gem_object *obj = ringbuf->obj;
int ret;
@ -2120,15 +2104,13 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
return ret;
ret = i915_gem_object_set_to_cpu_domain(obj, true);
if (ret) {
i915_gem_object_ggtt_unpin(obj);
return ret;
}
if (ret)
goto err_unpin;
ringbuf->virtual_start = vmap_obj(obj);
ringbuf->virtual_start = i915_gem_object_pin_map(obj);
if (ringbuf->virtual_start == NULL) {
i915_gem_object_ggtt_unpin(obj);
return -ENOMEM;
ret = -ENOMEM;
goto err_unpin;
}
} else {
ret = i915_gem_obj_ggtt_pin(obj, PAGE_SIZE, PIN_MAPPABLE);
@ -2136,25 +2118,26 @@ int intel_pin_and_map_ringbuffer_obj(struct drm_device *dev,
return ret;
ret = i915_gem_object_set_to_gtt_domain(obj, true);
if (ret) {
i915_gem_object_ggtt_unpin(obj);
return ret;
}
if (ret)
goto err_unpin;
/* Access through the GTT requires the device to be awake. */
assert_rpm_wakelock_held(dev_priv);
ringbuf->virtual_start = ioremap_wc(dev_priv->ggtt.mappable_base +
ringbuf->virtual_start = ioremap_wc(ggtt->mappable_base +
i915_gem_obj_ggtt_offset(obj), ringbuf->size);
if (ringbuf->virtual_start == NULL) {
i915_gem_object_ggtt_unpin(obj);
return -EINVAL;
ret = -ENOMEM;
goto err_unpin;
}
}
ringbuf->vma = i915_gem_obj_to_ggtt(obj);
return 0;
err_unpin:
i915_gem_object_ggtt_unpin(obj);
return ret;
}
static void intel_destroy_ringbuffer_obj(struct intel_ringbuffer *ringbuf)
@ -2477,11 +2460,11 @@ static int __intel_ring_prepare(struct intel_engine_cs *engine, int bytes)
if (unlikely(total_bytes > remain_usable)) {
/*
* The base request will fit but the reserved space
* falls off the end. So only need to to wait for the
* reserved size after flushing out the remainder.
* falls off the end. So don't need an immediate wrap
* and only need to effectively wait for the reserved
* size space from the start of ringbuffer.
*/
wait_bytes = remain_actual + ringbuf->reserved_size;
need_wrap = true;
} else if (total_bytes > ringbuf->space) {
/* No wrapping required, just waiting. */
wait_bytes = total_bytes;
@ -2549,17 +2532,36 @@ int intel_ring_cacheline_align(struct drm_i915_gem_request *req)
void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno)
{
struct drm_device *dev = engine->dev;
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_private *dev_priv = to_i915(engine->dev);
if (INTEL_INFO(dev)->gen == 6 || INTEL_INFO(dev)->gen == 7) {
/* Our semaphore implementation is strictly monotonic (i.e. we proceed
* so long as the semaphore value in the register/page is greater
* than the sync value), so whenever we reset the seqno,
* so long as we reset the tracking semaphore value to 0, it will
* always be before the next request's seqno. If we don't reset
* the semaphore value, then when the seqno moves backwards all
* future waits will complete instantly (causing rendering corruption).
*/
if (INTEL_INFO(dev_priv)->gen == 6 || INTEL_INFO(dev_priv)->gen == 7) {
I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
if (HAS_VEBOX(dev))
if (HAS_VEBOX(dev_priv))
I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
}
if (dev_priv->semaphore_obj) {
struct drm_i915_gem_object *obj = dev_priv->semaphore_obj;
struct page *page = i915_gem_object_get_dirty_page(obj, 0);
void *semaphores = kmap(page);
memset(semaphores + GEN8_SEMAPHORE_OFFSET(engine->id, 0),
0, I915_NUM_ENGINES * gen8_semaphore_seqno_size);
kunmap(page);
}
memset(engine->semaphore.sync_seqno, 0,
sizeof(engine->semaphore.sync_seqno));
engine->set_seqno(engine, seqno);
engine->last_submitted_seqno = seqno;
engine->hangcheck.seqno = seqno;
}
@ -2799,7 +2801,8 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
engine->irq_get = gen8_ring_get_irq;
engine->irq_put = gen8_ring_put_irq;
engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
engine->get_seqno = gen6_ring_get_seqno;
engine->irq_seqno_barrier = gen6_seqno_barrier;
engine->get_seqno = ring_get_seqno;
engine->set_seqno = ring_set_seqno;
if (i915_semaphore_is_enabled(dev)) {
WARN_ON(!dev_priv->semaphore_obj);
@ -2816,7 +2819,8 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
engine->irq_get = gen6_ring_get_irq;
engine->irq_put = gen6_ring_put_irq;
engine->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
engine->get_seqno = gen6_ring_get_seqno;
engine->irq_seqno_barrier = gen6_seqno_barrier;
engine->get_seqno = ring_get_seqno;
engine->set_seqno = ring_set_seqno;
if (i915_semaphore_is_enabled(dev)) {
engine->semaphore.sync_to = gen6_ring_sync;
@ -2931,7 +2935,8 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
engine->write_tail = gen6_bsd_ring_write_tail;
engine->flush = gen6_bsd_ring_flush;
engine->add_request = gen6_add_request;
engine->get_seqno = gen6_ring_get_seqno;
engine->irq_seqno_barrier = gen6_seqno_barrier;
engine->get_seqno = ring_get_seqno;
engine->set_seqno = ring_set_seqno;
if (INTEL_INFO(dev)->gen >= 8) {
engine->irq_enable_mask =
@ -3004,7 +3009,8 @@ int intel_init_bsd2_ring_buffer(struct drm_device *dev)
engine->mmio_base = GEN8_BSD2_RING_BASE;
engine->flush = gen6_bsd_ring_flush;
engine->add_request = gen6_add_request;
engine->get_seqno = gen6_ring_get_seqno;
engine->irq_seqno_barrier = gen6_seqno_barrier;
engine->get_seqno = ring_get_seqno;
engine->set_seqno = ring_set_seqno;
engine->irq_enable_mask =
GT_RENDER_USER_INTERRUPT << GEN8_VCS2_IRQ_SHIFT;
@ -3035,7 +3041,8 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
engine->write_tail = ring_write_tail;
engine->flush = gen6_ring_flush;
engine->add_request = gen6_add_request;
engine->get_seqno = gen6_ring_get_seqno;
engine->irq_seqno_barrier = gen6_seqno_barrier;
engine->get_seqno = ring_get_seqno;
engine->set_seqno = ring_set_seqno;
if (INTEL_INFO(dev)->gen >= 8) {
engine->irq_enable_mask =
@ -3093,7 +3100,8 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev)
engine->write_tail = ring_write_tail;
engine->flush = gen6_ring_flush;
engine->add_request = gen6_add_request;
engine->get_seqno = gen6_ring_get_seqno;
engine->irq_seqno_barrier = gen6_seqno_barrier;
engine->get_seqno = ring_get_seqno;
engine->set_seqno = ring_set_seqno;
if (INTEL_INFO(dev)->gen >= 8) {

View File

@ -52,16 +52,15 @@ struct intel_hw_status_page {
/* seqno size is actually only a uint32, but since we plan to use MI_FLUSH_DW to
* do the writes, and that must have qw aligned offsets, simply pretend it's 8b.
*/
#define i915_semaphore_seqno_size sizeof(uint64_t)
#define gen8_semaphore_seqno_size sizeof(uint64_t)
#define GEN8_SEMAPHORE_OFFSET(__from, __to) \
(((__from) * I915_NUM_ENGINES + (__to)) * gen8_semaphore_seqno_size)
#define GEN8_SIGNAL_OFFSET(__ring, to) \
(i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
((__ring)->id * I915_NUM_ENGINES * i915_semaphore_seqno_size) + \
(i915_semaphore_seqno_size * (to)))
GEN8_SEMAPHORE_OFFSET((__ring)->id, (to)))
#define GEN8_WAIT_OFFSET(__ring, from) \
(i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
((from) * I915_NUM_ENGINES * i915_semaphore_seqno_size) + \
(i915_semaphore_seqno_size * (__ring)->id))
GEN8_SEMAPHORE_OFFSET(from, (__ring)->id))
#define GEN8_RING_SEMAPHORE_INIT(e) do { \
if (!dev_priv->semaphore_obj) { \
@ -88,6 +87,7 @@ enum intel_ring_hangcheck_action {
struct intel_ring_hangcheck {
u64 acthd;
u32 seqno;
unsigned user_interrupts;
int score;
enum intel_ring_hangcheck_action action;
int deadlock;
@ -194,8 +194,8 @@ struct intel_engine_cs {
* seen value is good enough. Note that the seqno will always be
* monotonic, even if not coherent.
*/
u32 (*get_seqno)(struct intel_engine_cs *ring,
bool lazy_coherency);
void (*irq_seqno_barrier)(struct intel_engine_cs *ring);
u32 (*get_seqno)(struct intel_engine_cs *ring);
void (*set_seqno)(struct intel_engine_cs *ring,
u32 seqno);
int (*dispatch_execbuffer)(struct drm_i915_gem_request *req,
@ -266,7 +266,8 @@ struct intel_engine_cs {
} semaphore;
/* Execlists */
spinlock_t execlist_lock;
struct tasklet_struct irq_tasklet;
spinlock_t execlist_lock; /* used inside tasklet, use spin_lock_bh */
struct list_head execlist_queue;
struct list_head execlist_retired_req_list;
unsigned int next_context_status_buffer;
@ -305,6 +306,7 @@ struct intel_engine_cs {
* inspecting request list.
*/
u32 last_submitted_seqno;
unsigned user_interrupts;
bool gpu_caches_dirty;
@ -383,17 +385,16 @@ intel_ring_sync_index(struct intel_engine_cs *engine,
static inline void
intel_flush_status_page(struct intel_engine_cs *engine, int reg)
{
drm_clflush_virt_range(&engine->status_page.page_addr[reg],
sizeof(uint32_t));
mb();
clflush(&engine->status_page.page_addr[reg]);
mb();
}
static inline u32
intel_read_status_page(struct intel_engine_cs *engine,
int reg)
intel_read_status_page(struct intel_engine_cs *engine, int reg)
{
/* Ensure that the compiler doesn't optimize away the load. */
barrier();
return engine->status_page.page_addr[reg];
return READ_ONCE(engine->status_page.page_addr[reg]);
}
static inline void

View File

@ -2039,17 +2039,17 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
* The enabling order will be from lower to higher indexed wells,
* the disabling order is reversed.
*/
if (IS_HASWELL(dev_priv->dev)) {
if (IS_HASWELL(dev_priv)) {
set_power_wells(power_domains, hsw_power_wells);
} else if (IS_BROADWELL(dev_priv->dev)) {
} else if (IS_BROADWELL(dev_priv)) {
set_power_wells(power_domains, bdw_power_wells);
} else if (IS_SKYLAKE(dev_priv->dev) || IS_KABYLAKE(dev_priv->dev)) {
} else if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) {
set_power_wells(power_domains, skl_power_wells);
} else if (IS_BROXTON(dev_priv->dev)) {
} else if (IS_BROXTON(dev_priv)) {
set_power_wells(power_domains, bxt_power_wells);
} else if (IS_CHERRYVIEW(dev_priv->dev)) {
} else if (IS_CHERRYVIEW(dev_priv)) {
set_power_wells(power_domains, chv_power_wells);
} else if (IS_VALLEYVIEW(dev_priv->dev)) {
} else if (IS_VALLEYVIEW(dev_priv)) {
set_power_wells(power_domains, vlv_power_wells);
} else {
set_power_wells(power_domains, i9xx_always_on_power_well);

View File

@ -1025,8 +1025,8 @@ static uint32_t skl_plane_formats[] = {
int
intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
{
struct intel_plane *intel_plane;
struct intel_plane_state *state;
struct intel_plane *intel_plane = NULL;
struct intel_plane_state *state = NULL;
unsigned long possible_crtcs;
const uint32_t *plane_formats;
int num_plane_formats;
@ -1036,13 +1036,15 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
return -ENODEV;
intel_plane = kzalloc(sizeof(*intel_plane), GFP_KERNEL);
if (!intel_plane)
return -ENOMEM;
if (!intel_plane) {
ret = -ENOMEM;
goto fail;
}
state = intel_create_plane_state(&intel_plane->base);
if (!state) {
kfree(intel_plane);
return -ENOMEM;
ret = -ENOMEM;
goto fail;
}
intel_plane->base.state = &state->base;
@ -1097,28 +1099,34 @@ intel_plane_init(struct drm_device *dev, enum pipe pipe, int plane)
num_plane_formats = ARRAY_SIZE(skl_plane_formats);
break;
default:
kfree(intel_plane);
return -ENODEV;
MISSING_CASE(INTEL_INFO(dev)->gen);
ret = -ENODEV;
goto fail;
}
intel_plane->pipe = pipe;
intel_plane->plane = plane;
intel_plane->frontbuffer_bit = INTEL_FRONTBUFFER_SPRITE(pipe, plane);
intel_plane->check_plane = intel_check_sprite_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 (ret) {
kfree(intel_plane);
goto out;
}
if (ret)
goto fail;
intel_create_rotation_property(dev, intel_plane);
drm_plane_helper_add(&intel_plane->base, &intel_plane_helper_funcs);
out:
return 0;
fail:
kfree(state);
kfree(intel_plane);
return ret;
}

View File

@ -204,7 +204,7 @@ static int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
/* On VLV, FIFO will be shared by both SW and HW.
* So, we need to read the FREE_ENTRIES everytime */
if (IS_VALLEYVIEW(dev_priv->dev))
if (IS_VALLEYVIEW(dev_priv))
dev_priv->uncore.fifo_count = fifo_free_entries(dev_priv);
if (dev_priv->uncore.fifo_count < GT_FIFO_NUM_RESERVED_ENTRIES) {
@ -716,8 +716,8 @@ __gen2_read(64)
trace_i915_reg_rw(false, reg, val, sizeof(val), trace); \
return val
static inline void __force_wake_get(struct drm_i915_private *dev_priv,
enum forcewake_domains fw_domains)
static inline void __force_wake_auto(struct drm_i915_private *dev_priv,
enum forcewake_domains fw_domains)
{
struct intel_uncore_forcewake_domain *domain;
enum forcewake_domain_id id;
@ -745,7 +745,7 @@ static u##x \
gen6_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
GEN6_READ_HEADER(x); \
if (NEEDS_FORCE_WAKE(offset)) \
__force_wake_get(dev_priv, FORCEWAKE_RENDER); \
__force_wake_auto(dev_priv, FORCEWAKE_RENDER); \
val = __raw_i915_read##x(dev_priv, reg); \
GEN6_READ_FOOTER; \
}
@ -762,7 +762,7 @@ vlv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(offset)) \
fw_engine = FORCEWAKE_MEDIA; \
if (fw_engine) \
__force_wake_get(dev_priv, fw_engine); \
__force_wake_auto(dev_priv, fw_engine); \
val = __raw_i915_read##x(dev_priv, reg); \
GEN6_READ_FOOTER; \
}
@ -781,7 +781,7 @@ chv_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \
fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
if (fw_engine) \
__force_wake_get(dev_priv, fw_engine); \
__force_wake_auto(dev_priv, fw_engine); \
val = __raw_i915_read##x(dev_priv, reg); \
GEN6_READ_FOOTER; \
}
@ -805,7 +805,7 @@ gen9_read##x(struct drm_i915_private *dev_priv, i915_reg_t reg, bool trace) { \
else \
fw_engine = FORCEWAKE_BLITTER; \
if (fw_engine) \
__force_wake_get(dev_priv, fw_engine); \
__force_wake_auto(dev_priv, fw_engine); \
val = __raw_i915_read##x(dev_priv, reg); \
GEN6_READ_FOOTER; \
}
@ -969,7 +969,7 @@ static void \
gen8_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool trace) { \
GEN6_WRITE_HEADER; \
if (NEEDS_FORCE_WAKE(offset) && !is_gen8_shadowed(dev_priv, reg)) \
__force_wake_get(dev_priv, FORCEWAKE_RENDER); \
__force_wake_auto(dev_priv, FORCEWAKE_RENDER); \
__raw_i915_write##x(dev_priv, reg, val); \
GEN6_WRITE_FOOTER; \
}
@ -989,7 +989,7 @@ chv_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, bool t
else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(offset)) \
fw_engine = FORCEWAKE_RENDER | FORCEWAKE_MEDIA; \
if (fw_engine) \
__force_wake_get(dev_priv, fw_engine); \
__force_wake_auto(dev_priv, fw_engine); \
__raw_i915_write##x(dev_priv, reg, val); \
GEN6_WRITE_FOOTER; \
}
@ -1036,7 +1036,7 @@ gen9_write##x(struct drm_i915_private *dev_priv, i915_reg_t reg, u##x val, \
else \
fw_engine = FORCEWAKE_BLITTER; \
if (fw_engine) \
__force_wake_get(dev_priv, fw_engine); \
__force_wake_auto(dev_priv, fw_engine); \
__raw_i915_write##x(dev_priv, reg, val); \
GEN6_WRITE_FOOTER; \
}
@ -1161,7 +1161,7 @@ static void intel_uncore_fw_domains_init(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
if (INTEL_INFO(dev_priv->dev)->gen <= 5)
if (INTEL_INFO(dev_priv)->gen <= 5)
return;
if (IS_GEN9(dev)) {
@ -1673,6 +1673,25 @@ bool intel_has_gpu_reset(struct drm_device *dev)
return intel_get_gpu_reset(dev) != NULL;
}
int intel_guc_reset(struct drm_i915_private *dev_priv)
{
int ret;
unsigned long irqflags;
if (!i915.enable_guc_submission)
return -EINVAL;
intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL);
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
ret = gen6_hw_domain_reset(dev_priv, GEN9_GRDOM_GUC);
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL);
return ret;
}
bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv)
{
return check_for_unclaimed_mmio(dev_priv);

View File

@ -261,9 +261,6 @@ struct old_child_dev_config {
* versions. Notice that the meaning of the contents contents may still change,
* but at least the offsets are consistent. */
/* Definitions for flags_1 */
#define IBOOST_ENABLE (1<<3)
struct common_child_dev_config {
u16 handle;
u16 device_type;
@ -272,9 +269,18 @@ struct common_child_dev_config {
u8 not_common2[2];
u8 ddc_pin;
u16 edid_ptr;
u8 obsolete;
u8 flags_1;
u8 not_common3[13];
u8 dvo_cfg; /* See DEVICE_CFG_* above */
u8 efp_routed:1;
u8 lane_reversal:1;
u8 lspcon:1;
u8 iboost:1;
u8 hpd_invert:1;
u8 flag_reserved:3;
u8 hdmi_support:1;
u8 dp_support:1;
u8 tmds_support:1;
u8 support_reserved:5;
u8 not_common3[12];
u8 iboost_level;
} __packed;

View File

@ -54,6 +54,25 @@ static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size)
GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
}
static __inline__ void *drm_malloc_gfp(size_t nmemb, size_t size, gfp_t gfp)
{
if (size != 0 && nmemb > SIZE_MAX / size)
return NULL;
if (size * nmemb <= PAGE_SIZE)
return kmalloc(nmemb * size, gfp);
if (gfp & __GFP_RECLAIMABLE) {
void *ptr = kmalloc(nmemb * size,
gfp | __GFP_NOWARN | __GFP_NORETRY);
if (ptr)
return ptr;
}
return __vmalloc(size * nmemb,
gfp | __GFP_HIGHMEM, PAGE_KERNEL);
}
static __inline void drm_free_large(void *ptr)
{
kvfree(ptr);

View File

@ -8,6 +8,7 @@
#include <linux/rbtree.h>
struct vm_area_struct; /* vma defining user mapping in mm_types.h */
struct notifier_block; /* in notifier.h */
/* bits in flags of vmalloc's vm_struct below */
#define VM_IOREMAP 0x00000001 /* ioremap() and friends */
@ -187,4 +188,7 @@ pcpu_free_vm_areas(struct vm_struct **vms, int nr_vms)
#define VMALLOC_TOTAL 0UL
#endif
int register_vmap_purge_notifier(struct notifier_block *nb);
int unregister_vmap_purge_notifier(struct notifier_block *nb);
#endif /* _LINUX_VMALLOC_H */

View File

@ -21,6 +21,7 @@
#include <linux/debugobjects.h>
#include <linux/kallsyms.h>
#include <linux/list.h>
#include <linux/notifier.h>
#include <linux/rbtree.h>
#include <linux/radix-tree.h>
#include <linux/rcupdate.h>
@ -344,6 +345,8 @@ static void __insert_vmap_area(struct vmap_area *va)
static void purge_vmap_area_lazy(void);
static BLOCKING_NOTIFIER_HEAD(vmap_notify_list);
/*
* Allocate a region of KVA of the specified size and alignment, within the
* vstart and vend.
@ -363,6 +366,8 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
BUG_ON(offset_in_page(size));
BUG_ON(!is_power_of_2(align));
might_sleep_if(gfpflags_allow_blocking(gfp_mask));
va = kmalloc_node(sizeof(struct vmap_area),
gfp_mask & GFP_RECLAIM_MASK, node);
if (unlikely(!va))
@ -468,6 +473,16 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
purged = 1;
goto retry;
}
if (gfpflags_allow_blocking(gfp_mask)) {
unsigned long freed = 0;
blocking_notifier_call_chain(&vmap_notify_list, 0, &freed);
if (freed > 0) {
purged = 0;
goto retry;
}
}
if (printk_ratelimit())
pr_warn("vmap allocation for size %lu failed: use vmalloc=<size> to increase size\n",
size);
@ -475,6 +490,18 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
return ERR_PTR(-EBUSY);
}
int register_vmap_purge_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&vmap_notify_list, nb);
}
EXPORT_SYMBOL_GPL(register_vmap_purge_notifier);
int unregister_vmap_purge_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_unregister(&vmap_notify_list, nb);
}
EXPORT_SYMBOL_GPL(unregister_vmap_purge_notifier);
static void __free_vmap_area(struct vmap_area *va)
{
BUG_ON(RB_EMPTY_NODE(&va->rb_node));