Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 5059 → Rev 5060

/drivers/video/drm/i915/intel_uncore.c
40,6 → 40,12
 
#define __raw_posting_read(dev_priv__, reg__) (void)__raw_i915_read32(dev_priv__, reg__)
 
static void
assert_device_not_suspended(struct drm_i915_private *dev_priv)
{
WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
"Device suspended\n");
}
 
static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv)
{
83,7 → 89,7
__gen6_gt_wait_for_thread_c0(dev_priv);
}
 
static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
static void __gen7_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
{
__raw_i915_write32(dev_priv, FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff));
/* something from same cacheline, but !FORCEWAKE_MT */
90,7 → 96,7
__raw_posting_read(dev_priv, ECOBUS);
}
 
static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv,
static void __gen7_gt_force_wake_mt_get(struct drm_i915_private *dev_priv,
int fw_engine)
{
u32 forcewake_ack;
136,7 → 142,7
gen6_gt_check_fifodbg(dev_priv);
}
 
static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv,
static void __gen7_gt_force_wake_mt_put(struct drm_i915_private *dev_priv,
int fw_engine)
{
__raw_i915_write32(dev_priv, FORCEWAKE_MT,
143,6 → 149,8
_MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
/* something from same cacheline, but !FORCEWAKE_MT */
__raw_posting_read(dev_priv, ECOBUS);
 
if (IS_GEN7(dev_priv->dev))
gen6_gt_check_fifodbg(dev_priv);
}
 
177,6 → 185,8
{
__raw_i915_write32(dev_priv, FORCEWAKE_VLV,
_MASKED_BIT_DISABLE(0xffff));
__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
_MASKED_BIT_DISABLE(0xffff));
/* something from same cacheline, but !FORCEWAKE_VLV */
__raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV);
}
221,8 → 231,8
}
 
/* WaRsForcewakeWaitTC0:vlv */
if (!IS_CHERRYVIEW(dev_priv->dev))
__gen6_gt_wait_for_thread_c0(dev_priv);
 
}
 
