Skip to content

Commit f8c3c0e

Browse files
svenpeter42marcan
authored andcommitted
usb: typec: tipd: Clear interrupts first
Right now the interrupt handler first reads all updated status registers and only then clears the interrupts. It's possible that a duplicate interrupt for a changed register or plug state comes in after the interrupts have been processed but before they have been cleared: * plug is inserted, TPS_REG_INT_PLUG_EVENT is set * TPS_REG_INT_EVENT1 is read * tps6598x_handle_plug_event() has run and registered the plug * plug is removed again, TPS_REG_INT_PLUG_EVENT is set (again) * TPS_REG_INT_CLEAR1 is written, TPS_REG_INT_PLUG_EVENT is cleared We then have no plug connected and no pending interrupt but the tipd core still thinks there is a plug. It's possible to trigger this with e.g. a slightly broken Type-C to USB A converter. Fix this by first clearing the interrupts and only then reading the updated registers. Fixes: 45188f2 ("usb: typec: tipd: Add support for Apple CD321X") Fixes: 0a4c005 ("usb: typec: driver for TI TPS6598x USB Power Delivery controllers") Cc: stable <[email protected]> Signed-off-by: Sven Peter <[email protected]>
1 parent 3b2571b commit f8c3c0e

1 file changed

Lines changed: 11 additions & 13 deletions

File tree

drivers/usb/typec/tipd/core.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -487,24 +487,23 @@ static irqreturn_t cd321x_interrupt(int irq, void *data)
487487
if (!event)
488488
goto err_unlock;
489489

490+
tps6598x_write64(tps, TPS_REG_INT_CLEAR1, event);
491+
490492
if (!tps6598x_read_status(tps, &status))
491-
goto err_clear_ints;
493+
goto err_unlock;
492494

493495
if (event & APPLE_CD_REG_INT_POWER_STATUS_UPDATE)
494496
if (!tps6598x_read_power_status(tps))
495-
goto err_clear_ints;
497+
goto err_unlock;
496498

497499
if (event & APPLE_CD_REG_INT_DATA_STATUS_UPDATE)
498500
if (!tps6598x_read_data_status(tps))
499-
goto err_clear_ints;
501+
goto err_unlock;
500502

501503
/* Handle plug insert or removal */
502504
if (event & APPLE_CD_REG_INT_PLUG_EVENT)
503505
tps6598x_handle_plug_event(tps, status);
504506

505-
err_clear_ints:
506-
tps6598x_write64(tps, TPS_REG_INT_CLEAR1, event);
507-
508507
err_unlock:
509508
mutex_unlock(&tps->lock);
510509

@@ -534,25 +533,24 @@ static irqreturn_t tps6598x_interrupt(int irq, void *data)
534533
if (!(event1 | event2))
535534
goto err_unlock;
536535

536+
tps6598x_write64(tps, TPS_REG_INT_CLEAR1, event1);
537+
tps6598x_write64(tps, TPS_REG_INT_CLEAR2, event2);
538+
537539
if (!tps6598x_read_status(tps, &status))
538-
goto err_clear_ints;
540+
goto err_unlock;
539541

540542
if ((event1 | event2) & TPS_REG_INT_POWER_STATUS_UPDATE)
541543
if (!tps6598x_read_power_status(tps))
542-
goto err_clear_ints;
544+
goto err_unlock;
543545

544546
if ((event1 | event2) & TPS_REG_INT_DATA_STATUS_UPDATE)
545547
if (!tps6598x_read_data_status(tps))
546-
goto err_clear_ints;
548+
goto err_unlock;
547549

548550
/* Handle plug insert or removal */
549551
if ((event1 | event2) & TPS_REG_INT_PLUG_EVENT)
550552
tps6598x_handle_plug_event(tps, status);
551553

552-
err_clear_ints:
553-
tps6598x_write64(tps, TPS_REG_INT_CLEAR1, event1);
554-
tps6598x_write64(tps, TPS_REG_INT_CLEAR2, event2);
555-
556554
err_unlock:
557555
mutex_unlock(&tps->lock);
558556

0 commit comments

Comments
 (0)