From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755954AbbDGNV4 (ORCPT ); Tue, 7 Apr 2015 09:21:56 -0400 Received: from ip4-83-240-67-251.cust.nbox.cz ([83.240.67.251]:54443 "EHLO ip4-83-240-18-248.cust.nbox.cz" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754082AbbDGMwH (ORCPT ); Tue, 7 Apr 2015 08:52:07 -0400 From: Jiri Slaby To: stable@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Alexander Sverdlin , Mark Brown , Jiri Slaby Subject: [PATCH 3.12 045/155] spi: pl022: Fix race in giveback() leading to driver lock-up Date: Tue, 7 Apr 2015 14:50:14 +0200 Message-Id: <3d75857fbf0105e30a7d7ae3d1bdd39b2cbc535a.1428411004.git.jslaby@suse.cz> X-Mailer: git-send-email 2.3.4 In-Reply-To: <9a548862b8a26cbccc14f2c6c9c3688813d8d14b.1428411003.git.jslaby@suse.cz> References: <9a548862b8a26cbccc14f2c6c9c3688813d8d14b.1428411003.git.jslaby@suse.cz> In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Alexander Sverdlin 3.12-stable review patch. If anyone has any objections, please let me know. =============== commit cd6fa8d2ca53cac3226fdcffcf763be390abae32 upstream. 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 Signed-off-by: Mark Brown Signed-off-by: Jiri Slaby --- drivers/spi/spi-pl022.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index b1a9ba893fab..0bc4e4508e6f 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -503,12 +503,12 @@ static void giveback(struct pl022 *pl022) pl022->cur_msg = NULL; pl022->cur_transfer = NULL; pl022->cur_chip = NULL; - spi_finalize_current_message(pl022->master); /* disable the SPI/SSP operation */ writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); + spi_finalize_current_message(pl022->master); } /** -- 2.3.4