static void __vlv_force_wake_put(struct drm_i915_private *dev_priv,
240,81 → 250,120
__raw_i915_write32(dev_priv, FORCEWAKE_MEDIA_VLV,
_MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
 
/* The below doubles as a POSTING_READ */
/* something from same cacheline, but !FORCEWAKE_VLV */
__raw_posting_read(dev_priv, FORCEWAKE_ACK_VLV);
if (!IS_CHERRYVIEW(dev_priv->dev))
gen6_gt_check_fifodbg(dev_priv);
 
}
 
void vlv_force_wake_get(struct drm_i915_private *dev_priv,
int fw_engine)
static void vlv_force_wake_get(struct drm_i915_private *dev_priv, int fw_engine)
{
unsigned long irqflags;
 
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
if (FORCEWAKE_RENDER & fw_engine) {
if (dev_priv->uncore.fw_rendercount++ == 0)
dev_priv->uncore.funcs.force_wake_get(dev_priv,
FORCEWAKE_RENDER);
}
if (FORCEWAKE_MEDIA & fw_engine) {
if (dev_priv->uncore.fw_mediacount++ == 0)
dev_priv->uncore.funcs.force_wake_get(dev_priv,
FORCEWAKE_MEDIA);
}
 
if (fw_engine & FORCEWAKE_RENDER &&
dev_priv->uncore.fw_rendercount++ != 0)
fw_engine &= ~FORCEWAKE_RENDER;
if (fw_engine & FORCEWAKE_MEDIA &&
dev_priv->uncore.fw_mediacount++ != 0)
fw_engine &= ~FORCEWAKE_MEDIA;
 
if (fw_engine)
dev_priv->uncore.funcs.force_wake_get(dev_priv, fw_engine);
 
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
 
void vlv_force_wake_put(struct drm_i915_private *dev_priv,
int fw_engine)
static void vlv_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
{
unsigned long irqflags;
 
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
if (FORCEWAKE_RENDER & fw_engine) {
WARN_ON(dev_priv->uncore.fw_rendercount == 0);
if (--dev_priv->uncore.fw_rendercount == 0)
dev_priv->uncore.funcs.force_wake_put(dev_priv,
FORCEWAKE_RENDER);
if (fw_engine & FORCEWAKE_RENDER) {
WARN_ON(!dev_priv->uncore.fw_rendercount);
if (--dev_priv->uncore.fw_rendercount != 0)
fw_engine &= ~FORCEWAKE_RENDER;
}
 
if (FORCEWAKE_MEDIA & fw_engine) {
WARN_ON(dev_priv->uncore.fw_mediacount == 0);
if (--dev_priv->uncore.fw_mediacount == 0)
dev_priv->uncore.funcs.force_wake_put(dev_priv,
FORCEWAKE_MEDIA);
if (fw_engine & FORCEWAKE_MEDIA) {
WARN_ON(!dev_priv->uncore.fw_mediacount);
if (--dev_priv->uncore.fw_mediacount != 0)
fw_engine &= ~FORCEWAKE_MEDIA;
}
 
if (fw_engine)
dev_priv->uncore.funcs.force_wake_put(dev_priv, fw_engine);
 
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
 
static void gen6_force_wake_work(struct work_struct *work)
static void gen6_force_wake_timer(unsigned long arg)
{
struct drm_i915_private *dev_priv =
container_of(work, typeof(*dev_priv), uncore.force_wake_work.work);
struct drm_i915_private *dev_priv = (void *)arg;
unsigned long irqflags;
 
assert_device_not_suspended(dev_priv);
 
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
WARN_ON(!dev_priv->uncore.forcewake_count);
 
if (--dev_priv->uncore.forcewake_count == 0)
dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 
intel_runtime_pm_put(dev_priv);
}
 
static void intel_uncore_forcewake_reset(struct drm_device *dev)
void intel_uncore_forcewake_reset(struct drm_device *dev, bool restore)
{
struct drm_i915_private *dev_priv = dev->dev_private;
unsigned long irqflags;
 
if (IS_VALLEYVIEW(dev)) {
if (del_timer_sync(&dev_priv->uncore.force_wake_timer))
gen6_force_wake_timer((unsigned long)dev_priv);
 
/* Hold uncore.lock across reset to prevent any register access
* with forcewake not set correctly
*/
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
if (IS_VALLEYVIEW(dev))
vlv_force_wake_reset(dev_priv);
} else if (INTEL_INFO(dev)->gen >= 6) {
else if (IS_GEN6(dev) || IS_GEN7(dev))
__gen6_gt_force_wake_reset(dev_priv);
if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
__gen6_gt_force_wake_mt_reset(dev_priv);
 
if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev) || IS_GEN8(dev))
__gen7_gt_force_wake_mt_reset(dev_priv);
 
if (restore) { /* If reset with a user forcewake, try to restore */
unsigned fw = 0;
 
if (IS_VALLEYVIEW(dev)) {
if (dev_priv->uncore.fw_rendercount)
fw |= FORCEWAKE_RENDER;
 
if (dev_priv->uncore.fw_mediacount)
fw |= FORCEWAKE_MEDIA;
} else {
if (dev_priv->uncore.forcewake_count)
fw = FORCEWAKE_ALL;
}
 
if (fw)
dev_priv->uncore.funcs.force_wake_get(dev_priv, fw);
 
if (IS_GEN6(dev) || IS_GEN7(dev))
dev_priv->uncore.fifo_count =
__raw_i915_read32(dev_priv, GTFIFOCTL) &
GT_FIFO_FREE_ENTRIES_MASK;
}
 
void intel_uncore_early_sanitize(struct drm_device *dev)
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
}
 
void intel_uncore_early_sanitize(struct drm_device *dev, bool restore_forcewake)
{
struct drm_i915_private *dev_priv = dev->dev_private;
 
321,7 → 370,7
if (HAS_FPGA_DBG_UNCLAIMED(dev))
__raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
 
if (IS_HASWELL(dev) &&
if ((IS_HASWELL(dev) || IS_BROADWELL(dev)) &&
(__raw_i915_read32(dev_priv, HSW_EDRAM_PRESENT) == 1)) {
/* The docs do not explain exactly how the calculation can be
* made. It is somewhat guessable, but for now, it's always
337,30 → 386,14
__raw_i915_write32(dev_priv, GTFIFODBG,
__raw_i915_read32(dev_priv, GTFIFODBG));
 
intel_uncore_forcewake_reset(dev);
intel_uncore_forcewake_reset(dev, restore_forcewake);
}
 
void intel_uncore_sanitize(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 reg_val;
 
/* BIOS often leaves RC6 enabled, but disable it for hw init */
intel_disable_gt_powersave(dev);
 
/* Turn off power gate, require especially for the BIOS less system */
if (IS_VALLEYVIEW(dev)) {
 
mutex_lock(&dev_priv->rps.hw_lock);
reg_val = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS);
 
if (reg_val & (RENDER_PWRGT | MEDIA_PWRGT | DISP2D_PWRGT))
vlv_punit_write(dev_priv, PUNIT_REG_PWRGT_CTRL, 0x0);
 
mutex_unlock(&dev_priv->rps.hw_lock);
 
}
}
 
/*
* Generally this is called implicitly by the register read function. However,
393,31 → 426,84
void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv, int fw_engine)
{
unsigned long irqflags;
bool delayed = false;
 
if (!dev_priv->uncore.funcs.force_wake_put)
return;
 
/* Redirect to VLV specific routine */
if (IS_VALLEYVIEW(dev_priv->dev))
return vlv_force_wake_put(dev_priv, fw_engine);
if (IS_VALLEYVIEW(dev_priv->dev)) {
vlv_force_wake_put(dev_priv, fw_engine);
goto out;
}
 
 
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
WARN_ON(!dev_priv->uncore.forcewake_count);
 
if (--dev_priv->uncore.forcewake_count == 0) {
dev_priv->uncore.forcewake_count++;
mod_delayed_work(dev_priv->wq,
&dev_priv->uncore.force_wake_work,
1);
delayed = true;
// mod_timer_pinned(&dev_priv->uncore.force_wake_timer,
// GetTimerTicks() + 1);
}
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
 
out:
if (!delayed)
intel_runtime_pm_put(dev_priv);
}
 
void assert_force_wake_inactive(struct drm_i915_private *dev_priv)
{
if (!dev_priv->uncore.funcs.force_wake_get)
return;
 
WARN_ON(dev_priv->uncore.forcewake_count > 0);
}
 
/* We give fast paths for the really cool registers */
#define NEEDS_FORCE_WAKE(dev_priv, reg) \
((reg) < 0x40000 && (reg) != FORCEWAKE)
 
#define REG_RANGE(reg, start, end) ((reg) >= (start) && (reg) < (end))
 
#define FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg) \
(REG_RANGE((reg), 0x2000, 0x4000) || \
REG_RANGE((reg), 0x5000, 0x8000) || \
REG_RANGE((reg), 0xB000, 0x12000) || \
REG_RANGE((reg), 0x2E000, 0x30000))
 
#define FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg) \
(REG_RANGE((reg), 0x12000, 0x14000) || \
REG_RANGE((reg), 0x22000, 0x24000) || \
REG_RANGE((reg), 0x30000, 0x40000))
 
#define FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg) \
(REG_RANGE((reg), 0x2000, 0x4000) || \
REG_RANGE((reg), 0x5000, 0x8000) || \
REG_RANGE((reg), 0x8300, 0x8500) || \
REG_RANGE((reg), 0xB000, 0xC000) || \
REG_RANGE((reg), 0xE000, 0xE800))
 
#define FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg) \
(REG_RANGE((reg), 0x8800, 0x8900) || \
REG_RANGE((reg), 0xD000, 0xD800) || \
REG_RANGE((reg), 0x12000, 0x14000) || \
REG_RANGE((reg), 0x1A000, 0x1C000) || \
REG_RANGE((reg), 0x1E800, 0x1EA00) || \
REG_RANGE((reg), 0x30000, 0x40000))
 
#define FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg) \
(REG_RANGE((reg), 0x4000, 0x5000) || \
REG_RANGE((reg), 0x8000, 0x8300) || \
REG_RANGE((reg), 0x8500, 0x8600) || \
REG_RANGE((reg), 0x9000, 0xB000) || \
REG_RANGE((reg), 0xC000, 0xC800) || \
REG_RANGE((reg), 0xF000, 0x10000) || \
REG_RANGE((reg), 0x14000, 0x14400) || \
REG_RANGE((reg), 0x22000, 0x24000))
 
static void
ilk_dummy_write(struct drm_i915_private *dev_priv)
{
428,34 → 514,38
}
 
static void
hsw_unclaimed_reg_clear(struct drm_i915_private *dev_priv, u32 reg)
hsw_unclaimed_reg_debug(struct drm_i915_private *dev_priv, u32 reg, bool read,
bool before)
{
const char *op = read ? "reading" : "writing to";
const char *when = before ? "before" : "after";
 
if (!i915.mmio_debug)
return;
 
if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) {
DRM_ERROR("Unknown unclaimed register before writing to %x\n",
reg);
WARN(1, "Unclaimed register detected %s %s register 0x%x\n",
when, op, reg);
__raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
}
}
 
static void
hsw_unclaimed_reg_check(struct drm_i915_private *dev_priv, u32 reg)
hsw_unclaimed_reg_detect(struct drm_i915_private *dev_priv)
{
if (i915.mmio_debug)
return;
 
if (__raw_i915_read32(dev_priv, FPGA_DBG) & FPGA_DBG_RM_NOCLAIM) {
DRM_ERROR("Unclaimed write to %x\n", reg);
DRM_ERROR("Unclaimed register detected. Please use the i915.mmio_debug=1 to debug this problem.");
__raw_i915_write32(dev_priv, FPGA_DBG, FPGA_DBG_RM_NOCLAIM);
}
}
 
static void
assert_device_not_suspended(struct drm_i915_private *dev_priv)
{
WARN(HAS_RUNTIME_PM(dev_priv->dev) && dev_priv->pm.suspended,
"Device suspended\n");
}
 
#define REG_READ_HEADER(x) \
unsigned long irqflags; \
u##x val = 0; \
assert_device_not_suspended(dev_priv); \
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
 
#define REG_READ_FOOTER \
484,17 → 574,18
static u##x \
gen6_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
REG_READ_HEADER(x); \
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
if (dev_priv->uncore.forcewake_count == 0) \
hsw_unclaimed_reg_debug(dev_priv, reg, true, true); \
if (dev_priv->uncore.forcewake_count == 0 && \
NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
dev_priv->uncore.funcs.force_wake_get(dev_priv, \
FORCEWAKE_ALL); \
val = __raw_i915_read##x(dev_priv, reg); \
if (dev_priv->uncore.forcewake_count == 0) \
dev_priv->uncore.funcs.force_wake_put(dev_priv, \
FORCEWAKE_ALL); \
} else { \
val = __raw_i915_read##x(dev_priv, reg); \
} \
hsw_unclaimed_reg_debug(dev_priv, reg, true, false); \
REG_READ_FOOTER; \
}
 
502,31 → 593,51
static u##x \
vlv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
unsigned fwengine = 0; \
unsigned *fwcount; \
REG_READ_HEADER(x); \
if (FORCEWAKE_VLV_RENDER_RANGE_OFFSET(reg)) { \
if (dev_priv->uncore.fw_rendercount == 0) \
fwengine = FORCEWAKE_RENDER; \
fwcount = &dev_priv->uncore.fw_rendercount; \
} else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)) { \
if (dev_priv->uncore.fw_mediacount == 0) \
fwengine = FORCEWAKE_MEDIA; \
} \
else if (FORCEWAKE_VLV_MEDIA_RANGE_OFFSET(reg)) { \
if (fwengine) \
dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \
val = __raw_i915_read##x(dev_priv, reg); \
if (fwengine) \
dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \
REG_READ_FOOTER; \
}
 
