Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp4479058ybz; Tue, 28 Apr 2020 12:00:52 -0700 (PDT) X-Google-Smtp-Source: APiQypJC/pHWCMYPnQQa1Hh8FEjk5l58HBqeS4IJcA6a6KYmLN1EGlIAPiHUHiLG+bOaW/z9EqQF X-Received: by 2002:a17:907:40f2:: with SMTP id no2mr10527444ejb.41.1588100452231; Tue, 28 Apr 2020 12:00:52 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1588100452; cv=none; d=google.com; s=arc-20160816; b=FCHea1eOc2Q+FASLw3h9Nz72j6TfxBe6Nbi9p6B0A3FrMpcjq9Jf7xJEgJzyiMz0MW vkDCWEw5PzzSBJr4Gtz0Y4y66YNNQOMwtrPCox2NLD5vGh4QNBUVncMixmcVe7cNHCod jAMuxVhUIcAmUFsAW7FFk7hVbj1oj7fPMps7gpjcFbiweM+AzUdmODXhNPcem8qlIXJI QIm04SXIFJpN4SNqEWK1T+ZUgjL1xk+qTvvPq1GDeIQB96qsjCaTWLwGYYybK4F55PF+ eIH7QccF6djhFj9uMvq5ApA80CQuhwoMfxLBgN9yOBSXoBygn7nabPfWvxTArhFrWPHC NSPw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=ry7YgUBqJbQw/CzhlaTW6DvzQ0LiUTueZiDI/EfPZ4k=; b=SNmO9Gv76PdNtCNu/CMTGHrWxp3ORAtSiHtc5pOcQuKzO9pVHg4/ulIXMU1e5XIy0A sEOBNHtr2yKnrzUdsl4KQd9wb5ikm0ZmM2FAaTk1VyU0r7EvI4jIAkrIkJROgfPeWgX4 YtLvrlgLP/pfOHuwFhrBdCzSlWyzMIb6wemvZrnsLNukz0UWReuuRtXoMbdiKALafX3S OmWTAm5yVGVopBXlaplucAqJ/1LHcm1cFdKFfh7+3W7bHIvicGc+vYucOU4nOL/mWttn /+/cSBrPpDxiBdbQK7Q6eQLgYhKn6D0odaOUQNPEIitEI+ofWHwsizpVjg9lrxtmB4L/ 6NNA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=GnOS9ZkS; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id u10si2067265edl.591.2020.04.28.12.00.27; Tue, 28 Apr 2020 12:00:52 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=GnOS9ZkS; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729052AbgD1Sai (ORCPT + 99 others); Tue, 28 Apr 2020 14:30:38 -0400 Received: from mail.kernel.org ([198.145.29.99]:45484 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729514AbgD1Saf (ORCPT ); Tue, 28 Apr 2020 14:30:35 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id DAE4721744; Tue, 28 Apr 2020 18:30:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1588098634; bh=g1YAP39CqTG42n6Lrt7NMs/G51rc1/7uvT2gc345fpE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=GnOS9ZkSIqZ1o1+9fyjqZQzRXMLvBd9fIAZWs8v8CAKH7G5TxCme9jtBo7lGN2cFJ K3ksEqZtRBvZNguw32ZX/rgB+XJUHGWIjzv0A9viMBy61CeE29k8xk8jzTTBd8xN+U YI9+c5YKsMCYwKjUo4NPtrK/WDcd0jxezdIexoE8= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Lars-Peter Clausen , Stable@vger.kernel.org, Jonathan Cameron Subject: [PATCH 5.6 089/167] iio: xilinx-xadc: Make sure not exceed maximum samplerate Date: Tue, 28 Apr 2020 20:24:25 +0200 Message-Id: <20200428182236.228366958@linuxfoundation.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200428182225.451225420@linuxfoundation.org> References: <20200428182225.451225420@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Lars-Peter Clausen commit 3b7f9dbb827ce8680b98490215e698b6079a9ec5 upstream. The XADC supports a samplerate of up to 1MSPS. Unfortunately the hardware does not have a FIFO, which means it generates an interrupt for each conversion sequence. At one 1MSPS this creates an interrupt storm that causes the system to soft-lock. For this reason the driver limits the maximum samplerate to 150kSPS. Currently this check is only done when setting a new samplerate. But it is also possible that the initial samplerate configured in the FPGA bitstream exceeds the limit. In this case when starting to capture data without first changing the samplerate the system can overload. To prevent this check the currently configured samplerate in the probe function and reduce it to the maximum if necessary. Signed-off-by: Lars-Peter Clausen Fixes: bdc8cda1d010 ("iio:adc: Add Xilinx XADC driver") Cc: Signed-off-by: Jonathan Cameron Signed-off-by: Greg Kroah-Hartman --- drivers/iio/adc/xilinx-xadc-core.c | 78 ++++++++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 18 deletions(-) --- a/drivers/iio/adc/xilinx-xadc-core.c +++ b/drivers/iio/adc/xilinx-xadc-core.c @@ -102,6 +102,16 @@ static const unsigned int XADC_ZYNQ_UNMA #define XADC_FLAGS_BUFFERED BIT(0) +/* + * The XADC hardware supports a samplerate of up to 1MSPS. Unfortunately it does + * not have a hardware FIFO. Which means an interrupt is generated for each + * conversion sequence. At 1MSPS sample rate the CPU in ZYNQ7000 is completely + * overloaded by the interrupts that it soft-lockups. For this reason the driver + * limits the maximum samplerate 150kSPS. At this rate the CPU is fairly busy, + * but still responsive. + */ +#define XADC_MAX_SAMPLERATE 150000 + static void xadc_write_reg(struct xadc *xadc, unsigned int reg, uint32_t val) { @@ -834,11 +844,27 @@ static const struct iio_buffer_setup_ops .postdisable = &xadc_postdisable, }; +static int xadc_read_samplerate(struct xadc *xadc) +{ + unsigned int div; + uint16_t val16; + int ret; + + ret = xadc_read_adc_reg(xadc, XADC_REG_CONF2, &val16); + if (ret) + return ret; + + div = (val16 & XADC_CONF2_DIV_MASK) >> XADC_CONF2_DIV_OFFSET; + if (div < 2) + div = 2; + + return xadc_get_dclk_rate(xadc) / div / 26; +} + static int xadc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long info) { struct xadc *xadc = iio_priv(indio_dev); - unsigned int div; uint16_t val16; int ret; @@ -891,41 +917,31 @@ static int xadc_read_raw(struct iio_dev *val = -((273150 << 12) / 503975); return IIO_VAL_INT; case IIO_CHAN_INFO_SAMP_FREQ: - ret = xadc_read_adc_reg(xadc, XADC_REG_CONF2, &val16); - if (ret) + ret = xadc_read_samplerate(xadc); + if (ret < 0) return ret; - div = (val16 & XADC_CONF2_DIV_MASK) >> XADC_CONF2_DIV_OFFSET; - if (div < 2) - div = 2; - - *val = xadc_get_dclk_rate(xadc) / div / 26; - + *val = ret; return IIO_VAL_INT; default: return -EINVAL; } } -static int xadc_write_raw(struct iio_dev *indio_dev, - struct iio_chan_spec const *chan, int val, int val2, long info) +static int xadc_write_samplerate(struct xadc *xadc, int val) { - struct xadc *xadc = iio_priv(indio_dev); unsigned long clk_rate = xadc_get_dclk_rate(xadc); unsigned int div; if (!clk_rate) return -EINVAL; - if (info != IIO_CHAN_INFO_SAMP_FREQ) - return -EINVAL; - if (val <= 0) return -EINVAL; /* Max. 150 kSPS */ - if (val > 150000) - val = 150000; + if (val > XADC_MAX_SAMPLERATE) + val = XADC_MAX_SAMPLERATE; val *= 26; @@ -938,7 +954,7 @@ static int xadc_write_raw(struct iio_dev * limit. */ div = clk_rate / val; - if (clk_rate / div / 26 > 150000) + if (clk_rate / div / 26 > XADC_MAX_SAMPLERATE) div++; if (div < 2) div = 2; @@ -949,6 +965,17 @@ static int xadc_write_raw(struct iio_dev div << XADC_CONF2_DIV_OFFSET); } +static int xadc_write_raw(struct iio_dev *indio_dev, + struct iio_chan_spec const *chan, int val, int val2, long info) +{ + struct xadc *xadc = iio_priv(indio_dev); + + if (info != IIO_CHAN_INFO_SAMP_FREQ) + return -EINVAL; + + return xadc_write_samplerate(xadc, val); +} + static const struct iio_event_spec xadc_temp_events[] = { { .type = IIO_EV_TYPE_THRESH, @@ -1234,6 +1261,21 @@ static int xadc_probe(struct platform_de if (ret) goto err_free_samplerate_trigger; + /* + * Make sure not to exceed the maximum samplerate since otherwise the + * resulting interrupt storm will soft-lock the system. + */ + if (xadc->ops->flags & XADC_FLAGS_BUFFERED) { + ret = xadc_read_samplerate(xadc); + if (ret < 0) + goto err_free_samplerate_trigger; + if (ret > XADC_MAX_SAMPLERATE) { + ret = xadc_write_samplerate(xadc, XADC_MAX_SAMPLERATE); + if (ret < 0) + goto err_free_samplerate_trigger; + } + } + ret = request_irq(xadc->irq, xadc->ops->interrupt_handler, 0, dev_name(&pdev->dev), indio_dev); if (ret)