]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commit
spi: pl022: Fix race in giveback() leading to driver lock-up
authorAlexander Sverdlin <alexander.sverdlin@nokia.com>
Fri, 27 Feb 2015 15:30:21 +0000 (16:30 +0100)
committerMark Brown <broonie@kernel.org>
Fri, 6 Mar 2015 19:45:55 +0000 (19:45 +0000)
commitcd6fa8d2ca53cac3226fdcffcf763be390abae32
tree2ae9291447b4a70c781c0ac7f8c6e3fcb5c1751a
parentc517d838eb7d07bbe9507871fab3931deccff539
spi: pl022: Fix race in giveback() leading to driver lock-up

Commit fd316941c ("spi/pl022: disable port when unused") introduced a race,
which leads to possible driver lock up (easily reproducible on SMP).

The problem happens in giveback() function where the completion of the transfer
is signalled to SPI subsystem and then the HW SPI controller is disabled. Another
transfer might be setup in between, which brings driver in locked-up state.

Exact event sequence on SMP:

core0                                   core1

                                        => pump_transfers()
                                        /* message->state == STATE_DONE */
                                          => giveback()
                                            => spi_finalize_current_message()

=> pl022_unprepare_transfer_hardware()
=> pl022_transfer_one_message
  => flush()
  => do_interrupt_dma_transfer()
    => set_up_next_transfer()
    /* Enable SSP, turn on interrupts */
    writew((readw(SSP_CR1(pl022->virtbase)) |
           SSP_CR1_MASK_SSE), SSP_CR1(pl022->virtbase));

...

=> pl022_interrupt_handler()
  => readwriter()

                                        /* disable the SPI/SSP operation */
                                        => writew((readw(SSP_CR1(pl022->virtbase)) &
                                                  (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));

Lockup! SPI controller is disabled and the data will never be received. Whole
SPI subsystem is waiting for transfer ACK and blocked.

So, only signal transfer completion after disabling the controller.

Fixes: fd316941c (spi/pl022: disable port when unused)
Signed-off-by: Alexander Sverdlin <alexander.sverdlin@nokia.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Cc: stable@vger.kernel.org
drivers/spi/spi-pl022.c