Merge branch 'drm-fixes' of git://people.freedesktop.org/~airlied/linux
Pull intel drm fixes from Dave Airlie. * 'drm-fixes' of git://people.freedesktop.org/~airlied/linux: drm/i915: vlv: fix save/restore of GFX_MAX_REQ_COUNT reg drm/i915: Workaround to avoid lite restore with HEAD==TAIL drm/i915: cope with large i2c transfers
This commit is contained in:
commit
1190944f4b
|
@ -1038,7 +1038,7 @@ static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv)
|
|||
s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4);
|
||||
|
||||
s->media_max_req_count = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
|
||||
s->gfx_max_req_count = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT);
|
||||
s->gfx_max_req_count = I915_READ(GEN7_GFX_MAX_REQ_COUNT);
|
||||
|
||||
s->render_hwsp = I915_READ(RENDER_HWS_PGA_GEN7);
|
||||
s->ecochk = I915_READ(GAM_ECOCHK);
|
||||
|
@ -1120,7 +1120,7 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv)
|
|||
I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]);
|
||||
|
||||
I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count);
|
||||
I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->gfx_max_req_count);
|
||||
I915_WRITE(GEN7_GFX_MAX_REQ_COUNT, s->gfx_max_req_count);
|
||||
|
||||
I915_WRITE(RENDER_HWS_PGA_GEN7, s->render_hwsp);
|
||||
I915_WRITE(GAM_ECOCHK, s->ecochk);
|
||||
|
|
|
@ -2377,10 +2377,11 @@ int __i915_add_request(struct intel_engine_cs *ring,
|
|||
ret = ring->add_request(ring);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
request->tail = intel_ring_get_tail(ringbuf);
|
||||
}
|
||||
|
||||
request->head = request_start;
|
||||
request->tail = intel_ring_get_tail(ringbuf);
|
||||
|
||||
/* Whilst this request exists, batch_obj will be on the
|
||||
* active_list, and so will hold the active reference. Only when this
|
||||
|
|
|
@ -1807,6 +1807,7 @@ enum skl_disp_power_wells {
|
|||
#define GMBUS_CYCLE_INDEX (2<<25)
|
||||
#define GMBUS_CYCLE_STOP (4<<25)
|
||||
#define GMBUS_BYTE_COUNT_SHIFT 16
|
||||
#define GMBUS_BYTE_COUNT_MAX 256U
|
||||
#define GMBUS_SLAVE_INDEX_SHIFT 8
|
||||
#define GMBUS_SLAVE_ADDR_SHIFT 1
|
||||
#define GMBUS_SLAVE_READ (1<<0)
|
||||
|
|
|
@ -270,18 +270,17 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv)
|
|||
}
|
||||
|
||||
static int
|
||||
gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
|
||||
u32 gmbus1_index)
|
||||
gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv,
|
||||
unsigned short addr, u8 *buf, unsigned int len,
|
||||
u32 gmbus1_index)
|
||||
{
|
||||
int reg_offset = dev_priv->gpio_mmio_base;
|
||||
u16 len = msg->len;
|
||||
u8 *buf = msg->buf;
|
||||
|
||||
I915_WRITE(GMBUS1 + reg_offset,
|
||||
gmbus1_index |
|
||||
GMBUS_CYCLE_WAIT |
|
||||
(len << GMBUS_BYTE_COUNT_SHIFT) |
|
||||
(msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
|
||||
(addr << GMBUS_SLAVE_ADDR_SHIFT) |
|
||||
GMBUS_SLAVE_READ | GMBUS_SW_RDY);
|
||||
while (len) {
|
||||
int ret;
|
||||
|
@ -303,11 +302,35 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
|
|||
}
|
||||
|
||||
static int
|
||||
gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
|
||||
gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg,
|
||||
u32 gmbus1_index)
|
||||
{
|
||||
u8 *buf = msg->buf;
|
||||
unsigned int rx_size = msg->len;
|
||||
unsigned int len;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
len = min(rx_size, GMBUS_BYTE_COUNT_MAX);
|
||||
|
||||
ret = gmbus_xfer_read_chunk(dev_priv, msg->addr,
|
||||
buf, len, gmbus1_index);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
rx_size -= len;
|
||||
buf += len;
|
||||
} while (rx_size != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv,
|
||||
unsigned short addr, u8 *buf, unsigned int len)
|
||||
{
|
||||
int reg_offset = dev_priv->gpio_mmio_base;
|
||||
u16 len = msg->len;
|
||||
u8 *buf = msg->buf;
|
||||
unsigned int chunk_size = len;
|
||||
u32 val, loop;
|
||||
|
||||
val = loop = 0;
|
||||
|
@ -319,8 +342,8 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
|
|||
I915_WRITE(GMBUS3 + reg_offset, val);
|
||||
I915_WRITE(GMBUS1 + reg_offset,
|
||||
GMBUS_CYCLE_WAIT |
|
||||
(msg->len << GMBUS_BYTE_COUNT_SHIFT) |
|
||||
(msg->addr << GMBUS_SLAVE_ADDR_SHIFT) |
|
||||
(chunk_size << GMBUS_BYTE_COUNT_SHIFT) |
|
||||
(addr << GMBUS_SLAVE_ADDR_SHIFT) |
|
||||
GMBUS_SLAVE_WRITE | GMBUS_SW_RDY);
|
||||
while (len) {
|
||||
int ret;
|
||||
|
@ -337,6 +360,29 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
|
|||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg)
|
||||
{
|
||||
u8 *buf = msg->buf;
|
||||
unsigned int tx_size = msg->len;
|
||||
unsigned int len;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
len = min(tx_size, GMBUS_BYTE_COUNT_MAX);
|
||||
|
||||
ret = gmbus_xfer_write_chunk(dev_priv, msg->addr, buf, len);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
buf += len;
|
||||
tx_size -= len;
|
||||
} while (tx_size != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -393,6 +393,26 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring)
|
|||
}
|
||||
}
|
||||
|
||||
if (IS_GEN8(ring->dev) || IS_GEN9(ring->dev)) {
|
||||
/*
|
||||
* WaIdleLiteRestore: make sure we never cause a lite
|
||||
* restore with HEAD==TAIL
|
||||
*/
|
||||
if (req0 && req0->elsp_submitted) {
|
||||
/*
|
||||
* Apply the wa NOOPS to prevent ring:HEAD == req:TAIL
|
||||
* as we resubmit the request. See gen8_emit_request()
|
||||
* for where we prepare the padding after the end of the
|
||||
* request.
|
||||
*/
|
||||
struct intel_ringbuffer *ringbuf;
|
||||
|
||||
ringbuf = req0->ctx->engine[ring->id].ringbuf;
|
||||
req0->tail += 8;
|
||||
req0->tail &= ringbuf->size - 1;
|
||||
}
|
||||
}
|
||||
|
||||
WARN_ON(req1 && req1->elsp_submitted);
|
||||
|
||||
execlists_submit_contexts(ring, req0->ctx, req0->tail,
|
||||
|
@ -1315,7 +1335,12 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf,
|
|||
u32 cmd;
|
||||
int ret;
|
||||
|
||||
ret = intel_logical_ring_begin(ringbuf, request->ctx, 6);
|
||||
/*
|
||||
* Reserve space for 2 NOOPs at the end of each request to be
|
||||
* used as a workaround for not being allowed to do lite
|
||||
* restore with HEAD==TAIL (WaIdleLiteRestore).
|
||||
*/
|
||||
ret = intel_logical_ring_begin(ringbuf, request->ctx, 8);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
@ -1333,6 +1358,14 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf,
|
|||
intel_logical_ring_emit(ringbuf, MI_NOOP);
|
||||
intel_logical_ring_advance_and_submit(ringbuf, request->ctx, request);
|
||||
|
||||
/*
|
||||
* Here we add two extra NOOPs as padding to avoid
|
||||
* lite restore of a context with HEAD==TAIL.
|
||||
*/
|
||||
intel_logical_ring_emit(ringbuf, MI_NOOP);
|
||||
intel_logical_ring_emit(ringbuf, MI_NOOP);
|
||||
intel_logical_ring_advance(ringbuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue