- 23 Jan, 2021 40 commits
-
-
Ahmed S. Darwish authored
libsas event notifiers required an extension where gfp_t flags must be explicitly passed. For bisectability, a temporary _gfp() variant of such functions were added. All call sites then got converted use the _gfp() variants and explicitly pass GFP context. Having no callers left, the original libsas notifiers were then modified to accept gfp_t flags by default. Switch back to the original libas API, while still passing GFP context. The libsas _gfp() variants will be removed afterwards. Link: https://lore.kernel.org/r/20210118100955.1761652-14-a.darwish@linutronix.deReviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Ahmed S. Darwish authored
All call-sites of below libsas APIs: - sas_alloc_event() - sas_notify_port_event() - sas_notify_phy_event() have been converted to use the _gfp()-suffixed version. Modify the original APIs above to take a gfp_t flags parameter by default. For bisectability, call-sites will be modified again to use the original libsas APIs (while passing gfp_t). The temporary _gfp()-suffixed versions can then be removed. Link: https://lore.kernel.org/r/20210118100955.1761652-13-a.darwish@linutronix.de Cc: Jason Yan <yanaijie@huawei.com> Reviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Ahmed S. Darwish authored
Use the new libsas event notifiers API, which requires callers to explicitly pass the gfp_t memory allocation flags. Below are the context analysis for modified functions: => hisi_sas_bytes_dmaed(): Since it is invoked from both process and atomic contexts, let its callers pass the gfp_t flags: * hisi_sas_main.c: ------------------ hisi_sas_phyup_work(): workqueue context -> hisi_sas_bytes_dmaed(..., GFP_KERNEL) hisi_sas_controller_reset_done(): has an msleep() -> hisi_sas_rescan_topology() -> hisi_sas_phy_down() -> hisi_sas_bytes_dmaed(..., GFP_KERNEL) hisi_sas_debug_I_T_nexus_reset(): calls wait_for_completion_timeout() -> hisi_sas_phy_down() -> hisi_sas_bytes_dmaed(..., GFP_KERNEL) * hisi_sas_v1_hw.c: ------------------- int_abnormal_v1_hw(): irq handler -> hisi_sas_phy_down() -> hisi_sas_bytes_dmaed(..., GFP_ATOMIC) * hisi_sas_v[23]_hw.c: ---------------------- int_phy_updown_v[23]_hw(): irq handler -> phy_down_v[23]_hw() -> hisi_sas_phy_down() -> hisi_sas_bytes_dmaed(..., GFP_ATOMIC) => int_bcast_v1_hw() and phy_bcast_v3_hw(): Both are invoked exclusively from irq handlers. Pass GFP_ATOMIC. Link: https://lore.kernel.org/r/20210118100955.1761652-12-a.darwish@linutronix.deReviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Ahmed S. Darwish authored
Use the new libsas event notifiers API, which requires callers to explicitly pass the gfp_t memory allocation flags. Context analysis: aic94xx_hwi.c: asd_dl_tasklet_handler() -> asd_ascb::tasklet_complete() == escb_tasklet_complete() -> aic94xx_scb.c: asd_phy_event_tasklet() -> aic94xx_scb.c: asd_bytes_dmaed_tasklet() -> aic94xx_scb.c: asd_link_reset_err_tasklet() -> aic94xx_scb.c: asd_primitive_rcvd_tasklet() All functions are invoked by escb_tasklet_complete(), which is invoked by the tasklet handler. Pass GFP_ATOMIC. Link: https://lore.kernel.org/r/20210118100955.1761652-11-a.darwish@linutronix.deReviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Ahmed S. Darwish authored
Use the new libsas event notifiers API, which requires callers to explicitly pass the gfp_t memory allocation flags. Call chain analysis, pm8001_hwi.c: pm8001_interrupt_handler_msix() || pm8001_interrupt_handler_intx() || pm8001_tasklet() -> PM8001_CHIP_DISP->isr() = pm80xx_chip_isr() -> process_oq [spin_lock_irqsave(&pm8001_ha->lock, ...)] -> process_one_iomb() -> mpi_hw_event() -> hw_event_sas_phy_up() -> pm8001_bytes_dmaed() -> hw_event_sata_phy_up -> pm8001_bytes_dmaed() All functions are invoked by process_one_iomb(), which is invoked by the interrupt service routine and the tasklet handler. A similar call chain is also found at pm80xx_hwi.c. Pass GFP_ATOMIC. For pm8001_sas.c, pm8001_phy_control() runs in task context as it calls wait_for_completion() and msleep(). Pass GFP_KERNEL. Link: https://lore.kernel.org/r/20210118100955.1761652-10-a.darwish@linutronix.de Cc: Jack Wang <jinpu.wang@cloud.ionos.com> Reviewed-by: John Garry <john.garry@huawei.com> Reviewed-by: Jack Wang <jinpu.wang@cloud.ionos.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Ahmed S. Darwish authored
Use the new libsas event notifiers API, which requires callers to explicitly pass the gfp_t memory allocation flags. Context analysis: - sas_enable_revalidation(): process, acquires mutex - sas_resume_ha(): process, calls wait_event_timeout() Link: https://lore.kernel.org/r/20210118100955.1761652-9-a.darwish@linutronix.de Cc: Jason Yan <yanaijie@huawei.com> Reviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Ahmed S. Darwish authored
Use the new libsas event notifiers API, which requires callers to explicitly pass the gfp_t memory allocation flags. libsas sas_notify_port_event() is called from isci_port_bc_change_received(). Below is the context analysis for all of its call chains: host.c: sci_controller_error_handler(): atomic, irq handler (*) OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) -> sci_controller_process_completions() -> sci_controller_event_completion() -> phy.c: sci_phy_event_handler() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received() host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> port_config.c: sci_port_configuration_agent_initialize() -> sci_mpc_agent_validate_phy_configuration() -> port.c: sci_port_add_phy() -> sci_port_set_phy() -> phy.c: sci_phy_set_port() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received() port_config.c: apc_agent_timeout(), atomic, timer callback (*) -> sci_apc_agent_configure_ports() -> port.c: sci_port_add_phy() -> sci_port_set_phy() -> phy.c: sci_phy_set_port() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received() phy.c: enter SCI state: *SCI_PHY_STOPPED* # Cont. from [1] -> sci_phy_stopped_state_enter() -> host.c: sci_controller_link_down() -> ->link_down_handler() == port_config.c: sci_apc_agent_link_down() -> port.c: sci_port_remove_phy() -> sci_port_clear_phy() -> phy.c: sci_phy_set_port() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received() phy.c: enter SCI state: *SCI_PHY_STARTING* # Cont. from [2] -> sci_phy_starting_state_enter() -> host.c: sci_controller_link_down() -> ->link_down_handler() == port_config.c: sci_apc_agent_link_down() -> port.c: sci_port_remove_phy() -> sci_port_clear_phy() -> phy.c: sci_phy_set_port() -> port.c: sci_port_broadcast_change_received() -> isci_port_bc_change_received() [1] Call chains for entering state: *SCI_PHY_STOPPED* ----------------------------------------------------- host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> phy.c: sci_phy_initialize() -> phy.c: sci_phy_link_layer_initialization() -> phy.c: sci_change_state(SCI_PHY_STOPPED) init.c: PCI ->remove() || PM_OPS ->suspend, process context (+) -> host.c: isci_host_deinit() -> sci_controller_stop_phys() -> phy.c: sci_phy_stop() -> sci_change_state(SCI_PHY_STOPPED) phy.c: isci_phy_control() spin_lock_irqsave(isci_host::scic_lock, ) -> sci_phy_stop(), atomic (*) -> sci_change_state(SCI_PHY_STOPPED) [2] Call chains for entering state: *SCI_PHY_STARTING* ------------------------------------------------------ phy.c: phy_sata_timeout(), atimer, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> sci_change_state(SCI_PHY_STARTING) host.c: phy_startup_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING) host.c: isci_host_start() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_start(), atomic (*) -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING) phy.c: Enter SCI state *SCI_PHY_SUB_FINAL* # Cont. from [2A] -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_phy_starting_final_substate_enter() -> sci_change_state(SCI_PHY_READY) -> Enter SCI state: *SCI_PHY_READY* -> sci_phy_ready_state_enter() -> host.c: sci_controller_link_up() -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING) phy.c: sci_phy_event_handler(), atomic, discussed earlier (*) -> sci_change_state(SCI_PHY_STARTING), 11 instances port.c: isci_port_perform_hard_reset() spin_lock_irqsave(isci_host::scic_lock, ) -> port.c: sci_port_hard_reset(), atomic (*) -> phy.c: sci_phy_reset() -> sci_change_state(SCI_PHY_RESETTING) -> enter SCI PHY state: *SCI_PHY_RESETTING* -> sci_phy_resetting_state_enter() -> sci_change_state(SCI_PHY_STARTING) [2A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL* ------------------------------------------------------------ host.c: power_control_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> phy.c: sci_phy_consume_power_handler() -> phy.c: sci_change_state(SCI_PHY_SUB_FINAL) host.c: sci_controller_error_handler(): atomic, irq handler (*) OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) -> sci_controller_process_completions() -> sci_controller_unsolicited_frame() -> phy.c: sci_phy_frame_handler() -> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER) -> sci_phy_starting_await_sas_power_substate_enter() -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_controller_event_completion() -> phy.c: sci_phy_event_handler() -> sci_phy_start_sata_link_training() -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER) -> sci_phy_starting_await_sata_power_substate_enter -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) As can be seen from the "(*)" markers above, almost all the call-chains are atomic. The only exception, marked with "(+)", is a PCI ->remove() and PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas port event notifier. Note, the now-replaced libsas APIs used in_interrupt() to implicitly decide which memory allocation type to use. This was only partially correct, as it fails to choose the correct GFP flags when just preemption or interrupts are disabled. Such buggy code paths are marked with "(@)" in the call chains above. Link: https://lore.kernel.org/r/20210118100955.1761652-8-a.darwish@linutronix.de Fixes: 1c393b97 ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Artur Paszkiewicz <artur.paszkiewicz@intel.com> Reviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Ahmed S. Darwish authored
Use the new libsas event notifiers API, which requires callers to explicitly pass the gfp_t memory allocation flags. libsas sas_notify_port_event() is called from isci_port_link_up(). Below is the context analysis for all of its call chains: host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> port_config.c: sci_port_configuration_agent_initialize() -> sci_mpc_agent_validate_phy_configuration() -> port.c: sci_port_add_phy() -> sci_port_general_link_up_handler() -> sci_port_activate_phy() -> isci_port_link_up() port_config.c: apc_agent_timeout(), atomic, timer callback (*) -> sci_apc_agent_configure_ports() -> port.c: sci_port_add_phy() -> sci_port_general_link_up_handler() -> sci_port_activate_phy() -> isci_port_link_up() phy.c: enter SCI state: *SCI_PHY_SUB_FINAL* # Cont. from [1] -> phy.c: sci_phy_starting_final_substate_enter() -> phy.c: sci_change_state(SCI_PHY_READY) -> enter SCI state: *SCI_PHY_READY* -> phy.c: sci_phy_ready_state_enter() -> host.c: sci_controller_link_up() -> .link_up_handler() == port_config.c: sci_apc_agent_link_up() -> port.c: sci_port_link_up() -> (continue at [A]) == port_config.c: sci_mpc_agent_link_up() -> port.c: sci_port_link_up() -> (continue at [A]) port_config.c: mpc_agent_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> ->link_up_handler() == port_config.c: sci_apc_agent_link_up() -> port.c: sci_port_link_up() -> (continue at [A]) == port_config.c: sci_mpc_agent_link_up() -> port.c: sci_port_link_up() -> (continue at [A]) [A] port.c: sci_port_link_up() -> sci_port_activate_phy() -> isci_port_link_up() -> sci_port_general_link_up_handler() -> sci_port_activate_phy() -> isci_port_link_up() [1] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL* ----------------------------------------------------------- host.c: power_control_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> phy.c: sci_phy_consume_power_handler() -> phy.c: sci_change_state(SCI_PHY_SUB_FINAL) host.c: sci_controller_error_handler(): atomic, irq handler (*) OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) -> sci_controller_process_completions() -> sci_controller_unsolicited_frame() -> phy.c: sci_phy_frame_handler() -> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER) -> sci_phy_starting_await_sas_power_substate_enter() -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_controller_event_completion() -> phy.c: sci_phy_event_handler() -> sci_phy_start_sata_link_training() -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER) -> sci_phy_starting_await_sata_power_substate_enter -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) As can be seen from the "(*)" markers above, all the call-chains are atomic. Pass GFP_ATOMIC to libsas port event notifier. Note, the now-replaced libsas APIs used in_interrupt() to implicitly decide which memory allocation type to use. This was only partially correct, as it fails to choose the correct GFP flags when just preemption or interrupts are disabled. Such buggy code paths are marked with "(@)" in the call chains above. Link: https://lore.kernel.org/r/20210118100955.1761652-7-a.darwish@linutronix.de Fixes: 1c393b97 ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Artur Paszkiewicz <artur.paszkiewicz@intel.com> Reviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Ahmed S. Darwish authored
Use the new libsas event notifiers API, which requires callers to explicitly pass the gfp_t memory allocation flags. sas_notify_phy_event() is exclusively called by isci_port_link_down(). Below is the context analysis for all of its call chains: port.c: port_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> port_state_machine_change(..., SCI_PORT_FAILED) -> enter SCI port state: *SCI_PORT_FAILED* -> sci_port_failed_state_enter() -> isci_port_hard_reset_complete() -> isci_port_link_down() port.c: isci_port_perform_hard_reset() spin_lock_irqsave(isci_host::scic_lock, ) -> port.c: sci_port_hard_reset(), atomic (*) -> phy.c: sci_phy_reset() -> sci_change_state(SCI_PHY_RESETTING) -> enter SCI PHY state: *SCI_PHY_RESETTING* -> sci_phy_resetting_state_enter() -> port.c: sci_port_deactivate_phy() -> isci_port_link_down() port.c: enter SCI port state: *SCI_PORT_READY* # Cont. from [1] -> sci_port_ready_state_enter() -> isci_port_hard_reset_complete() -> isci_port_link_down() phy.c: enter SCI state: *SCI_PHY_STOPPED* # Cont. from [2] -> sci_phy_stopped_state_enter() -> host.c: sci_controller_link_down() -> ->link_down_handler() == port_config.c: sci_apc_agent_link_down() -> port.c: sci_port_remove_phy() -> sci_port_deactivate_phy() -> isci_port_link_down() == port_config.c: sci_mpc_agent_link_down() -> port.c: sci_port_link_down() -> sci_port_deactivate_phy() -> isci_port_link_down() phy.c: enter SCI state: *SCI_PHY_STARTING* # Cont. from [3] -> sci_phy_starting_state_enter() -> host.c: sci_controller_link_down() -> ->link_down_handler() == port_config.c: sci_apc_agent_link_down() -> port.c: sci_port_remove_phy() -> isci_port_link_down() == port_config.c: sci_mpc_agent_link_down() -> port.c: sci_port_link_down() -> sci_port_deactivate_phy() -> isci_port_link_down() [1] Call chains for 'enter SCI port state: *SCI_PORT_READY*' ------------------------------------------------------------ host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> port_config.c: sci_port_configuration_agent_initialize() -> sci_mpc_agent_validate_phy_configuration() -> port.c: sci_port_add_phy() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* host.c: isci_host_start() (@) spin_lock_irq(isci_host::scic_lock) -> host.c: sci_controller_start(), atomic (*) -> host.c: sci_port_start() -> port.c: port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* port_config.c: apc_agent_timeout(), atomic, timer callback (*) -> sci_apc_agent_configure_ports() -> port.c: sci_port_add_phy() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* port_config.c: mpc_agent_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> ->link_up_handler() == port.c: sci_apc_agent_link_up() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* == port.c: sci_mpc_agent_link_up() -> port.c: sci_port_link_up() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* phy.c: enter SCI state: SCI_PHY_SUB_FINAL # Cont. from [1A] -> sci_phy_starting_final_substate_enter() -> sci_change_state(SCI_PHY_READY) -> enter SCI state: *SCI_PHY_READY* -> sci_phy_ready_state_enter() -> host.c: sci_controller_link_up() -> port_agent.link_up_handler() == port_config.c: sci_apc_agent_link_up() -> port.c: sci_port_link_up() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* == port_config.c: sci_mpc_agent_link_up() -> port.c: sci_port_link_up() -> sci_port_general_link_up_handler() -> port_state_machine_change(, SCI_PORT_READY) -> enter port state *SCI_PORT_READY* [1A] Call chains for entering SCI state: *SCI_PHY_SUB_FINAL* ------------------------------------------------------------ host.c: power_control_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> phy.c: sci_phy_consume_power_handler() -> phy.c: sci_change_state(SCI_PHY_SUB_FINAL) host.c: sci_controller_error_handler(): atomic, irq handler (*) OR host.c: sci_controller_completion_handler(), atomic, tasklet (*) -> sci_controller_process_completions() -> sci_controller_unsolicited_frame() -> phy.c: sci_phy_frame_handler() -> sci_change_state(SCI_PHY_SUB_AWAIT_SAS_POWER) -> sci_phy_starting_await_sas_power_substate_enter() -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_controller_event_completion() -> phy.c: sci_phy_event_handler() -> sci_phy_start_sata_link_training() -> sci_change_state(SCI_PHY_SUB_AWAIT_SATA_POWER) -> sci_phy_starting_await_sata_power_substate_enter -> host.c: sci_controller_power_control_queue_insert() -> phy.c: sci_phy_consume_power_handler() -> sci_change_state(SCI_PHY_SUB_FINAL) [2] Call chains for entering state: *SCI_PHY_STOPPED* ----------------------------------------------------- host.c: isci_host_init() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_initialize(), atomic (*) -> phy.c: sci_phy_initialize() -> phy.c: sci_phy_link_layer_initialization() -> phy.c: sci_change_state(SCI_PHY_STOPPED) init.c: PCI ->remove() || PM_OPS ->suspend, process context (+) -> host.c: isci_host_deinit() -> sci_controller_stop_phys() -> phy.c: sci_phy_stop() -> sci_change_state(SCI_PHY_STOPPED) phy.c: isci_phy_control() spin_lock_irqsave(isci_host::scic_lock, ) -> sci_phy_stop(), atomic (*) -> sci_change_state(SCI_PHY_STOPPED) [3] Call chains for entering state: *SCI_PHY_STARTING* ------------------------------------------------------ phy.c: phy_sata_timeout(), atimer, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> sci_change_state(SCI_PHY_STARTING) host.c: phy_startup_timeout(), atomic, timer callback (*) spin_lock_irqsave(isci_host::scic_lock, ) -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING) host.c: isci_host_start() (@) spin_lock_irq(isci_host::scic_lock) -> sci_controller_start(), atomic (*) -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING) phy.c: Enter SCI state *SCI_PHY_SUB_FINAL*, atomic, check above (*) -> sci_change_state(SCI_PHY_SUB_FINAL) -> sci_phy_starting_final_substate_enter() -> sci_change_state(SCI_PHY_READY) -> Enter SCI state: *SCI_PHY_READY* -> sci_phy_ready_state_enter() -> host.c: sci_controller_link_up() -> sci_controller_start_next_phy() -> sci_phy_start() -> sci_change_state(SCI_PHY_STARTING) phy.c: sci_phy_event_handler(), atomic, discussed earlier (*) -> sci_change_state(SCI_PHY_STARTING), 11 instances phy.c: enter SCI state: *SCI_PHY_RESETTING*, atomic, discussed (*) -> sci_phy_resetting_state_enter() -> sci_change_state(SCI_PHY_STARTING) As can be seen from the "(*)" markers above, almost all the call-chains are atomic. The only exception, marked with "(+)", is a PCI ->remove() and PM_OPS ->suspend() cold path. Thus, pass GFP_ATOMIC to the libsas phy event notifier. Note, The now-replaced libsas APIs used in_interrupt() to implicitly decide which memory allocation type to use. This was only partially correct, as it fails to choose the correct GFP flags when just preemption or interrupts are disabled. Such buggy code paths are marked with "(@)" in the call chains above. Link: https://lore.kernel.org/r/20210118100955.1761652-6-a.darwish@linutronix.de Fixes: 1c393b97 ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Artur Paszkiewicz <artur.paszkiewicz@intel.com> Reviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Ahmed S. Darwish authored
mvsas calls the non _gfp version of the libsas event notifiers API, leading to the buggy call chains below: mvsas/mv_sas.c: mvs_work_queue() [process context] spin_lock_irqsave(mvs_info::lock, ) -> libsas/sas_event.c: sas_notify_phy_event() -> sas_alloc_event() -> in_interrupt() = false -> invalid GFP_KERNEL allocation -> libsas/sas_event.c: sas_notify_port_event() -> sas_alloc_event() -> in_interrupt() = false -> invalid GFP_KERNEL allocation Use the new event notifiers API instead, which requires callers to explicitly pass the gfp_t memory allocation flags. Below are context analysis for the modified functions: => mvs_bytes_dmaed(): Since it is invoked from both process and atomic contexts, let its callers pass the gfp_t flags. Call chains: scsi_scan.c: do_scsi_scan_host() [has msleep()] -> shost->hostt->scan_start() -> [mvsas/mv_init.c: Scsi_Host::scsi_host_template .scan_start = mvs_scan_start()] -> mvsas/mv_sas.c: mvs_scan_start() -> mvs_bytes_dmaed(..., GFP_KERNEL) mvsas/mv_sas.c: mvs_work_queue() spin_lock_irqsave(mvs_info::lock,) -> mvs_bytes_dmaed(..., GFP_ATOMIC) mvsas/mv_64xx.c: mvs_64xx_isr() || mvsas/mv_94xx.c: mvs_94xx_isr() -> mvsas/mv_chips.h: mvs_int_full() -> mvsas/mv_sas.c: mvs_int_port() -> mvs_bytes_dmaed(..., GFP_ATOMIC); => mvs_work_queue(): Invoked from process context, but it calls all the libsas event notifier APIs under a spin_lock_irqsave(). Pass GFP_ATOMIC. Link: https://lore.kernel.org/r/20210118100955.1761652-5-a.darwish@linutronix.de Fixes: 1c393b97 ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Jason Yan <yanaijie@huawei.com> Reviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Ahmed S. Darwish authored
sas_alloc_event() uses in_interrupt() to decide which allocation should be used. The usage of in_interrupt() in drivers is phased out and Linus clearly requested that code which changes behaviour depending on context should either be separated or the context be conveyed in an argument passed by the caller, which usually knows the context. The in_interrupt() check is also only partially correct, because it fails to choose the correct code path when just preemption or interrupts are disabled. For example, as in the following call chain: mvsas/mv_sas.c: mvs_work_queue() [process context] spin_lock_irqsave(mvs_info::lock, ) -> libsas/sas_event.c: sas_notify_phy_event() -> sas_alloc_event() -> in_interrupt() = false -> invalid GFP_KERNEL allocation -> libsas/sas_event.c: sas_notify_port_event() -> sas_alloc_event() -> in_interrupt() = false -> invalid GFP_KERNEL allocation Introduce sas_alloc_event_gfp(), sas_notify_port_event_gfp(), and sas_notify_phy_event_gfp(), which all behave like the non _gfp() variants but use a caller-passed GFP mask for allocations. For bisectability, all callers will be modified first to pass GFP context, then the non _gfp() libsas API variants will be modified to take a gfp_t by default. Link: https://lore.kernel.org/r/20210118100955.1761652-4-a.darwish@linutronix.de Fixes: 1c393b97 ("scsi: libsas: Use dynamic alloced work to avoid sas event lost") Cc: Jason Yan <yanaijie@huawei.com> Reviewed-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
John Garry authored
LLDDs report events to libsas with .notify_port_event and .notify_phy_event callbacks. These callbacks are fixed and so there is no reason why the functions cannot be called directly, so do that. This neatens the code slightly, makes it more obvious, and reduces function pointer usage, which is generally a good thing. Downside is that there are 2x more symbol exports. [a.darwish@linutronix.de: Remove the now unused "sas_ha" local variables] Link: https://lore.kernel.org/r/20210118100955.1761652-3-a.darwish@linutronix.deReviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Jack Wang <jinpu.wang@cloud.ionos.com> Signed-off-by: John Garry <john.garry@huawei.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Ahmed S. Darwish authored
The ->notify_ha_event() hook has long been removed from the libsas event interface. Remove it from documentation. Link: https://lore.kernel.org/r/20210118100955.1761652-2-a.darwish@linutronix.de Fixes: 042ebd29 ("scsi: libsas: kill useless ha_event and do some cleanup") Cc: stable@vger.kernel.org Reviewed-by: John Garry <john.garry@huawei.com> Reviewed-by: Jack Wang <jinpu.wang@cloud.ionos.com> Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Use SAM status values instead of the driver-defined ones. This also fixes a potential bug as the driver-defined values declare 'COMMAND TERMINATED' with a value of 0x20, whereas SCSI-II defines it with a value of 0x22. Link: https://lore.kernel.org/r/20210113090500.129644-36-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Replace the driver-defined status byte accessors with the mid-layer defined ones. Link: https://lore.kernel.org/r/20210113090500.129644-35-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
fc_remote_port_chkready() returns a SCSI result value, not the port status. Fix the value returned when the remote port isn't set. Link: https://lore.kernel.org/r/20210113090500.129644-34-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
ILLEGAL_COMMAND is a sense code, not a driver byte. Link: https://lore.kernel.org/r/20210113090500.129644-33-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
A non-zero queuecommand() return code means 'busy', i.e. the command hasn't been submitted. So any command which should be failed need to be completed via the ->scsi_done() callback with the appropriate result code set. Link: https://lore.kernel.org/r/20210113090500.129644-32-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Use standard SCSI status and drop usage of the linux-specific ones. Link: https://lore.kernel.org/r/20210113090500.129644-31-hare@suse.deReviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
The message byte setting always devolves to COMMAND_COMPLETE so we can drop setting the message byte in the SCSI result. Link: https://lore.kernel.org/r/20210113090500.129644-30-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Just pass in the host byte to esp_cmd_is_done() and set the status or message bytes if the host byte is DID_OK. Link: https://lore.kernel.org/r/20210113090500.129644-29-hare@suse.deAcked-by: Finn Thain <fthain@telegraphics.com.au> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Add the missing 'set_status_byte()' accessor function. Link: https://lore.kernel.org/r/20210113090500.129644-28-hare@suse.deReviewed-by: Benjamin Block <bblock@linux.ibm.com> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Change the error code for an invalid SCSI opcode to DID_ERROR. INITIATOR_ERROR is a scsi parallel message which doesn't apply for RAID HBAs. Link: https://lore.kernel.org/r/20210113090500.129644-27-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
CMD_ACCEPT_MSG is an internal definition and most certainly not a SCSI status. As the latter gets set during command completion we can drop the assignment here. Link: https://lore.kernel.org/r/20210113090500.129644-26-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Use standard definitions for SCSI commands and return status instead of the hardcoded values. Link: https://lore.kernel.org/r/20210113090500.129644-25-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
COMMAND_COMPLETE is defined as '0', so setting it is quite pointless. Link: https://lore.kernel.org/r/20210113090500.129644-24-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
COMMAND_COMPLETE is defined as '0', so setting it is quite pointless. Link: https://lore.kernel.org/r/20210113090500.129644-23-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Acked-by: Douglas Gilbert <dgilbert@interlog.com> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Use the standard SCSI message definitions instead of the driver-internal ones. Link: https://lore.kernel.org/r/20210113090500.129644-22-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Drop the internal SCSI message definitions and use the functions provided by the SPI transport class. Link: https://lore.kernel.org/r/20210113090500.129644-21-hare@suse.deReported-by: kernel test robot <lkp@intel.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Use the standard SCSI message definitions instead of the driver-internal ones. Link: https://lore.kernel.org/r/20210113090500.129644-20-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Use the standard SCSI message definitions instead of the driver-internal ones. Link: https://lore.kernel.org/r/20210113090500.129644-19-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
COMMAND_COMPLETE is defined as '0', so setting it is quite pointless. Link: https://lore.kernel.org/r/20210113090500.129644-18-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
COMMAND_COMPLETE is defined as '0', and it is a SCSI parallel message to boot. Drop the call to set_msg_byte(). Link: https://lore.kernel.org/r/20210113090500.129644-17-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Acked-by: Don Brace <don.brace@microchip.com> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
The aacraid controller is a RAID controller and the driver will never see any SCSI messages. Plus it's quite pointless to set the message byte if the host byte is already set, as the latter takes precedence during error recovery. Drop the message byte values for the final result. Link: https://lore.kernel.org/r/20210113090500.129644-16-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
COMMAND_COMPLETE is defined as '0', and it is a SCSI parallel message to boot. So drop the call to set_msg_byte(). Link: https://lore.kernel.org/r/20210113090500.129644-15-hare@suse.deReviewed-by: Benjamin Block <bblock@linux.ibm.com> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Use standard SAM status definitions and drop the driver-defined ones. Link: https://lore.kernel.org/r/20210113090500.129644-14-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
We don't need to duplicate definitions from the common include files. Link: https://lore.kernel.org/r/20210113090500.129644-13-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
SCp.status is always the SAM-defined status value, not the Linux ones. Fixup the one wrong definition. Link: https://lore.kernel.org/r/20210113090500.129644-12-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Use midlayer-defined values and drop the non-existing QUEUE_FULL case; we are checking the SCSI messages in the switch statement, and QUEUE_FULL is a SCSI status hence it can never occur here. Link: https://lore.kernel.org/r/20210113090500.129644-11-hare@suse.deReviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-
Hannes Reinecke authored
Drop the driver-defined SCSI status codes and use the generic ones instead. Link: https://lore.kernel.org/r/20210113090500.129644-10-hare@suse.deReviewed-by: Bart Van Assche <bvanassche@acm.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-