From patchwork Thu Jan 9 13:23:55 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 3460191 Return-Path: X-Original-To: patchwork-linux-spi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 63A5D9F384 for ; Thu, 9 Jan 2014 13:24:01 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4766C20123 for ; Thu, 9 Jan 2014 13:24:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 134E42012E for ; Thu, 9 Jan 2014 13:23:59 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751978AbaAINX6 (ORCPT ); Thu, 9 Jan 2014 08:23:58 -0500 Received: from mga01.intel.com ([192.55.52.88]:34187 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753269AbaAINX6 (ORCPT ); Thu, 9 Jan 2014 08:23:58 -0500 Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 09 Jan 2014 05:23:57 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.95,630,1384329600"; d="scan'208";a="462586549" Received: from blue.fi.intel.com ([10.237.72.156]) by fmsmga002.fm.intel.com with ESMTP; 09 Jan 2014 05:23:56 -0800 Received: by blue.fi.intel.com (Postfix, from userid 1004) id 6401DE0090; Thu, 9 Jan 2014 15:23:55 +0200 (EET) From: Mika Westerberg To: linux-spi@vger.kernel.org Cc: Mark Brown , Jarkko Nikula , Mika Westerberg , linux-kernel@vger.kernel.org Subject: [PATCH] spi: Check conflicting CS based on spi->chip_select instead of device name Date: Thu, 9 Jan 2014 15:23:55 +0200 Message-Id: <1389273835-8615-1-git-send-email-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 1.8.5.2 Sender: linux-spi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-spi@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Commit e13ac47bec20 (spi: Use stable dev_name for ACPI enumerated SPI slaves) changed the SPI device naming to be based on ACPI device name instead of carrying bus number and chip select for devices enumerated from ACPI namespace. In case of a buggy BIOS that lists multiple SPI devices sharing the same chip select (even though they should use different) the current code fails to detect that and allows the devices to be added to the bus. Fix this by walking through the bus and comparing spi->chip_select instead of device name. This should work regardless what the device name will be in future. Cc: Jarkko Nikula Signed-off-by: Mika Westerberg Acked-by: Jarkko Nikula --- drivers/spi/spi.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 349ebba4b199..13dcc360bde6 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -370,6 +370,17 @@ static void spi_dev_set_name(struct spi_device *spi) spi->chip_select); } +static int spi_dev_check(struct device *dev, void *data) +{ + struct spi_device *spi = to_spi_device(dev); + struct spi_device *new_spi = data; + + if (spi->master == new_spi->master && + spi->chip_select == new_spi->chip_select) + return -EBUSY; + return 0; +} + /** * spi_add_device - Add spi_device allocated with spi_alloc_device * @spi: spi_device to register @@ -384,7 +395,6 @@ int spi_add_device(struct spi_device *spi) static DEFINE_MUTEX(spi_add_lock); struct spi_master *master = spi->master; struct device *dev = master->dev.parent; - struct device *d; int status; /* Chipselects are numbered 0..max; validate. */ @@ -404,12 +414,10 @@ int spi_add_device(struct spi_device *spi) */ mutex_lock(&spi_add_lock); - d = bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev)); - if (d != NULL) { + status = bus_for_each_dev(&spi_bus_type, NULL, spi, spi_dev_check); + if (status) { dev_err(dev, "chipselect %d already in use\n", spi->chip_select); - put_device(d); - status = -EBUSY; goto done; }