From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754076AbcICQiv (ORCPT ); Sat, 3 Sep 2016 12:38:51 -0400 Received: from saturn.retrosnub.co.uk ([178.18.118.26]:45311 "EHLO saturn.retrosnub.co.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753296AbcICQis (ORCPT ); Sat, 3 Sep 2016 12:38:48 -0400 Subject: Re: A potential bug in drivers/iio/light/opt3001.ko To: Pavel Andrianov References: Cc: Hartmut Knaack , Lars-Peter Clausen , Peter Meerwald-Stadler , linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, Alexander Koch , Vaishali Thakkar , ldv-project@linuxtesting.org, Andreas Dannenberg From: Jonathan Cameron Message-ID: <61728463-8bd8-c68e-ef4a-7a3e0ddd7899@kernel.org> Date: Sat, 3 Sep 2016 17:38:44 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 31/08/16 11:23, Pavel Andrianov wrote: > Hi! > > There is a bug in drivers/iio/light/opt3001.ko. Regard such case: > > Thread 1 Thread 2 > -> opt3001_read_raw > -> mutex_lock(&opt->lock) > -> opt3001_get_lux() > .. > ->i2c_smbus_write_word_swapped() > Now an interrupt comes > -> opt3001_irq > -> mutex_lock(&opt->lock) > > This is a deadlock, as the flag ok_to_ignore_lock has not been set yet. Good find. Will need reordering to set the ok_to_ignore_lock first. Whether it ever actually happens will depend on just how long that EOC interrupt takes to happen. Still it's a theoretical problem with a fairly simple fix so let's fix it. > > Regard another case: > > Thread 1 Thread 2 > -> opt3001_read_raw > -> mutex_lock(&opt->lock) > -> opt3001_get_lux() > .. > -> i2c_smbus_write_word_swapped() > opt->ok_to_ignore_lock = true; > Now an interrupt comes > -> opt3001_irq > .. > opt->result_ready = true > wake_up() > opt->result_ready = false; > wait_event_timeout() > > In this case the first thread misses the result and waits until timeout expires. > Agreed - looks like some reordering is needed here as well. Jonathan