From patchwork Sun May 21 22:59:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Artur Rojek X-Patchwork-Id: 96942 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp1093511vqo; Sun, 21 May 2023 16:07:23 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5Uk1GnlGJ3NVEWE5vAt9C9ld/0LK+QTIGWCNie2b8oMioknNYxD8cq4XUjx0mrCUNz/5rw X-Received: by 2002:a05:6a20:a120:b0:103:7b79:1506 with SMTP id q32-20020a056a20a12000b001037b791506mr9769008pzk.24.1684710443538; Sun, 21 May 2023 16:07:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1684710443; cv=none; d=google.com; s=arc-20160816; b=UgK/KpzPD6tzaDErDhigfxhzi+Q1SztP+gHiazdR7SpeIbl4Y9phuocjD9UJdr9bAl 74PT0aJ4mHKhtm7OlK7x6Ao8LBe4uNcxjVODFzC2oXe9ZRPB3ekCqAmcmInwb5EaYtbJ 1mVj0wB7Lve8DVY7Wttyf6DrEvWhRynMNjUDIexABogTKLH5cfvv4CJ9aTTpBzdEC1Sm paPkU2Ync1QibYGBbpGPlbDpeKZBWm9Uw843BgodH9ZudZxESv68NHe0u/GqrdFDPUZY 5x1zK1doqoQI7xOFxzKdmtt99RyUF9L4XGeBMxJcmz1uqK0lU8Rymtr5gsucNMp5SjpM DrOg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=LrB+fvPvvZ3r2mY8RpmQNKLa3SATQwbfcD3rDBy5psc=; b=dKxEjmqgYWiVD+DCEBbIpbHKLwirURLRoCOucZg4VHMg7p4acr8nax+Ec6JMVBQ+4m IfCYqFICwhIvATNCj0z9JFEiXP6Ix05ICiYW4WRrjYg241JbFRRAFFMRt/RFTcmbzKUX xLC3ptxyrsqYXzA63S1z2lMnPdTRyz9LogM6/kXBO8VwwQjD2kM85VnNTC3UflPSpOkb OwJj5SwOnfiCl1WvYUKoInCCG/StgXM9M/5oh++1tDo9xLltBgZYR6sRuduwlhiBTFV9 yXS5e+YUNJEX48hZ8Pj7IYOU4Enof1mMGAHtt6aFZTfvq/beSyI0KXEZk1pirBk8Dnkd JlAQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id o21-20020a637315000000b00527b90936b8si3769279pgc.38.2023.05.21.16.07.11; Sun, 21 May 2023 16:07:23 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231528AbjEUW74 (ORCPT + 99 others); Sun, 21 May 2023 18:59:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50238 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231329AbjEUW7u (ORCPT ); Sun, 21 May 2023 18:59:50 -0400 Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [IPv6:2001:4b98:dc4:8::225]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B36CBBE; Sun, 21 May 2023 15:59:48 -0700 (PDT) Received: (Authenticated sender: contact@artur-rojek.eu) by mail.gandi.net (Postfix) with ESMTPSA id 6424B1C0003; Sun, 21 May 2023 22:59:45 +0000 (UTC) From: Artur Rojek To: Paul Cercueil , Jonathan Cameron , Dmitry Torokhov , Chris Morgan , Andy Shevchenko Cc: linux-mips@vger.kernel.org, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, Artur Rojek Subject: [PATCH v2 1/2] iio/adc: ingenic: Fix channel offsets in buffer Date: Mon, 22 May 2023 00:59:00 +0200 Message-Id: <20230521225901.388455-2-contact@artur-rojek.eu> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230521225901.388455-1-contact@artur-rojek.eu> References: <20230521225901.388455-1-contact@artur-rojek.eu> MIME-Version: 1.0 X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766546938365455894?= X-GMAIL-MSGID: =?utf-8?q?1766546938365455894?= Consumers expect the buffer to only contain enabled channels. While preparing the buffer, the driver makes two mistakes: 1) It inserts empty data for disabled channels. 2) Each ADC readout contains samples for two 16-bit channels. If either of them is active, the whole 32-bit sample is pushed into the buffer as-is. Both of those issues cause the active channels to appear at the wrong offsets in the buffer. Fix the above by demuxing samples for active channels only. This has remained unnoticed, as all the consumers so far were only using channels 0 and 1, leaving them unaffected by changes introduced in this commit. Signed-off-by: Artur Rojek Tested-by: Paul Cercueil --- v2: - demux active channels from ADC readouts - clarify in the commit description that this patch doesn't impact existing consumers of this driver drivers/iio/adc/ingenic-adc.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/iio/adc/ingenic-adc.c b/drivers/iio/adc/ingenic-adc.c index a7325dbbb99a..093710a7ad4c 100644 --- a/drivers/iio/adc/ingenic-adc.c +++ b/drivers/iio/adc/ingenic-adc.c @@ -802,13 +802,19 @@ static irqreturn_t ingenic_adc_irq(int irq, void *data) struct ingenic_adc *adc = iio_priv(iio_dev); unsigned long mask = iio_dev->active_scan_mask[0]; unsigned int i; - u32 tdat[3]; - - for (i = 0; i < ARRAY_SIZE(tdat); mask >>= 2, i++) { - if (mask & 0x3) - tdat[i] = readl(adc->base + JZ_ADC_REG_ADTCH); - else - tdat[i] = 0; + u16 tdat[6]; + u32 val; + + memset(tdat, 0, ARRAY_SIZE(tdat)); + for (i = 0; mask && i < ARRAY_SIZE(tdat); mask >>= 2) { + if (mask & 0x3) { + val = readl(adc->base + JZ_ADC_REG_ADTCH); + /* Two channels per sample. Demux active. */ + if (mask & BIT(0)) + tdat[i++] = val & 0xffff; + if (mask & BIT(1)) + tdat[i++] = val >> 16; + } } iio_push_to_buffers(iio_dev, tdat); From patchwork Sun May 21 22:59:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Artur Rojek X-Patchwork-Id: 96943 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a59:b0ea:0:b0:3b6:4342:cba0 with SMTP id b10csp1093581vqo; Sun, 21 May 2023 16:07:32 -0700 (PDT) X-Google-Smtp-Source: ACHHUZ5YVVkRvzLhF1QnDrIMsBAhClOedze1jQOdZuu8z3RyEywaDc+yPGyQ25gbvnRrYVeqR3il X-Received: by 2002:a17:90a:a415:b0:253:3e9d:f920 with SMTP id y21-20020a17090aa41500b002533e9df920mr8515111pjp.3.1684710452290; Sun, 21 May 2023 16:07:32 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1684710452; cv=none; d=google.com; s=arc-20160816; b=B6SBT6w/EmRoE/HecUy6hE5JNFI+y2IigGYchn1T/R4o2vR4zbrG3gL0g9pfDlnK3e EqOsyoJ7zfyvymFBq6PBs/tNikr56NpqRo5v88XY7qeTTWqnC1PBCsEftveXOyL8ojh8 W812iJcMnrYxr6vLUqi2Qc/zzz9LZ4r7I/BYfLmJ3N90GV9R0rEdLlHLz09gA1gCoHDc piuxcDp6Fai2IaXAEr/UKRDRucPle9WmL1t5st+jOV5GdYyb/TpYJhw6v7KUyeG5CHPv Rol22wm1SYFnBwY2iuITuO3FncQeCcJEMAy/Jc6lyY1tUx6snL0S8Yw+KcP1O67xALiZ MyOA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=U9PPFUmS0iqeHq2ypShrKgFa0IDZTuKYUyeOYT2x1mU=; b=Dbcw9Da9O1+sQ6rGEAxPpn1UzZPJKAYEAlWG7gnmsjdCiG5VX3o34SPhUP4PJAbnK3 p/VB5Z4pFnJdEvo9apB/1OLM0VtAcOQVbSLxCugUo+DqnsvpY/Iu1paDAxu9qn5NQR2k iYngQTfYi36rAeYjY5qRLQ5NcOu8epHFdpzvPoGWiJiiG+pM2lNOO2UaEZT13/A0xVDD pXNm6eldJz5qGOUyut7DBcVGMaDuuvhE1KsxtKGt1n/s99nHg6t0pHtDDW5iZg2VNAN6 TnGVNsjRpJg4TaNK09lEEVy4zjrf6A/2XEq4cQr5EtSzHg2bXyI8qrIziMY4Oha3JG8F 8ijg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id v7-20020a17090a6b0700b0024bccf6609dsi482055pjj.114.2023.05.21.16.07.20; Sun, 21 May 2023 16:07:32 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231547AbjEUXAA (ORCPT + 99 others); Sun, 21 May 2023 19:00:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:50252 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231534AbjEUW7v (ORCPT ); Sun, 21 May 2023 18:59:51 -0400 Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 17AEAC1; Sun, 21 May 2023 15:59:49 -0700 (PDT) Received: (Authenticated sender: contact@artur-rojek.eu) by mail.gandi.net (Postfix) with ESMTPSA id 35D0E1C0004; Sun, 21 May 2023 22:59:47 +0000 (UTC) From: Artur Rojek To: Paul Cercueil , Jonathan Cameron , Dmitry Torokhov , Chris Morgan , Andy Shevchenko Cc: linux-mips@vger.kernel.org, linux-iio@vger.kernel.org, linux-kernel@vger.kernel.org, linux-input@vger.kernel.org, Artur Rojek Subject: [PATCH v2 2/2] input: joystick: Fix buffer data parsing Date: Mon, 22 May 2023 00:59:01 +0200 Message-Id: <20230521225901.388455-3-contact@artur-rojek.eu> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230521225901.388455-1-contact@artur-rojek.eu> References: <20230521225901.388455-1-contact@artur-rojek.eu> MIME-Version: 1.0 X-Spam-Status: No, score=-2.6 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1766546947303103313?= X-GMAIL-MSGID: =?utf-8?q?1766546947303103313?= Don't try to access buffer data of a channel by its scan index. Instead, calculate its offset in the buffer. This is necessary, as the scan index of a channel does not represent its position in a buffer - the buffer will contain data for enabled channels only, affecting data offsets and alignment. While at it, also fix minor style issue in probe. Reported-by: Chris Morgan Closes: https://lore.kernel.org/linux-input/20220408212857.9583-1-macroalpha82@gmail.com/ Signed-off-by: Artur Rojek Tested-by: Paul Cercueil --- v2: - provide new implementation for calculating channel offsets - cache the resulting offsets - fix minor style issue in probe - drop the "Fixes" tag drivers/input/joystick/adc-joystick.c | 102 +++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 12 deletions(-) diff --git a/drivers/input/joystick/adc-joystick.c b/drivers/input/joystick/adc-joystick.c index c0deff5d4282..2f9f0cae8f95 100644 --- a/drivers/input/joystick/adc-joystick.c +++ b/drivers/input/joystick/adc-joystick.c @@ -10,6 +10,7 @@ #include #include #include +#include #include @@ -25,6 +26,7 @@ struct adc_joystick { struct iio_cb_buffer *buffer; struct adc_joystick_axis *axes; struct iio_channel *chans; + int *offsets; int num_chans; bool polled; }; @@ -47,35 +49,38 @@ static int adc_joystick_handle(const void *data, void *private) { struct adc_joystick *joy = private; enum iio_endian endianness; - int bytes, msb, val, idx, i; - const u16 *data_u16; + int bytes, msb, val, off, i; + const u8 *chan_data; bool sign; bytes = joy->chans[0].channel->scan_type.storagebits >> 3; for (i = 0; i < joy->num_chans; ++i) { - idx = joy->chans[i].channel->scan_index; endianness = joy->chans[i].channel->scan_type.endianness; msb = joy->chans[i].channel->scan_type.realbits - 1; sign = tolower(joy->chans[i].channel->scan_type.sign) == 's'; + off = joy->offsets[i]; + + if (off < 0) + return -EINVAL; + + chan_data = (const u8 *)data + off; switch (bytes) { case 1: - val = ((const u8 *)data)[idx]; + val = *chan_data; break; case 2: - data_u16 = (const u16 *)data + idx; - /* * Data is aligned to the sample size by IIO core. * Call `get_unaligned_xe16` to hide type casting. */ if (endianness == IIO_BE) - val = get_unaligned_be16(data_u16); + val = get_unaligned_be16(chan_data); else if (endianness == IIO_LE) - val = get_unaligned_le16(data_u16); + val = get_unaligned_le16(chan_data); else /* IIO_CPU */ - val = *data_u16; + val = *(const u16 *)chan_data; break; default: return -EINVAL; @@ -94,6 +99,69 @@ static int adc_joystick_handle(const void *data, void *private) return 0; } +static int adc_joystick_si_cmp(const void *a, const void *b, const void *priv) +{ + const struct iio_channel *chans = priv; + + return chans[*(int *)a].channel->scan_index - + chans[*(int *)b].channel->scan_index; +} + +static int *adc_joystick_get_chan_offsets(struct iio_channel *chans, int count) +{ + struct iio_dev *indio_dev = chans[0].indio_dev; + const struct iio_chan_spec *ch; + int *offsets, *si_order; + int idx, i, si, length, offset = 0; + + offsets = kmalloc_array(count, sizeof(int), GFP_KERNEL); + if (!offsets) + return ERR_PTR(-ENOMEM); + + si_order = kmalloc_array(count, sizeof(int), GFP_KERNEL); + if (!si_order) { + kfree(offsets); + return ERR_PTR(-ENOMEM); + } + + for (i = 0; i < count; ++i) + si_order[i] = i; + /* Channels in buffer are ordered by scan index. Sort to match that. */ + sort_r(si_order, count, sizeof(int), adc_joystick_si_cmp, NULL, chans); + + for (i = 0; i < count; ++i) { + idx = si_order[i]; + ch = chans[idx].channel; + si = ch->scan_index; + + if (si < 0 || !test_bit(si, indio_dev->active_scan_mask)) { + offsets[idx] = -1; + continue; + } + + /* Channels sharing scan indices also share the samples. */ + if (idx > 0 && si == chans[idx - 1].channel->scan_index) { + offsets[idx] = offsets[idx - 1]; + continue; + } + + offsets[idx] = offset; + + length = ch->scan_type.storagebits / 8; + if (ch->scan_type.repeat > 1) + length *= ch->scan_type.repeat; + + /* Account for channel alignment. */ + if (offset % length) + offset += length - (offset % length); + offset += length; + } + + kfree(si_order); + + return offsets; +} + static int adc_joystick_open(struct input_dev *dev) { struct adc_joystick *joy = input_get_drvdata(dev); @@ -101,10 +169,19 @@ static int adc_joystick_open(struct input_dev *dev) int ret; ret = iio_channel_start_all_cb(joy->buffer); - if (ret) + if (ret) { dev_err(devp, "Unable to start callback buffer: %d\n", ret); + return ret; + } - return ret; + joy->offsets = adc_joystick_get_chan_offsets(joy->chans, + joy->num_chans); + if (IS_ERR(joy->offsets)) { + dev_err(devp, "Unable to allocate channel offsets\n"); + return PTR_ERR(joy->offsets); + } + + return 0; } static void adc_joystick_close(struct input_dev *dev) @@ -112,6 +189,7 @@ static void adc_joystick_close(struct input_dev *dev) struct adc_joystick *joy = input_get_drvdata(dev); iio_channel_stop_all_cb(joy->buffer); + kfree(joy->offsets); } static void adc_joystick_cleanup(void *data) @@ -269,7 +347,7 @@ static int adc_joystick_probe(struct platform_device *pdev) error = devm_add_action_or_reset(dev, adc_joystick_cleanup, joy->buffer); - if (error) { + if (error) { dev_err(dev, "Unable to add action\n"); return error; }