Remove the system error worker thread and instead have the execution environment worker handle that transition to serialize processing and avoid any possible race conditions during shutdown.
Unified · Split
| @@ -34,6 +34,7 @@ const char * const dev_state_tran_str[DEV_ST_TRANSITION_MAX] = { · 33 unmodified lines | ||
| 34 | 34 | [DEV_ST_TRANSITION_READY] = "READY", |
| 35 | 35 | [DEV_ST_TRANSITION_SBL] = "SBL", |
| 36 | 36 | [DEV_ST_TRANSITION_MISSION_MODE] = "MISSION_MODE", |
| 37 | + [DEV_ST_TRANSITION_SYS_ERR] = "SYS_ERR", | |
| 37 | 38 | }; |
| 38 | 39 | |
| 39 | 40 | const char * const mhi_state_str[MHI_STATE_MAX] = { |
| @@ -834,7 +835,6 @@ int mhi_register_controller(struct mhi_controller *mhi_cntrl, · 794 unmodified lines | ||
| 834 | 835 | spin_lock_init(&mhi_cntrl->transition_lock); |
| 835 | 836 | spin_lock_init(&mhi_cntrl->wlock); |
| 836 | 837 | INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker); |
| 837 | − INIT_WORK(&mhi_cntrl->syserr_worker, mhi_pm_sys_err_worker); | |
| 838 | 838 | init_waitqueue_head(&mhi_cntrl->state_event); |
| 839 | 839 | |
| 840 | 840 | mhi_cmd = mhi_cntrl->mhi_cmd; |
| @@ -386,6 +386,7 @@ enum dev_st_transition { · 385 unmodified lines | ||
| 386 | 386 | DEV_ST_TRANSITION_READY, |
| 387 | 387 | DEV_ST_TRANSITION_SBL, |
| 388 | 388 | DEV_ST_TRANSITION_MISSION_MODE, |
| 389 | + DEV_ST_TRANSITION_SYS_ERR, | |
| 389 | 390 | DEV_ST_TRANSITION_MAX, |
| 390 | 391 | }; |
| 391 | 392 | |
| @@ -587,7 +588,7 @@ enum mhi_ee_type mhi_get_exec_env(struct mhi_controller *mhi_cntrl); · 195 unmodified lines | ||
| 587 | 588 | int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl, |
| 588 | 589 | enum dev_st_transition state); |
| 589 | 590 | void mhi_pm_st_worker(struct work_struct *work); |
| 590 | −void mhi_pm_sys_err_worker(struct work_struct *work); | |
| 591 | +void mhi_pm_sys_err_handler(struct mhi_controller *mhi_cntrl); | |
| 591 | 592 | void mhi_fw_load_worker(struct work_struct *work); |
| 592 | 593 | int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl); |
| 593 | 594 | void mhi_ctrl_ev_task(unsigned long data); |
| @@ -406,7 +406,7 @@ irqreturn_t mhi_intvec_threaded_handler(int irq_number, void *dev) · 405 unmodified lines | ||
| 406 | 406 | if (MHI_IN_PBL(ee)) |
| 407 | 407 | mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_FATAL_ERROR); |
| 408 | 408 | else |
| 409 | − schedule_work(&mhi_cntrl->syserr_worker); | |
| 409 | + mhi_pm_sys_err_handler(mhi_cntrl); | |
| 410 | 410 | } |
| 411 | 411 | |
| 412 | 412 | exit_intvec: |
| @@ -734,7 +734,7 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl, · 321 unmodified lines | ||
| 734 | 734 | MHI_PM_SYS_ERR_DETECT); |
| 735 | 735 | write_unlock_irq(&mhi_cntrl->pm_lock); |
| 736 | 736 | if (new_state == MHI_PM_SYS_ERR_DETECT) |
| 737 | − schedule_work(&mhi_cntrl->syserr_worker); | |
| 737 | + mhi_pm_sys_err_handler(mhi_cntrl); | |
| 738 | 738 | break; |
| 739 | 739 | } |
| 740 | 740 | default: |
| @@ -920,7 +920,7 @@ void mhi_ctrl_ev_task(unsigned long data) · 179 unmodified lines | ||
| 920 | 920 | } |
| 921 | 921 | write_unlock_irq(&mhi_cntrl->pm_lock); |
| 922 | 922 | if (pm_state == MHI_PM_SYS_ERR_DETECT) |
| 923 | − schedule_work(&mhi_cntrl->syserr_worker); | |
| 923 | + mhi_pm_sys_err_handler(mhi_cntrl); | |
| 924 | 924 | } |
| 925 | 925 | } |
| 926 | 926 | |
| @@ -449,19 +449,8 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl, · 448 unmodified lines | ||
| 449 | 449 | to_mhi_pm_state_str(transition_state)); |
| 450 | 450 | |
| 451 | 451 | /* We must notify MHI control driver so it can clean up first */ |
| 452 | − if (transition_state == MHI_PM_SYS_ERR_PROCESS) { | |
| 453 | − /* | |
| 454 | − * If controller supports RDDM, we do not process | |
| 455 | − * SYS error state, instead we will jump directly | |
| 456 | − * to RDDM state | |
| 457 | − */ | |
| 458 | − if (mhi_cntrl->rddm_image) { | |
| 459 | − dev_dbg(dev, | |
| 460 | − "Controller supports RDDM, so skip SYS_ERR\n"); | |
| 461 | − return; | |
| 462 | − } | |
| 452 | + if (transition_state == MHI_PM_SYS_ERR_PROCESS) | |
| 463 | 453 | mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_SYS_ERROR); |
| 464 | − } | |
| 465 | 454 | |
| 466 | 455 | mutex_lock(&mhi_cntrl->pm_mutex); |
| 467 | 456 | write_lock_irq(&mhi_cntrl->pm_lock); |
| @@ -527,7 +516,6 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl, · 59 unmodified lines | ||
| 527 | 516 | mutex_unlock(&mhi_cntrl->pm_mutex); |
| 528 | 517 | dev_dbg(dev, "Waiting for all pending threads to complete\n"); |
| 529 | 518 | wake_up_all(&mhi_cntrl->state_event); |
| 530 | − flush_work(&mhi_cntrl->st_worker); | |
| 531 | 519 | |
| 532 | 520 | dev_dbg(dev, "Reset all active channels and remove MHI devices\n"); |
| 533 | 521 | device_for_each_child(mhi_cntrl->cntrl_dev, NULL, mhi_destroy_device); |
| @@ -607,13 +595,17 @@ int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl, · 73 unmodified lines | ||
| 607 | 595 | } |
| 608 | 596 | |
| 609 | 597 | /* SYS_ERR worker */ |
| 610 | −void mhi_pm_sys_err_worker(struct work_struct *work) | |
| 598 | +void mhi_pm_sys_err_handler(struct mhi_controller *mhi_cntrl) | |
| 611 | 599 | { |
| 612 | − struct mhi_controller *mhi_cntrl = container_of(work, | |
| 613 | − struct mhi_controller, | |
| 614 | − syserr_worker); | |
| 600 | + struct device *dev = &mhi_cntrl->mhi_dev->dev; | |
| 601 | + | |
| 602 | + /* skip if controller supports RDDM */ | |
| 603 | + if (mhi_cntrl->rddm_image) { | |
| 604 | + dev_dbg(dev, "Controller supports RDDM, skip SYS_ERROR\n"); | |
| 605 | + return; | |
| 606 | + } | |
| 615 | 607 | |
| 616 | − mhi_pm_disable_transition(mhi_cntrl, MHI_PM_SYS_ERR_PROCESS); | |
| 608 | + mhi_queue_state_transition(mhi_cntrl, DEV_ST_TRANSITION_SYS_ERR); | |
| 617 | 609 | } |
| 618 | 610 | |
| 619 | 611 | /* Device State Transition worker */ |
| @@ -661,6 +653,10 @@ void mhi_pm_st_worker(struct work_struct *work) · 41 unmodified lines | ||
| 661 | 653 | case DEV_ST_TRANSITION_READY: |
| 662 | 654 | mhi_ready_state_transition(mhi_cntrl); |
| 663 | 655 | break; |
| 656 | + case DEV_ST_TRANSITION_SYS_ERR: | |
| 657 | + mhi_pm_disable_transition | |
| 658 | + (mhi_cntrl, MHI_PM_SYS_ERR_PROCESS); | |
| 659 | + break; | |
| 664 | 660 | default: |
| 665 | 661 | break; |
| 666 | 662 | } |
| @@ -331,7 +331,6 @@ struct mhi_controller_config { · 330 unmodified lines | ||
| 331 | 331 | * @wlock: Lock for protecting device wakeup |
| 332 | 332 | * @mhi_link_info: Device bandwidth info |
| 333 | 333 | * @st_worker: State transition worker |
| 334 | − * @syserr_worker: System error worker | |
| 335 | 334 | * @state_event: State change event |
| 336 | 335 | * @status_cb: CB function to notify power states of the device (required) |
| 337 | 336 | * @wake_get: CB function to assert device wake (optional) |
| @@ -411,7 +410,6 @@ struct mhi_controller { · 73 unmodified lines | ||
| 411 | 410 | spinlock_t wlock; |
| 412 | 411 | struct mhi_link_info mhi_link_info; |
| 413 | 412 | struct work_struct st_worker; |
| 414 | − struct work_struct syserr_worker; | |
| 415 | 413 | wait_queue_head_t state_event; |
| 416 | 414 | |
| 417 | 415 | void (*status_cb)(struct mhi_controller *mhi_cntrl, |