#define __chv_read(x) \
static u##x \
chv_read##x(struct drm_i915_private *dev_priv, off_t reg, bool trace) { \
unsigned fwengine = 0; \
REG_READ_HEADER(x); \
if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) { \
if (dev_priv->uncore.fw_rendercount == 0) \
fwengine = FORCEWAKE_RENDER; \
} else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) { \
if (dev_priv->uncore.fw_mediacount == 0) \
fwengine = FORCEWAKE_MEDIA; \
fwcount = &dev_priv->uncore.fw_mediacount; \
} else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) { \
if (dev_priv->uncore.fw_rendercount == 0) \
fwengine |= FORCEWAKE_RENDER; \
if (dev_priv->uncore.fw_mediacount == 0) \
fwengine |= FORCEWAKE_MEDIA; \
} \
if (fwengine != 0) { \
if ((*fwcount)++ == 0) \
(dev_priv)->uncore.funcs.force_wake_get(dev_priv, \
fwengine); \
if (fwengine) \
dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \
val = __raw_i915_read##x(dev_priv, reg); \
if (--(*fwcount) == 0) \
(dev_priv)->uncore.funcs.force_wake_put(dev_priv, \
fwengine); \
} else { \
val = __raw_i915_read##x(dev_priv, reg); \
} \
if (fwengine) \
dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \
REG_READ_FOOTER; \
}
 
 
__chv_read(8)
__chv_read(16)
__chv_read(32)
__chv_read(64)
__vlv_read(8)
__vlv_read(16)
__vlv_read(32)
544,6 → 655,7
__gen4_read(32)
__gen4_read(64)
 
