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 | [DEV_ST_TRANSITION_READY] = "READY", | 34 | [DEV_ST_TRANSITION_READY] = "READY", |
| 35 | [DEV_ST_TRANSITION_SBL] = "SBL", | 35 | [DEV_ST_TRANSITION_SBL] = "SBL", |
| 36 | [DEV_ST_TRANSITION_MISSION_MODE] = "MISSION_MODE", | 36 | [DEV_ST_TRANSITION_MISSION_MODE] = "MISSION_MODE", |
| 37 | [DEV_ST_TRANSITION_SYS_ERR] = "SYS_ERR", | ||
| 37 | }; | 38 | }; |
| 38 | 39 | ||
| 39 | const char * const mhi_state_str[MHI_STATE_MAX] = { | 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 | spin_lock_init(&mhi_cntrl->transition_lock); | 835 | spin_lock_init(&mhi_cntrl->transition_lock); |
| 835 | spin_lock_init(&mhi_cntrl->wlock); | 836 | spin_lock_init(&mhi_cntrl->wlock); |
| 836 | INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker); | 837 | INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker); |
| 837 | INIT_WORK(&mhi_cntrl->syserr_worker, mhi_pm_sys_err_worker); | ||
| 838 | init_waitqueue_head(&mhi_cntrl->state_event); | 838 | init_waitqueue_head(&mhi_cntrl->state_event); |
| 839 | 839 | ||
| 840 | mhi_cmd = mhi_cntrl->mhi_cmd; | 840 | mhi_cmd = mhi_cntrl->mhi_cmd; |
| @@ -386,6 +386,7 @@ enum dev_st_transition { · 385 unmodified lines | |||
| 386 | DEV_ST_TRANSITION_READY, | 386 | DEV_ST_TRANSITION_READY, |
| 387 | DEV_ST_TRANSITION_SBL, | 387 | DEV_ST_TRANSITION_SBL, |
| 388 | DEV_ST_TRANSITION_MISSION_MODE, | 388 | DEV_ST_TRANSITION_MISSION_MODE, |
| 389 | DEV_ST_TRANSITION_SYS_ERR, | ||
| 389 | DEV_ST_TRANSITION_MAX, | 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 | int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl, | 588 | int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl, |
| 588 | enum dev_st_transition state); | 589 | enum dev_st_transition state); |
| 589 | void mhi_pm_st_worker(struct work_struct *work); | 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 | void mhi_fw_load_worker(struct work_struct *work); | 592 | void mhi_fw_load_worker(struct work_struct *work); |
| 592 | int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl); | 593 | int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl); |
| 593 | void mhi_ctrl_ev_task(unsigned long data); | 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 | if (MHI_IN_PBL(ee)) | 406 | if (MHI_IN_PBL(ee)) |
| 407 | mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_FATAL_ERROR); | 407 | mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_FATAL_ERROR); |
| 408 | else | 408 | else |
| 409 | schedule_work(&mhi_cntrl->syserr_worker); | 409 | mhi_pm_sys_err_handler(mhi_cntrl); |
| 410 | } | 410 | } |
| 411 | 411 | ||
| 412 | exit_intvec: | 412 | exit_intvec: |
| @@ -734,7 +734,7 @@ int mhi_process_ctrl_ev_ring(struct mhi_controller *mhi_cntrl, · 321 unmodified lines | |||
| 734 | MHI_PM_SYS_ERR_DETECT); | 734 | MHI_PM_SYS_ERR_DETECT); |
| 735 | write_unlock_irq(&mhi_cntrl->pm_lock); | 735 | write_unlock_irq(&mhi_cntrl->pm_lock); |
| 736 | if (new_state == MHI_PM_SYS_ERR_DETECT) | 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 | break; | 738 | break; |
| 739 | } | 739 | } |
| 740 | default: | 740 | default: |
| @@ -920,7 +920,7 @@ void mhi_ctrl_ev_task(unsigned long data) · 179 unmodified lines | |||
| 920 | } | 920 | } |
| 921 | write_unlock_irq(&mhi_cntrl->pm_lock); | 921 | write_unlock_irq(&mhi_cntrl->pm_lock); |
| 922 | if (pm_state == MHI_PM_SYS_ERR_DETECT) | 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 | to_mhi_pm_state_str(transition_state)); | 449 | to_mhi_pm_state_str(transition_state)); |
| 450 | 450 | ||
| 451 | /* We must notify MHI control driver so it can clean up first */ | 451 | /* We must notify MHI control driver so it can clean up first */ |
| 452 | if (transition_state == MHI_PM_SYS_ERR_PROCESS) { | 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 | } | ||
| 463 | mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_SYS_ERROR); | 453 | mhi_cntrl->status_cb(mhi_cntrl, MHI_CB_SYS_ERROR); |
| 464 | } | ||
| 465 | 454 | ||
| 466 | mutex_lock(&mhi_cntrl->pm_mutex); | 455 | mutex_lock(&mhi_cntrl->pm_mutex); |
| 467 | write_lock_irq(&mhi_cntrl->pm_lock); | 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 | mutex_unlock(&mhi_cntrl->pm_mutex); | 516 | mutex_unlock(&mhi_cntrl->pm_mutex); |
| 528 | dev_dbg(dev, "Waiting for all pending threads to complete\n"); | 517 | dev_dbg(dev, "Waiting for all pending threads to complete\n"); |
| 529 | wake_up_all(&mhi_cntrl->state_event); | 518 | wake_up_all(&mhi_cntrl->state_event); |
| 530 | flush_work(&mhi_cntrl->st_worker); | ||
| 531 | 519 | ||
| 532 | dev_dbg(dev, "Reset all active channels and remove MHI devices\n"); | 520 | dev_dbg(dev, "Reset all active channels and remove MHI devices\n"); |
| 533 | device_for_each_child(mhi_cntrl->cntrl_dev, NULL, mhi_destroy_device); | 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 | /* SYS_ERR worker */ | 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, | 600 | struct device *dev = &mhi_cntrl->mhi_dev->dev; |
| 613 | struct mhi_controller, | 601 | |
| 614 | syserr_worker); | 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 | /* Device State Transition worker */ | 611 | /* Device State Transition worker */ |
| @@ -661,6 +653,10 @@ void mhi_pm_st_worker(struct work_struct *work) · 41 unmodified lines | |||
| 661 | case DEV_ST_TRANSITION_READY: | 653 | case DEV_ST_TRANSITION_READY: |
| 662 | mhi_ready_state_transition(mhi_cntrl); | 654 | mhi_ready_state_transition(mhi_cntrl); |
| 663 | break; | 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 | default: | 660 | default: |
| 665 | break; | 661 | break; |
| 666 | } | 662 | } |
| @@ -331,7 +331,6 @@ struct mhi_controller_config { · 330 unmodified lines | |||
| 331 | * @wlock: Lock for protecting device wakeup | 331 | * @wlock: Lock for protecting device wakeup |
| 332 | * @mhi_link_info: Device bandwidth info | 332 | * @mhi_link_info: Device bandwidth info |
| 333 | * @st_worker: State transition worker | 333 | * @st_worker: State transition worker |
| 334 | * @syserr_worker: System error worker | ||
| 335 | * @state_event: State change event | 334 | * @state_event: State change event |
| 336 | * @status_cb: CB function to notify power states of the device (required) | 335 | * @status_cb: CB function to notify power states of the device (required) |
| 337 | * @wake_get: CB function to assert device wake (optional) | 336 | * @wake_get: CB function to assert device wake (optional) |
| @@ -411,7 +410,6 @@ struct mhi_controller { · 73 unmodified lines | |||
| 411 | spinlock_t wlock; | 410 | spinlock_t wlock; |
| 412 | struct mhi_link_info mhi_link_info; | 411 | struct mhi_link_info mhi_link_info; |
| 413 | struct work_struct st_worker; | 412 | struct work_struct st_worker; |
| 414 | struct work_struct syserr_worker; | ||
| 415 | wait_queue_head_t state_event; | 413 | wait_queue_head_t state_event; |
| 416 | 414 | ||
| 417 | void (*status_cb)(struct mhi_controller *mhi_cntrl, | 415 | void (*status_cb)(struct mhi_controller *mhi_cntrl, |