diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-26 20:55:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-26 20:55:26 -0400 |
commit | 1190944f4b12203330ac5ed8784f6c181bf26f2d (patch) | |
tree | 8ef9d1e28d8a552a295d3b3ca134fcc147cbd323 | |
parent | 9f86262dcc573ca195488de9ec6e4d6d74288ad3 (diff) | |
parent | 59fd7e4b0b0769638b5162e56c28bbb027a118d3 (diff) |
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
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_i2c.c | 66 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lrc.c | 35 |
5 files changed, 95 insertions, 14 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c24c3f1ff8a3..c302ffb5a168 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -1038,7 +1038,7 @@ static void vlv_save_gunit_s0ix_state(struct drm_i915_private *dev_priv) | |||
1038 | s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4); | 1038 | s->lra_limits[i] = I915_READ(GEN7_LRA_LIMITS_BASE + i * 4); |
1039 | 1039 | ||
1040 | s->media_max_req_count = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT); | 1040 | s->media_max_req_count = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT); |
1041 | s->gfx_max_req_count = I915_READ(GEN7_MEDIA_MAX_REQ_COUNT); | 1041 | s->gfx_max_req_count = I915_READ(GEN7_GFX_MAX_REQ_COUNT); |
1042 | 1042 | ||
1043 | s->render_hwsp = I915_READ(RENDER_HWS_PGA_GEN7); | 1043 | s->render_hwsp = I915_READ(RENDER_HWS_PGA_GEN7); |
1044 | s->ecochk = I915_READ(GAM_ECOCHK); | 1044 | s->ecochk = I915_READ(GAM_ECOCHK); |
@@ -1120,7 +1120,7 @@ static void vlv_restore_gunit_s0ix_state(struct drm_i915_private *dev_priv) | |||
1120 | I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]); | 1120 | I915_WRITE(GEN7_LRA_LIMITS_BASE + i * 4, s->lra_limits[i]); |
1121 | 1121 | ||
1122 | I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count); | 1122 | I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->media_max_req_count); |
1123 | I915_WRITE(GEN7_MEDIA_MAX_REQ_COUNT, s->gfx_max_req_count); | 1123 | I915_WRITE(GEN7_GFX_MAX_REQ_COUNT, s->gfx_max_req_count); |
1124 | 1124 | ||
1125 | I915_WRITE(RENDER_HWS_PGA_GEN7, s->render_hwsp); | 1125 | I915_WRITE(RENDER_HWS_PGA_GEN7, s->render_hwsp); |
1126 | I915_WRITE(GAM_ECOCHK, s->ecochk); | 1126 | I915_WRITE(GAM_ECOCHK, s->ecochk); |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d07c0b1fb498..53394f998a1f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -2377,10 +2377,11 @@ int __i915_add_request(struct intel_engine_cs *ring, | |||
2377 | ret = ring->add_request(ring); | 2377 | ret = ring->add_request(ring); |
2378 | if (ret) | 2378 | if (ret) |
2379 | return ret; | 2379 | return ret; |
2380 | |||
2381 | request->tail = intel_ring_get_tail(ringbuf); | ||
2380 | } | 2382 | } |
2381 | 2383 | ||
2382 | request->head = request_start; | 2384 | request->head = request_start; |
2383 | request->tail = intel_ring_get_tail(ringbuf); | ||
2384 | 2385 | ||
2385 | /* Whilst this request exists, batch_obj will be on the | 2386 | /* Whilst this request exists, batch_obj will be on the |
2386 | * active_list, and so will hold the active reference. Only when this | 2387 | * active_list, and so will hold the active reference. Only when this |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b522eb6e59a4..3da1af46625c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -1807,6 +1807,7 @@ enum skl_disp_power_wells { | |||
1807 | #define GMBUS_CYCLE_INDEX (2<<25) | 1807 | #define GMBUS_CYCLE_INDEX (2<<25) |
1808 | #define GMBUS_CYCLE_STOP (4<<25) | 1808 | #define GMBUS_CYCLE_STOP (4<<25) |
1809 | #define GMBUS_BYTE_COUNT_SHIFT 16 | 1809 | #define GMBUS_BYTE_COUNT_SHIFT 16 |
1810 | #define GMBUS_BYTE_COUNT_MAX 256U | ||
1810 | #define GMBUS_SLAVE_INDEX_SHIFT 8 | 1811 | #define GMBUS_SLAVE_INDEX_SHIFT 8 |
1811 | #define GMBUS_SLAVE_ADDR_SHIFT 1 | 1812 | #define GMBUS_SLAVE_ADDR_SHIFT 1 |
1812 | #define GMBUS_SLAVE_READ (1<<0) | 1813 | #define GMBUS_SLAVE_READ (1<<0) |
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index b31088a551f2..56e437e31580 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c | |||
@@ -270,18 +270,17 @@ gmbus_wait_idle(struct drm_i915_private *dev_priv) | |||
270 | } | 270 | } |
271 | 271 | ||
272 | static int | 272 | static int |
273 | gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, | 273 | gmbus_xfer_read_chunk(struct drm_i915_private *dev_priv, |
274 | u32 gmbus1_index) | 274 | unsigned short addr, u8 *buf, unsigned int len, |
275 | u32 gmbus1_index) | ||
275 | { | 276 | { |
276 | int reg_offset = dev_priv->gpio_mmio_base; | 277 | int reg_offset = dev_priv->gpio_mmio_base; |
277 | u16 len = msg->len; | ||
278 | u8 *buf = msg->buf; | ||
279 | 278 | ||
280 | I915_WRITE(GMBUS1 + reg_offset, | 279 | I915_WRITE(GMBUS1 + reg_offset, |
281 | gmbus1_index | | 280 | gmbus1_index | |
282 | GMBUS_CYCLE_WAIT | | 281 | GMBUS_CYCLE_WAIT | |
283 | (len << GMBUS_BYTE_COUNT_SHIFT) | | 282 | (len << GMBUS_BYTE_COUNT_SHIFT) | |
284 | (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) | | 283 | (addr << GMBUS_SLAVE_ADDR_SHIFT) | |
285 | GMBUS_SLAVE_READ | GMBUS_SW_RDY); | 284 | GMBUS_SLAVE_READ | GMBUS_SW_RDY); |
286 | while (len) { | 285 | while (len) { |
287 | int ret; | 286 | int ret; |
@@ -303,11 +302,35 @@ gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, | |||
303 | } | 302 | } |
304 | 303 | ||
305 | static int | 304 | static int |
306 | gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) | 305 | gmbus_xfer_read(struct drm_i915_private *dev_priv, struct i2c_msg *msg, |
306 | u32 gmbus1_index) | ||
307 | { | 307 | { |
308 | int reg_offset = dev_priv->gpio_mmio_base; | ||
309 | u16 len = msg->len; | ||
310 | u8 *buf = msg->buf; | 308 | u8 *buf = msg->buf; |
309 | unsigned int rx_size = msg->len; | ||
310 | unsigned int len; | ||
311 | int ret; | ||
312 | |||
313 | do { | ||
314 | len = min(rx_size, GMBUS_BYTE_COUNT_MAX); | ||
315 | |||
316 | ret = gmbus_xfer_read_chunk(dev_priv, msg->addr, | ||
317 | buf, len, gmbus1_index); | ||
318 | if (ret) | ||
319 | return ret; | ||
320 | |||
321 | rx_size -= len; | ||
322 | buf += len; | ||
323 | } while (rx_size != 0); | ||
324 | |||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | static int | ||
329 | gmbus_xfer_write_chunk(struct drm_i915_private *dev_priv, | ||
330 | unsigned short addr, u8 *buf, unsigned int len) | ||
331 | { | ||
332 | int reg_offset = dev_priv->gpio_mmio_base; | ||
333 | unsigned int chunk_size = len; | ||
311 | u32 val, loop; | 334 | u32 val, loop; |
312 | 335 | ||
313 | val = loop = 0; | 336 | val = loop = 0; |
@@ -319,8 +342,8 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) | |||
319 | I915_WRITE(GMBUS3 + reg_offset, val); | 342 | I915_WRITE(GMBUS3 + reg_offset, val); |
320 | I915_WRITE(GMBUS1 + reg_offset, | 343 | I915_WRITE(GMBUS1 + reg_offset, |
321 | GMBUS_CYCLE_WAIT | | 344 | GMBUS_CYCLE_WAIT | |
322 | (msg->len << GMBUS_BYTE_COUNT_SHIFT) | | 345 | (chunk_size << GMBUS_BYTE_COUNT_SHIFT) | |
323 | (msg->addr << GMBUS_SLAVE_ADDR_SHIFT) | | 346 | (addr << GMBUS_SLAVE_ADDR_SHIFT) | |
324 | GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); | 347 | GMBUS_SLAVE_WRITE | GMBUS_SW_RDY); |
325 | while (len) { | 348 | while (len) { |
326 | int ret; | 349 | int ret; |
@@ -337,6 +360,29 @@ gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) | |||
337 | if (ret) | 360 | if (ret) |
338 | return ret; | 361 | return ret; |
339 | } | 362 | } |
363 | |||
364 | return 0; | ||
365 | } | ||
366 | |||
367 | static int | ||
368 | gmbus_xfer_write(struct drm_i915_private *dev_priv, struct i2c_msg *msg) | ||
369 | { | ||
370 | u8 *buf = msg->buf; | ||
371 | unsigned int tx_size = msg->len; | ||
372 | unsigned int len; | ||
373 | int ret; | ||
374 | |||
375 | do { | ||
376 | len = min(tx_size, GMBUS_BYTE_COUNT_MAX); | ||
377 | |||
378 | ret = gmbus_xfer_write_chunk(dev_priv, msg->addr, buf, len); | ||
379 | if (ret) | ||
380 | return ret; | ||
381 | |||
382 | buf += len; | ||
383 | tx_size -= len; | ||
384 | } while (tx_size != 0); | ||
385 | |||
340 | return 0; | 386 | return 0; |
341 | } | 387 | } |
342 | 388 | ||
diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index fcb074bd55dc..09df74b8e917 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c | |||
@@ -393,6 +393,26 @@ static void execlists_context_unqueue(struct intel_engine_cs *ring) | |||
393 | } | 393 | } |
394 | } | 394 | } |
395 | 395 | ||
396 | if (IS_GEN8(ring->dev) || IS_GEN9(ring->dev)) { | ||
397 | /* | ||
398 | * WaIdleLiteRestore: make sure we never cause a lite | ||
399 | * restore with HEAD==TAIL | ||
400 | */ | ||
401 | if (req0 && req0->elsp_submitted) { | ||
402 | /* | ||
403 | * Apply the wa NOOPS to prevent ring:HEAD == req:TAIL | ||
404 | * as we resubmit the request. See gen8_emit_request() | ||
405 | * for where we prepare the padding after the end of the | ||
406 | * request. | ||
407 | */ | ||
408 | struct intel_ringbuffer *ringbuf; | ||
409 | |||
410 | ringbuf = req0->ctx->engine[ring->id].ringbuf; | ||
411 | req0->tail += 8; | ||
412 | req0->tail &= ringbuf->size - 1; | ||
413 | } | ||
414 | } | ||
415 | |||
396 | WARN_ON(req1 && req1->elsp_submitted); | 416 | WARN_ON(req1 && req1->elsp_submitted); |
397 | 417 | ||
398 | execlists_submit_contexts(ring, req0->ctx, req0->tail, | 418 | execlists_submit_contexts(ring, req0->ctx, req0->tail, |
@@ -1315,7 +1335,12 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf, | |||
1315 | u32 cmd; | 1335 | u32 cmd; |
1316 | int ret; | 1336 | int ret; |
1317 | 1337 | ||
1318 | ret = intel_logical_ring_begin(ringbuf, request->ctx, 6); | 1338 | /* |
1339 | * Reserve space for 2 NOOPs at the end of each request to be | ||
1340 | * used as a workaround for not being allowed to do lite | ||
1341 | * restore with HEAD==TAIL (WaIdleLiteRestore). | ||
1342 | */ | ||
1343 | ret = intel_logical_ring_begin(ringbuf, request->ctx, 8); | ||
1319 | if (ret) | 1344 | if (ret) |
1320 | return ret; | 1345 | return ret; |
1321 | 1346 | ||
@@ -1333,6 +1358,14 @@ static int gen8_emit_request(struct intel_ringbuffer *ringbuf, | |||
1333 | intel_logical_ring_emit(ringbuf, MI_NOOP); | 1358 | intel_logical_ring_emit(ringbuf, MI_NOOP); |
1334 | intel_logical_ring_advance_and_submit(ringbuf, request->ctx, request); | 1359 | intel_logical_ring_advance_and_submit(ringbuf, request->ctx, request); |
1335 | 1360 | ||
1361 | /* | ||
1362 | * Here we add two extra NOOPs as padding to avoid | ||
1363 | * lite restore of a context with HEAD==TAIL. | ||
1364 | */ | ||
1365 | intel_logical_ring_emit(ringbuf, MI_NOOP); | ||
1366 | intel_logical_ring_emit(ringbuf, MI_NOOP); | ||
1367 | intel_logical_ring_advance(ringbuf); | ||
1368 | |||
1336 | return 0; | 1369 | return 0; |
1337 | } | 1370 | } |
1338 | 1371 | ||