Received: by 2002:a25:1985:0:0:0:0:0 with SMTP id 127csp4468535ybz; Tue, 28 Apr 2020 11:48:47 -0700 (PDT) X-Google-Smtp-Source: APiQypJgSnzIqUGO51yG2d165HLzSKr7r57n9i/dpw0hzzNX+Ub3drXVW8zPxdPGZ9X14d9gVenU X-Received: by 2002:a17:907:6fc:: with SMTP id yh28mr27056924ejb.326.1588099727397; Tue, 28 Apr 2020 11:48:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1588099727; cv=none; d=google.com; s=arc-20160816; b=jqdleP5pF/VWODmDGQy8zij6jvjy3MY+LGEOnXMWQppcG9+Wd17V54Of/fDVxcjpWY jXG1WPof6JFp16pOBsxKlC265bbCWUkahzlKLLvzQoYWhrbqfwQwpKvd+w+f8bpRGs20 k7GH6jS3xyNmpNZCCCxJGORf+gEyiSsAvs5RoGWBZtSs4FagRY72tHOODW5sk6Qe0jq7 KthU8c9gtgyiJ/XM1Mtn6p5kNLXprwa+c7ORvaGs1CBXmEl+bBHSlpHZiVmK+32BuoCx QzKhbKFzZdFIaZuiYYszrXy0uMganRu8kdZCmx4GxhxCgapkkqbyEYrTF1DjYGPOEwpv HlFQ== 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=fL/Vs/QF/+OXpQZQmvUNqMoAmoyuw37I+U4h3JduK3w=; b=cPH+e9LSvonKEo6rwoUxbqviW6myTRQ4rFUNpJM6nigrapSecrE6dCl9ph0w1fe+PT pniMFv58hX2WdTBdJW/Pv8Z6QeobnA9G4xhqhfx/muQxna56VybUOxtivuj1luv2Msw0 aJv2DOEHuL41uV5cJq4sqsQjUvgBif4puekWunFYn8gRkrhHSf2vZOn2Kd4XBOeNM66t nXSjF269d2XztYA3iUy21+fhyS2GIdFBgtHd7CyhS+nMZ5sv2XuVA3Xa7PE9VSOH1USf qCwVnpuN8xD0RNs2FEDoJb+AqhM1w6++SUDeRYvP9yMhDPrtFdFa2/0au0mCmDueiX3x jlkw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=Cgs2CCRW; 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 g7si2266470edn.251.2020.04.28.11.48.24; Tue, 28 Apr 2020 11:48:47 -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=Cgs2CCRW; 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 S1731103AbgD1SmZ (ORCPT + 99 others); Tue, 28 Apr 2020 14:42:25 -0400 Received: from mail.kernel.org ([198.145.29.99]:34284 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731098AbgD1SmW (ORCPT ); Tue, 28 Apr 2020 14:42:22 -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 5EC7420575; Tue, 28 Apr 2020 18:42:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1588099341; bh=yy+L2TaQ1fzV8FxZkoyYt4yIaFb/9edhiehY4/YtF6I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Cgs2CCRW8gxaK0bA00xxIWGho7YdzpWvakiBhDqaOrplbHcZUGL7N026b0RRfyOx2 aaa5HvrJAltTyVPqSXhMoRDDZaqLxCGgd0lvYXk6GYYC6XnKPmF/qowSInZ6Bg/gwP jBtGEgpYP7xiBHJhufRqKtECsSkP4u4njqQgo2HA= 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.4 094/168] iio: xilinx-xadc: Make sure not exceed maximum samplerate Date: Tue, 28 Apr 2020 20:24:28 +0200 Message-Id: <20200428182244.202435826@linuxfoundation.org> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20200428182231.704304409@linuxfoundation.org> References: <20200428182231.704304409@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, @@ -1236,6 +1263,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)