• Emmanuel Grumbach's avatar
    iwlwifi: pcie: fix a race in firmware loading flow · f16c3ebf
    Emmanuel Grumbach authored
    Upon firmware load interrupt (FH_TX), the ISR re-enables the
    firmware load interrupt only to avoid races with other
    flows as described in the commit below. When the firmware
    is completely loaded, the thread that is loading the
    firmware will enable all the interrupts to make sure that
    the driver gets the ALIVE interrupt.
    The problem with that is that the thread that is loading
    the firmware is actually racing against the ISR and we can
    get to the following situation:
    
    CPU0					CPU1
    iwl_pcie_load_given_ucode
    	...
    	iwl_pcie_load_firmware_chunk
    		wait_for_interrupt
    					<interrupt>
    					ISR handles CSR_INT_BIT_FH_TX
    					ISR wakes up the thread on CPU0
    	/* enable all the interrupts
    	 * to get the ALIVE interrupt
    	 */
    	iwl_enable_interrupts
    					ISR re-enables CSR_INT_BIT_FH_TX only
    	/* start the firmware */
    	iwl_write32(trans, CSR_RESET, 0);
    
    BUG! ALIVE interrupt will never arrive since it has been
    masked by CPU1.
    
    In order to fix that, change the ISR to first check if
    STATUS_INT_ENABLED is set. If so, re-enable all the
    interrupts. If STATUS_INT_ENABLED is clear, then we can
    check what specific interrupt happened and re-enable only
    that specific interrupt (RFKILL or FH_TX).
    
    All the credit for the analysis goes to Kirtika who did the
    actual debugging work.
    
    Cc: <stable@vger.kernel.org> [4.5+]
    Fixes: a6bd005f ("iwlwifi: pcie: fix RF-Kill vs. firmware load race")
    Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
    f16c3ebf
rx.c 58.3 KB