#undef __chv_read
#undef __vlv_read
#undef __gen6_read
#undef __gen5_read
554,6 → 666,7
#define REG_WRITE_HEADER \
unsigned long irqflags; \
trace_i915_reg_rw(true, reg, val, sizeof(val), trace); \
assert_device_not_suspended(dev_priv); \
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags)
 
#define REG_WRITE_FOOTER \
584,7 → 697,6
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
} \
assert_device_not_suspended(dev_priv); \
__raw_i915_write##x(dev_priv, reg, val); \
if (unlikely(__fifo_ret)) { \
gen6_gt_check_fifodbg(dev_priv); \
600,13 → 712,13
if (NEEDS_FORCE_WAKE((dev_priv), (reg))) { \
__fifo_ret = __gen6_gt_wait_for_fifo(dev_priv); \
} \
assert_device_not_suspended(dev_priv); \
hsw_unclaimed_reg_clear(dev_priv, reg); \
hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \
__raw_i915_write##x(dev_priv, reg, val); \
if (unlikely(__fifo_ret)) { \
gen6_gt_check_fifodbg(dev_priv); \
} \
hsw_unclaimed_reg_check(dev_priv, reg); \
hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \
hsw_unclaimed_reg_detect(dev_priv); \
REG_WRITE_FOOTER; \
}
 
