aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2015-02-18 08:19:33 -0500
committerLaurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>2015-03-19 06:28:55 -0400
commita5241289c4139f0521b89e34a70f5f998463ae15 (patch)
tree7b5e84d23a3f4c544c9a5c740ccdb299c719bcc7
parent2e96206c4f952295e11c311fbb2a7aa2105024af (diff)
drm: adv7511: Fix nested sleep when reading EDID
The EDID read code waits for the read completion interrupt to occur using wait_event_interruptible(). The condition passed to the macro reads I2C registers. This results in sleeping with the task state set to TASK_INTERRUPTIBLE, triggering a WARN_ON() introduced in commit 8eb23b9f35aae ("sched: Debug nested sleeps"). Fix this by reworking the EDID read code. Instead of checking whether the read is complete through I2C reads, handle the interrupt registers in the interrupt handler and update a new edid_read flag accordingly. As a side effect both the IRQ and polling code paths now process the interrupt sources through the same code path, simplifying the code. Cc: stable@vger.kernel.org Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
-rw-r--r--drivers/gpu/drm/i2c/adv7511.c96
1 files changed, 46 insertions, 50 deletions
diff --git a/drivers/gpu/drm/i2c/adv7511.c b/drivers/gpu/drm/i2c/adv7511.c
index 840895a77825..828b60185016 100644
--- a/drivers/gpu/drm/i2c/adv7511.c
+++ b/drivers/gpu/drm/i2c/adv7511.c
@@ -33,6 +33,7 @@ struct adv7511 {
33 33
34 unsigned int current_edid_segment; 34 unsigned int current_edid_segment;
35 uint8_t edid_buf[256]; 35 uint8_t edid_buf[256];
36 bool edid_read;
36 37
37 wait_queue_head_t wq; 38 wait_queue_head_t wq;
38 struct drm_encoder *encoder; 39 struct drm_encoder *encoder;
@@ -379,69 +380,71 @@ static bool adv7511_hpd(struct adv7511 *adv7511)
379 return false; 380 return false;
380} 381}
381 382
382static irqreturn_t adv7511_irq_handler(int irq, void *devid) 383static int adv7511_irq_process(struct adv7511 *adv7511)
383{
384 struct adv7511 *adv7511 = devid;
385
386 if (adv7511_hpd(adv7511))
387 drm_helper_hpd_irq_event(adv7511->encoder->dev);
388
389 wake_up_all(&adv7511->wq);
390
391 return IRQ_HANDLED;
392}
393
394static unsigned int adv7511_is_interrupt_pending(struct adv7511 *adv7511,
395 unsigned int irq)
396{ 384{
397 unsigned int irq0, irq1; 385 unsigned int irq0, irq1;
398 unsigned int pending;
399 int ret; 386 int ret;
400 387
401 ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0); 388 ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(0), &irq0);
402 if (ret < 0) 389 if (ret < 0)
403 return 0; 390 return ret;
391
404 ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(1), &irq1); 392 ret = regmap_read(adv7511->regmap, ADV7511_REG_INT(1), &irq1);
405 if (ret < 0) 393 if (ret < 0)
406 return 0; 394 return ret;
395
396 regmap_write(adv7511->regmap, ADV7511_REG_INT(0), irq0);
397 regmap_write(adv7511->regmap, ADV7511_REG_INT(1), irq1);
398
399 if (irq0 & ADV7511_INT0_HDP)
400 drm_helper_hpd_irq_event(adv7511->encoder->dev);
401
402 if (irq0 & ADV7511_INT0_EDID_READY || irq1 & ADV7511_INT1_DDC_ERROR) {
403 adv7511->edid_read = true;
407 404
408 pending = (irq1 << 8) | irq0; 405 if (adv7511->i2c_main->irq)
406 wake_up_all(&adv7511->wq);
407 }
409 408
410 return pending & irq; 409 return 0;
411} 410}
412 411
413static int adv7511_wait_for_interrupt(struct adv7511 *adv7511, int irq, 412static irqreturn_t adv7511_irq_handler(int irq, void *devid)
414 int timeout) 413{
414 struct adv7511 *adv7511 = devid;
415 int ret;
416
417 ret = adv7511_irq_process(adv7511);
418 return ret < 0 ? IRQ_NONE : IRQ_HANDLED;
419}
420
421/* -----------------------------------------------------------------------------
422 * EDID retrieval
423 */
424
425static int adv7511_wait_for_edid(struct adv7511 *adv7511, int timeout)
415{ 426{
416 unsigned int pending;
417 int ret; 427 int ret;
418 428
419 if (adv7511->i2c_main->irq) { 429 if (adv7511->i2c_main->irq) {
420 ret = wait_event_interruptible_timeout(adv7511->wq, 430 ret = wait_event_interruptible_timeout(adv7511->wq,
421 adv7511_is_interrupt_pending(adv7511, irq), 431 adv7511->edid_read, msecs_to_jiffies(timeout));
422 msecs_to_jiffies(timeout));
423 if (ret <= 0)
424 return 0;
425 pending = adv7511_is_interrupt_pending(adv7511, irq);
426 } else { 432 } else {
427 if (timeout < 25) 433 for (; timeout > 0; timeout -= 25) {
428 timeout = 25; 434 ret = adv7511_irq_process(adv7511);
429 do { 435 if (ret < 0)
430 pending = adv7511_is_interrupt_pending(adv7511, irq); 436 break;
431 if (pending) 437
438 if (adv7511->edid_read)
432 break; 439 break;
440
433 msleep(25); 441 msleep(25);
434 timeout -= 25; 442 }
435 } while (timeout >= 25);
436 } 443 }
437 444
438 return pending; 445 return adv7511->edid_read ? 0 : -EIO;
439} 446}
440 447
441/* -----------------------------------------------------------------------------
442 * EDID retrieval
443 */
444
445static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block, 448static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block,
446 size_t len) 449 size_t len)
447{ 450{
@@ -463,21 +466,14 @@ static int adv7511_get_edid_block(void *data, u8 *buf, unsigned int block,
463 return ret; 466 return ret;
464 467
465 if (status != 2) { 468 if (status != 2) {
469 adv7511->edid_read = false;
466 regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT, 470 regmap_write(adv7511->regmap, ADV7511_REG_EDID_SEGMENT,
467 block); 471 block);
468 ret = adv7511_wait_for_interrupt(adv7511, 472 ret = adv7511_wait_for_edid(adv7511, 200);
469 ADV7511_INT0_EDID_READY | 473 if (ret < 0)
470 (ADV7511_INT1_DDC_ERROR << 8), 200); 474 return ret;
471
472 if (!(ret & ADV7511_INT0_EDID_READY))
473 return -EIO;
474 } 475 }
475 476
476 regmap_write(adv7511->regmap, ADV7511_REG_INT(0),
477 ADV7511_INT0_EDID_READY);
478 regmap_write(adv7511->regmap, ADV7511_REG_INT(1),
479 ADV7511_INT1_DDC_ERROR);
480
481 /* Break this apart, hopefully more I2C controllers will 477 /* Break this apart, hopefully more I2C controllers will
482 * support 64 byte transfers than 256 byte transfers 478 * support 64 byte transfers than 256 byte transfers
483 */ 479 */