• A
    scsi: isci: Pass gfp_t flags in isci_port_link_up() · 230e595c
    Ahmed S. Darwish 提交于
    stable inclusion
    from stable-5.10.26
    commit d74238028a11f9404c25c6a20e005e92095010b9
    bugzilla: 51363
    
    --------------------------------
    
    [ Upstream commit 5ce79029 ]
    
    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: NJohn Garry <john.garry@huawei.com>
    Signed-off-by: NAhmed S. Darwish <a.darwish@linutronix.de>
    Signed-off-by: NMartin K. Petersen <martin.petersen@oracle.com>
    Signed-off-by: NSasha Levin <sashal@kernel.org>
    Signed-off-by: NChen Jun <chenjun102@huawei.com>
    Acked-by: N  Weilong Chen <chenweilong@huawei.com>
    Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
    230e595c
port.c 52.4 KB