634,20 → 746,56
#define __gen8_write(x) \
static void \
gen8_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
bool __needs_put = reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg); \
REG_WRITE_HEADER; \
if (__needs_put) { \
hsw_unclaimed_reg_debug(dev_priv, reg, false, true); \
if (reg < 0x40000 && !is_gen8_shadowed(dev_priv, reg)) { \
if (dev_priv->uncore.forcewake_count == 0) \
dev_priv->uncore.funcs.force_wake_get(dev_priv, \
FORCEWAKE_ALL); \
} \
__raw_i915_write##x(dev_priv, reg, val); \
if (__needs_put) { \
if (dev_priv->uncore.forcewake_count == 0) \
dev_priv->uncore.funcs.force_wake_put(dev_priv, \
FORCEWAKE_ALL); \
} else { \
__raw_i915_write##x(dev_priv, reg, val); \
} \
hsw_unclaimed_reg_debug(dev_priv, reg, false, false); \
hsw_unclaimed_reg_detect(dev_priv); \
REG_WRITE_FOOTER; \
}
 
#define __chv_write(x) \
static void \
chv_write##x(struct drm_i915_private *dev_priv, off_t reg, u##x val, bool trace) { \
unsigned fwengine = 0; \
bool shadowed = is_gen8_shadowed(dev_priv, reg); \
REG_WRITE_HEADER; \
if (!shadowed) { \
if (FORCEWAKE_CHV_RENDER_RANGE_OFFSET(reg)) { \
if (dev_priv->uncore.fw_rendercount == 0) \
fwengine = FORCEWAKE_RENDER; \
} else if (FORCEWAKE_CHV_MEDIA_RANGE_OFFSET(reg)) { \
if (dev_priv->uncore.fw_mediacount == 0) \
fwengine = FORCEWAKE_MEDIA; \
} else if (FORCEWAKE_CHV_COMMON_RANGE_OFFSET(reg)) { \
if (dev_priv->uncore.fw_rendercount == 0) \
fwengine |= FORCEWAKE_RENDER; \
if (dev_priv->uncore.fw_mediacount == 0) \
fwengine |= FORCEWAKE_MEDIA; \
} \
} \
if (fwengine) \
dev_priv->uncore.funcs.force_wake_get(dev_priv, fwengine); \
__raw_i915_write##x(dev_priv, reg, val); \
if (fwengine) \
dev_priv->uncore.funcs.force_wake_put(dev_priv, fwengine); \
REG_WRITE_FOOTER; \
}
 
__chv_write(8)
__chv_write(16)
__chv_write(32)
__chv_write(64)
__gen8_write(8)
__gen8_write(16)
__gen8_write(32)
669,6 → 817,7
__gen4_write(32)
__gen4_write(64)
 
#undef __chv_write
#undef __gen8_write
#undef __hsw_write
#undef __gen6_write
681,15 → 830,17
{
struct drm_i915_private *dev_priv = dev->dev_private;
 
INIT_DELAYED_WORK(&dev_priv->uncore.force_wake_work,
gen6_force_wake_work);
setup_timer(&dev_priv->uncore.force_wake_timer,
gen6_force_wake_timer, (unsigned long)dev_priv);
 
intel_uncore_early_sanitize(dev, false);
 
if (IS_VALLEYVIEW(dev)) {
dev_priv->uncore.funcs.force_wake_get = __vlv_force_wake_get;
dev_priv->uncore.funcs.force_wake_put = __vlv_force_wake_put;
} else if (IS_HASWELL(dev) || IS_GEN8(dev)) {
dev_priv->uncore.funcs.force_wake_get = __gen6_gt_force_wake_mt_get;
dev_priv->uncore.funcs.force_wake_put = __gen6_gt_force_wake_mt_put;
dev_priv->uncore.funcs.force_wake_get = __gen7_gt_force_wake_mt_get;
dev_priv->uncore.funcs.force_wake_put = __gen7_gt_force_wake_mt_put;
} else if (IS_IVYBRIDGE(dev)) {
u32 ecobus;
 
703,16 → 854,16
* forcewake being disabled.
*/
mutex_lock(&dev->struct_mutex);
__gen6_gt_force_wake_mt_get(dev_priv, FORCEWAKE_ALL);
__gen7_gt_force_wake_mt_get(dev_priv, FORCEWAKE_ALL);
ecobus = __raw_i915_read32(dev_priv, ECOBUS);
__gen6_gt_force_wake_mt_put(dev_priv, FORCEWAKE_ALL);
__gen7_gt_force_wake_mt_put(dev_priv, FORCEWAKE_ALL);
mutex_unlock(&dev->struct_mutex);
 
if (ecobus & FORCEWAKE_MT_ENABLE) {
dev_priv->uncore.funcs.force_wake_get =
__gen6_gt_force_wake_mt_get;
__gen7_gt_force_wake_mt_get;
dev_priv->uncore.funcs.force_wake_put =
__gen6_gt_force_wake_mt_put;
__gen7_gt_force_wake_mt_put;
} else {
DRM_INFO("No MT forcewake available on Ivybridge, this can result in issues\n");
DRM_INFO("when using vblank-synced partial screen updates.\n");
730,6 → 881,17
 
switch (INTEL_INFO(dev)->gen) {
default:
if (IS_CHERRYVIEW(dev)) {
dev_priv->uncore.funcs.mmio_writeb = chv_write8;
dev_priv->uncore.funcs.mmio_writew = chv_write16;
dev_priv->uncore.funcs.mmio_writel = chv_write32;
dev_priv->uncore.funcs.mmio_writeq = chv_write64;
dev_priv->uncore.funcs.mmio_readb = chv_read8;
dev_priv->uncore.funcs.mmio_readw = chv_read16;
dev_priv->uncore.funcs.mmio_readl = chv_read32;
dev_priv->uncore.funcs.mmio_readq = chv_read64;
 
} else {
dev_priv->uncore.funcs.mmio_writeb = gen8_write8;
dev_priv->uncore.funcs.mmio_writew = gen8_write16;
dev_priv->uncore.funcs.mmio_writel = gen8_write32;
738,6 → 900,7
dev_priv->uncore.funcs.mmio_readw = gen6_read16;
dev_priv->uncore.funcs.mmio_readl = gen6_read32;
dev_priv->uncore.funcs.mmio_readq = gen6_read64;
}
break;
case 7:
case 6:
792,20 → 955,20
 
void intel_uncore_fini(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
 
// flush_delayed_work(&dev_priv->uncore.force_wake_work);
 
/* Paranoia: make sure we have disabled everything before we exit. */
intel_uncore_sanitize(dev);
intel_uncore_forcewake_reset(dev, false);
}
 
#define GEN_RANGE(l, h) GENMASK(h, l)
 
static const struct register_whitelist {
uint64_t offset;
uint32_t size;
uint32_t gen_bitmask; /* support gens, 0x10 for 4, 0x30 for 4 and 5, etc. */
/* supported gens, 0x10 for 4, 0x30 for 4 and 5, etc. */
uint32_t gen_bitmask;
} whitelist[] = {
{ RING_TIMESTAMP(RENDER_RING_BASE), 8, 0x1F0 },
{ RING_TIMESTAMP(RENDER_RING_BASE), 8, GEN_RANGE(4, 8) },
};
 
int i915_reg_read_ioctl(struct drm_device *dev,
814,7 → 977,7
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_reg_read *reg = data;
struct register_whitelist const *entry = whitelist;
int i;
int i, ret = 0;
 
for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) {
if (entry->offset == reg->offset &&
840,10 → 1003,12
break;
default:
WARN_ON(1);
return -EINVAL;
ret = -EINVAL;
goto out;
}
 
return 0;
out:
return ret;
}
 
int i915_get_reset_stats_ioctl(struct drm_device *dev,
852,23 → 1017,22
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_reset_stats *args = data;
struct i915_ctx_hang_stats *hs;
struct intel_context *ctx;
int ret;
 
if (args->flags || args->pad)
return -EINVAL;
 
if (args->ctx_id == DEFAULT_CONTEXT_ID)
return -EPERM;
 
ret = mutex_lock_interruptible(&dev->struct_mutex);
if (ret)
return ret;
 
hs = i915_gem_context_get_hang_stats(dev, file, args->ctx_id);
if (IS_ERR(hs)) {
ctx = i915_gem_context_get(file->driver_priv, args->ctx_id);
if (IS_ERR(ctx)) {
mutex_unlock(&dev->struct_mutex);
return PTR_ERR(hs);
return PTR_ERR(ctx);
}
hs = &ctx->hang_stats;
 
args->reset_count = i915_reset_count(&dev_priv->gpu_error);
 
891,6 → 1055,9
{
int ret;
 
/* FIXME: i965g/gm need a display save/restore for gpu reset. */
return -ENODEV;
 
/*
* Set the domains we want to reset (GRDOM/bits 2 and 3) as
* well as the reset bit (GR/bit 0). Setting the GR bit
902,7 → 1069,6
if (ret)
return ret;
 
/* We can't reset render&media without also resetting display ... */
pci_write_config_byte(dev->pdev, I965_GDRST,
GRDOM_MEDIA | GRDOM_RESET_ENABLE);
 
915,26 → 1081,58
return 0;
}
 
static int g4x_do_reset(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
 
pci_write_config_byte(dev->pdev, I965_GDRST,
GRDOM_RENDER | GRDOM_RESET_ENABLE);
ret = wait_for(i965_reset_complete(dev), 500);
if (ret)
return ret;
 
/* WaVcpClkGateDisableForMediaReset:ctg,elk */
I915_WRITE(VDECCLK_GATE_D, I915_READ(VDECCLK_GATE_D) | VCP_UNIT_CLOCK_GATE_DISABLE);
POSTING_READ(VDECCLK_GATE_D);
 
pci_write_config_byte(dev->pdev, I965_GDRST,
GRDOM_MEDIA | GRDOM_RESET_ENABLE);
ret = wait_for(i965_reset_complete(dev), 500);
if (ret)
return ret;
 
/* WaVcpClkGateDisableForMediaReset:ctg,elk */
I915_WRITE(VDECCLK_GATE_D, I915_READ(VDECCLK_GATE_D) & ~VCP_UNIT_CLOCK_GATE_DISABLE);
POSTING_READ(VDECCLK_GATE_D);
 
pci_write_config_byte(dev->pdev, I965_GDRST, 0);
 
return 0;
}
 
static int ironlake_do_reset(struct drm_device *dev)
{
struct drm_i915_private *dev_priv = dev->dev_private;
u32 gdrst;
int ret;
 
gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
gdrst &= ~GRDOM_MASK;
I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
gdrst | GRDOM_RENDER | GRDOM_RESET_ENABLE);
ret = wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
ILK_GRDOM_RENDER | ILK_GRDOM_RESET_ENABLE);
ret = wait_for((I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) &
ILK_GRDOM_RESET_ENABLE) == 0, 500);
if (ret)
return ret;
 
/* We can't reset render&media without also resetting display ... */
gdrst = I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR);
gdrst &= ~GRDOM_MASK;
I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR,
gdrst | GRDOM_MEDIA | GRDOM_RESET_ENABLE);
return wait_for(I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) & 0x1, 500);
ILK_GRDOM_MEDIA | ILK_GRDOM_RESET_ENABLE);
ret = wait_for((I915_READ(MCHBAR_MIRROR_BASE + ILK_GDSR) &
ILK_GRDOM_RESET_ENABLE) == 0, 500);
if (ret)
return ret;
 
I915_WRITE(MCHBAR_MIRROR_BASE + ILK_GDSR, 0);
 
return 0;
}
 
static int gen6_do_reset(struct drm_device *dev)
941,13 → 1139,7
{
struct drm_i915_private *dev_priv = dev->dev_private;
int ret;
unsigned long irqflags;
 
/* Hold uncore.lock across reset to prevent any register access
* with forcewake not set correctly
*/
spin_lock_irqsave(&dev_priv->uncore.lock, irqflags);
 
/* Reset the chip */
 
/* GEN6_GDRST is not in the gt power well, no need to check
959,32 → 1151,24
/* Spin waiting for the device to ack the reset request */
ret = wait_for((__raw_i915_read32(dev_priv, GEN6_GDRST) & GEN6_GRDOM_FULL) == 0, 500);
 
intel_uncore_forcewake_reset(dev);
intel_uncore_forcewake_reset(dev, true);
 
/* If reset with a user forcewake, try to restore, otherwise turn it off */
if (dev_priv->uncore.forcewake_count)
dev_priv->uncore.funcs.force_wake_get(dev_priv, FORCEWAKE_ALL);
else
dev_priv->uncore.funcs.force_wake_put(dev_priv, FORCEWAKE_ALL);
 
/* Restore fifo count */
dev_priv->uncore.fifo_count = __raw_i915_read32(dev_priv, GTFIFOCTL) & GT_FIFO_FREE_ENTRIES_MASK;
 
spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags);
return ret;
}
 
int intel_gpu_reset(struct drm_device *dev)
{
switch (INTEL_INFO(dev)->gen) {
case 8:
case 7:
case 6: return gen6_do_reset(dev);
case 5: return ironlake_do_reset(dev);
case 4: return i965_do_reset(dev);
default: return -ENODEV;
if (INTEL_INFO(dev)->gen >= 6)
return gen6_do_reset(dev);
else if (IS_GEN5(dev))
return ironlake_do_reset(dev);
else if (IS_G4X(dev))
return g4x_do_reset(dev);
else if (IS_GEN4(dev))
return i965_do_reset(dev);
else
return -ENODEV;
}
}
 
void intel_uncore_check_errors(struct drm_device *dev)
{