Message ID | 20230316155734.3191577-2-ckeepax@opensource.cirrus.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:604a:0:0:0:0:0 with SMTP id j10csp577767wrt; Thu, 16 Mar 2023 09:26:22 -0700 (PDT) X-Google-Smtp-Source: AK7set9G6nAaYQlAq81kPQN2zCmAb2mRpfg3vvlk1NbSMxSdIeZLMkkhCIEe/lD2CSfcNDc/mtqB X-Received: by 2002:a05:6a20:3948:b0:cc:9ca2:8b5f with SMTP id r8-20020a056a20394800b000cc9ca28b5fmr5214106pzg.15.1678983982387; Thu, 16 Mar 2023 09:26:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1678983982; cv=none; d=google.com; s=arc-20160816; b=sA5WEgIbGmpPbJpNHflXT9Yj6ePoMXep04rnmIs62hoBkARPd+9wap5POMZp9CiZho viK460+lCojK88MAUkScHLe54CSUF80hdbxroIjqjZCVYJ8tHsPJNiT2hgjLn5sd6GZe qZUYbZwmHvxCi7vcHA1/d2hevlmt3AuWNGgRFzx/JQLDmyshFYV2Jjqci31gTM05toEM P6c8YmANpOlPvVi3q+Y36M3vha4/IhaNG6lb3NGcFVuAcwC8Q3CvCVL+LQr2OjX5I/gV sC15+Q15SsCeekn9eyTVgOIbQOyAEJr49vO6xWHcfk62dHE5/92YnZ2pX8uEdMNwOkQ0 iKUA== 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 :dkim-signature; bh=zwa+Kz3z5JsstvJyyjsKd/9rebLnLWbVJ5G8ya5H37k=; b=TN6/OxRg62oK/eJdgSRTAMmNIhbcgTdDt8PjZ4wKzSyNN5DX9K/LyKlPvDmgvuqq1U kz+Bc5ktDuzPXYx40KWKxWnmCKGiP0L3x2o/QA6X28kiiRTSquFMQJWHc7WT1ode2Sw6 bk8dLe9wVt5pUWkeaRqljGjdahNLbx53Yw9j/9PgVlJXn0wkjDfp3pqV7l2mwStl1M1d svNCJpttjWmX7A3qz1RT3O5BIcOFtBjMrJloOX+0Tv1ODbFs4i5nt5bTYo0o1dJhIAv9 2vK/yJeJnTYC2PdOU90VnArp4vdmbFiLH9wotXu56+J1c1oLrcKJSZdjfs2hUIO46cDi 6bwg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=TNPgfDSs; 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; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id w4-20020a656944000000b004ded572f110si561590pgq.870.2023.03.16.09.26.07; Thu, 16 Mar 2023 09:26:22 -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; dkim=pass header.i=@cirrus.com header.s=PODMain02222019 header.b=TNPgfDSs; 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; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=cirrus.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231603AbjCPP6K (ORCPT <rfc822;pwkd43@gmail.com> + 99 others); Thu, 16 Mar 2023 11:58:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:34786 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229629AbjCPP6H (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Thu, 16 Mar 2023 11:58:07 -0400 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 5CC4E14E8B for <linux-kernel@vger.kernel.org>; Thu, 16 Mar 2023 08:57:59 -0700 (PDT) Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 32GFpjVl015162; Thu, 16 Mar 2023 10:57:36 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=from : to : cc : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding : content-type; s=PODMain02222019; bh=zwa+Kz3z5JsstvJyyjsKd/9rebLnLWbVJ5G8ya5H37k=; b=TNPgfDSs79sO1vKqlcoH5bW71KMuMKW0xiODu1gRUUiJCQOz/6O6hnk3tafiC9vMv6Wz VaqAAK/4pytrLZbrUDtPkTchkd3dcxPLPstc+D5Gsy1IJNQ8cEDvc8xoQkJ4QTAqmp3l 4juR8sOZUfiJLgS2Jwyz76Sr6KyFDDEgy6dyLiXuW0JFQmMuCwTyGtPaZ0BPgGzfz7Du bY8oCJ/KoS5+6ZCXtHFmHh/nO4Q/W1MW746VUnVxn4gmaTmTDcD50C0ynNXIdnNTZv3a GABlEvnoQHEHhgxJ9pEVz9//KFoQqdLz4DN5Bfge8o0A5BJBN0RAMS4kpWbXiLIsooXa yw== Received: from ediex01.ad.cirrus.com ([84.19.233.68]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 3pbs2nrxxu-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Thu, 16 Mar 2023 10:57:35 -0500 Received: from ediex02.ad.cirrus.com (198.61.84.81) by ediex01.ad.cirrus.com (198.61.84.80) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.25; Thu, 16 Mar 2023 10:57:34 -0500 Received: from ediswmail.ad.cirrus.com (198.61.86.93) by anon-ediex02.ad.cirrus.com (198.61.84.81) with Microsoft SMTP Server id 15.2.1118.25 via Frontend Transport; Thu, 16 Mar 2023 10:57:34 -0500 Received: from algalon.ad.cirrus.com (algalon.ad.cirrus.com [198.90.251.122]) by ediswmail.ad.cirrus.com (Postfix) with ESMTP id 1EAD311D4; Thu, 16 Mar 2023 15:57:34 +0000 (UTC) From: Charles Keepax <ckeepax@opensource.cirrus.com> To: <vkoul@kernel.org> CC: <yung-chuan.liao@linux.intel.com>, <pierre-louis.bossart@linux.intel.com>, <sanyog.r.kale@intel.com>, <alsa-devel@alsa-project.org>, <linux-kernel@vger.kernel.org>, <patches@opensource.cirrus.com> Subject: [PATCH 2/2] soundwire: bus: Update sdw_nread/nwrite_no_pm to handle page boundaries Date: Thu, 16 Mar 2023 15:57:34 +0000 Message-ID: <20230316155734.3191577-2-ckeepax@opensource.cirrus.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230316155734.3191577-1-ckeepax@opensource.cirrus.com> References: <20230316155734.3191577-1-ckeepax@opensource.cirrus.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-Proofpoint-GUID: p0Dgp2C0Dmwbcqi8GtGVhGNykvjqSFYc X-Proofpoint-ORIG-GUID: p0Dgp2C0Dmwbcqi8GtGVhGNykvjqSFYc X-Proofpoint-Spam-Reason: safe X-Spam-Status: No, score=-2.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_EF,RCVD_IN_DNSWL_LOW,SPF_HELO_NONE,SPF_PASS 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: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1760542308513012476?= X-GMAIL-MSGID: =?utf-8?q?1760542308513012476?= |
Series |
[1/2] soundwire: bus: Remove now outdated comments on no_pm IO
|
|
Commit Message
Charles Keepax
March 16, 2023, 3:57 p.m. UTC
Currently issuing a sdw_nread/nwrite_no_pm across a page boundary
will silently fail to write correctly as nothing updates the page
registers, meaning the same page of the chip will get rewritten
with each successive page of data.
As the sdw_msg structure contains page information it seems
reasonable that a single sdw_msg should always be within one
page. It is also mostly simpler to handle the paging at the
bus level rather than each master having to handle it in their
xfer_msg callback.
As such add handling to the bus code to split up a transfer into
multiple sdw_msg's when they go across page boundaries.
Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com>
---
drivers/soundwire/bus.c | 47 +++++++++++++++++++++++------------------
1 file changed, 26 insertions(+), 21 deletions(-)
Comments
On 3/16/23 10:57, Charles Keepax wrote: > Currently issuing a sdw_nread/nwrite_no_pm across a page boundary > will silently fail to write correctly as nothing updates the page > registers, meaning the same page of the chip will get rewritten > with each successive page of data. > > As the sdw_msg structure contains page information it seems > reasonable that a single sdw_msg should always be within one > page. It is also mostly simpler to handle the paging at the > bus level rather than each master having to handle it in their > xfer_msg callback. > > As such add handling to the bus code to split up a transfer into > multiple sdw_msg's when they go across page boundaries. This sounds good but we need to clarify that the multiple sdw_msg's will not necessarily be sent one after the other, the msg_lock is held in the sdw_transfer() function, so there should be no expectation that e.g. one big chunk of firmware code can be sent without interruption. I also wonder if we should have a lower bar than the page to avoid hogging the bus with large read/write transactions. If there are multiple devices on the same link and one of them signals an alert status while a large transfer is on-going, the alert handling will mechanically be delayed by up to a page - that's 32k reads/writes, isn't it? > Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> > --- > drivers/soundwire/bus.c | 47 +++++++++++++++++++++++------------------ > 1 file changed, 26 insertions(+), 21 deletions(-) > > diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c > index 3c67266f94834..bdd251e871694 100644 > --- a/drivers/soundwire/bus.c > +++ b/drivers/soundwire/bus.c > @@ -386,37 +386,42 @@ int sdw_fill_msg(struct sdw_msg *msg, struct sdw_slave *slave, > * Read/Write IO functions. > */ > > -int sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) > +static int sdw_ntransfer_no_pm(struct sdw_slave *slave, u32 addr, u8 flags, > + size_t count, u8 *val) > { > struct sdw_msg msg; > + size_t size; > int ret; > > - ret = sdw_fill_msg(&msg, slave, addr, count, > - slave->dev_num, SDW_MSG_FLAG_READ, val); > - if (ret < 0) > - return ret; > + while (count) { > + // Only handle bytes up to next page boundary > + size = min(count, (SDW_REGADDR + 1) - (addr & SDW_REGADDR)); > > - ret = sdw_transfer(slave->bus, &msg); > - if (slave->is_mockup_device) > - ret = 0; > - return ret; > + ret = sdw_fill_msg(&msg, slave, addr, size, slave->dev_num, flags, val); > + if (ret < 0) > + return ret; > + > + ret = sdw_transfer(slave->bus, &msg); > + if (ret < 0 && !slave->is_mockup_device) > + return ret; > + > + addr += size; > + val += size; > + count -= size; > + } > + > + return 0; > +} > + > +int sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) > +{ > + return sdw_ntransfer_no_pm(slave, addr, SDW_MSG_FLAG_READ, count, val); > } > EXPORT_SYMBOL(sdw_nread_no_pm); > > int sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val) > { > - struct sdw_msg msg; > - int ret; > - > - ret = sdw_fill_msg(&msg, slave, addr, count, > - slave->dev_num, SDW_MSG_FLAG_WRITE, (u8 *)val); > - if (ret < 0) > - return ret; > - > - ret = sdw_transfer(slave->bus, &msg); > - if (slave->is_mockup_device) > - ret = 0; > - return ret; > + return sdw_ntransfer_no_pm(slave, addr, SDW_MSG_FLAG_WRITE, count, (u8 *)val); > } > EXPORT_SYMBOL(sdw_nwrite_no_pm); >
Hi Charles, I love your patch! Perhaps something to improve: [auto build test WARNING on linus/master] [also build test WARNING on v6.3-rc2 next-20230316] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Charles-Keepax/soundwire-bus-Update-sdw_nread-nwrite_no_pm-to-handle-page-boundaries/20230317-000005 patch link: https://lore.kernel.org/r/20230316155734.3191577-2-ckeepax%40opensource.cirrus.com patch subject: [PATCH 2/2] soundwire: bus: Update sdw_nread/nwrite_no_pm to handle page boundaries config: mips-randconfig-r022-20230312 (https://download.01.org/0day-ci/archive/20230317/202303170724.NdbQwtQo-lkp@intel.com/config) compiler: clang version 17.0.0 (https://github.com/llvm/llvm-project 67409911353323ca5edf2049ef0df54132fa1ca7) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install mips cross compiling tool for clang build # apt-get install binutils-mipsel-linux-gnu # https://github.com/intel-lab-lkp/linux/commit/6944d7175bd15a9a16a411c57f200d3bcecd3c00 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Charles-Keepax/soundwire-bus-Update-sdw_nread-nwrite_no_pm-to-handle-page-boundaries/20230317-000005 git checkout 6944d7175bd15a9a16a411c57f200d3bcecd3c00 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=mips olddefconfig COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=mips SHELL=/bin/bash drivers/soundwire/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> | Link: https://lore.kernel.org/oe-kbuild-all/202303170724.NdbQwtQo-lkp@intel.com/ All warnings (new ones prefixed by >>): >> drivers/soundwire/bus.c:398:10: warning: comparison of distinct pointer types ('typeof (count) *' (aka 'unsigned int *') and 'typeof ((((((int)(sizeof(struct (unnamed struct at drivers/soundwire/bus.c:398:10))))) + (((~(((0UL)))) - ((((1UL))) << (0)) + 1) & (~(((0UL))) >> (32 - 1 - (14))))) + 1) - (addr & ((((int)(sizeof(struct (unnamed struct at drivers/soundwire/bus.c:398:10))))) + (((~(((0UL)))) - ((((1UL))) << (0)) + 1) & (~(((0UL))) >> (32 - 1 - (14))))))) *' (aka 'unsigned long *')) [-Wcompare-distinct-pointer-types] size = min(count, (SDW_REGADDR + 1) - (addr & SDW_REGADDR)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/minmax.h:67:19: note: expanded from macro 'min' #define min(x, y) __careful_cmp(x, y, <) ^~~~~~~~~~~~~~~~~~~~~~ include/linux/minmax.h:36:24: note: expanded from macro '__careful_cmp' __builtin_choose_expr(__safe_cmp(x, y), \ ^~~~~~~~~~~~~~~~ include/linux/minmax.h:26:4: note: expanded from macro '__safe_cmp' (__typecheck(x, y) && __no_side_effects(x, y)) ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:20:28: note: expanded from macro '__typecheck' (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1))) ~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~ 1 warning generated. vim +398 drivers/soundwire/bus.c 384 385 /* 386 * Read/Write IO functions. 387 */ 388 389 static int sdw_ntransfer_no_pm(struct sdw_slave *slave, u32 addr, u8 flags, 390 size_t count, u8 *val) 391 { 392 struct sdw_msg msg; 393 size_t size; 394 int ret; 395 396 while (count) { 397 // Only handle bytes up to next page boundary > 398 size = min(count, (SDW_REGADDR + 1) - (addr & SDW_REGADDR)); 399 400 ret = sdw_fill_msg(&msg, slave, addr, size, slave->dev_num, flags, val); 401 if (ret < 0) 402 return ret; 403 404 ret = sdw_transfer(slave->bus, &msg); 405 if (ret < 0 && !slave->is_mockup_device) 406 return ret; 407 408 addr += size; 409 val += size; 410 count -= size; 411 } 412 413 return 0; 414 } 415
Hi Charles, I love your patch! Perhaps something to improve: [auto build test WARNING on linus/master] [also build test WARNING on v6.3-rc2 next-20230316] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Charles-Keepax/soundwire-bus-Update-sdw_nread-nwrite_no_pm-to-handle-page-boundaries/20230317-000005 patch link: https://lore.kernel.org/r/20230316155734.3191577-2-ckeepax%40opensource.cirrus.com patch subject: [PATCH 2/2] soundwire: bus: Update sdw_nread/nwrite_no_pm to handle page boundaries config: i386-randconfig-a011-20230313 (https://download.01.org/0day-ci/archive/20230317/202303170749.83Yd8Oh0-lkp@intel.com/config) compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project f28c006a5895fc0e329fe15fead81e37457cb1d1) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # https://github.com/intel-lab-lkp/linux/commit/6944d7175bd15a9a16a411c57f200d3bcecd3c00 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review Charles-Keepax/soundwire-bus-Update-sdw_nread-nwrite_no_pm-to-handle-page-boundaries/20230317-000005 git checkout 6944d7175bd15a9a16a411c57f200d3bcecd3c00 # save the config file mkdir build_dir && cp config build_dir/.config COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 olddefconfig COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/soundwire/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> | Link: https://lore.kernel.org/oe-kbuild-all/202303170749.83Yd8Oh0-lkp@intel.com/ All warnings (new ones prefixed by >>): >> drivers/soundwire/bus.c:398:10: warning: comparison of distinct pointer types ('typeof (count) *' (aka 'unsigned int *') and 'typeof ((((((int)(sizeof(struct (unnamed struct at drivers/soundwire/bus.c:398:10))))) + (((~(((0UL)))) - ((((1UL))) << (0)) + 1) & (~(((0UL))) >> (32 - 1 - (14))))) + 1) - (addr & ((((int)(sizeof(struct (unnamed struct at drivers/soundwire/bus.c:398:10))))) + (((~(((0UL)))) - ((((1UL))) << (0)) + 1) & (~(((0UL))) >> (32 - 1 - (14))))))) *' (aka 'unsigned long *')) [-Wcompare-distinct-pointer-types] size = min(count, (SDW_REGADDR + 1) - (addr & SDW_REGADDR)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/minmax.h:67:19: note: expanded from macro 'min' #define min(x, y) __careful_cmp(x, y, <) ^~~~~~~~~~~~~~~~~~~~~~ include/linux/minmax.h:36:24: note: expanded from macro '__careful_cmp' __builtin_choose_expr(__safe_cmp(x, y), \ ^~~~~~~~~~~~~~~~ include/linux/minmax.h:26:4: note: expanded from macro '__safe_cmp' (__typecheck(x, y) && __no_side_effects(x, y)) ^~~~~~~~~~~~~~~~~ include/linux/minmax.h:20:28: note: expanded from macro '__typecheck' (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1))) ~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~ 1 warning generated. vim +398 drivers/soundwire/bus.c 384 385 /* 386 * Read/Write IO functions. 387 */ 388 389 static int sdw_ntransfer_no_pm(struct sdw_slave *slave, u32 addr, u8 flags, 390 size_t count, u8 *val) 391 { 392 struct sdw_msg msg; 393 size_t size; 394 int ret; 395 396 while (count) { 397 // Only handle bytes up to next page boundary > 398 size = min(count, (SDW_REGADDR + 1) - (addr & SDW_REGADDR)); 399 400 ret = sdw_fill_msg(&msg, slave, addr, size, slave->dev_num, flags, val); 401 if (ret < 0) 402 return ret; 403 404 ret = sdw_transfer(slave->bus, &msg); 405 if (ret < 0 && !slave->is_mockup_device) 406 return ret; 407 408 addr += size; 409 val += size; 410 count -= size; 411 } 412 413 return 0; 414 } 415
On Thu, Mar 16, 2023 at 01:46:57PM -0500, Pierre-Louis Bossart wrote: > > > On 3/16/23 10:57, Charles Keepax wrote: > > Currently issuing a sdw_nread/nwrite_no_pm across a page boundary > > will silently fail to write correctly as nothing updates the page > > registers, meaning the same page of the chip will get rewritten > > with each successive page of data. > > > > As the sdw_msg structure contains page information it seems > > reasonable that a single sdw_msg should always be within one > > page. It is also mostly simpler to handle the paging at the > > bus level rather than each master having to handle it in their > > xfer_msg callback. > > > > As such add handling to the bus code to split up a transfer into > > multiple sdw_msg's when they go across page boundaries. > > This sounds good but we need to clarify that the multiple sdw_msg's will > not necessarily be sent one after the other, the msg_lock is held in the > sdw_transfer() function, so there should be no expectation that e.g. one > big chunk of firmware code can be sent without interruption. > I will update the kdoc for nread/nwrite to specify that transactions that cross a page boundry are not expected to be atomic. > I also wonder if we should have a lower bar than the page to avoid > hogging the bus with large read/write transactions. If there are > multiple devices on the same link and one of them signals an alert > status while a large transfer is on-going, the alert handling will > mechanically be delayed by up to a page - that's 32k reads/writes, isn't it? > I think its 16k, but I would be inclined to say this is a separate fix. The current code will tie up the bus for longer than my fix does, since it only calls sdw_transfer once, and it will write the wrong registers whilst doing it. Also to be clear this wasn't found with super large transfers just medium sized ones that happened to cross a page boundry. If we want to add some transaction size capping that is really a new feature, this patch a bug fix. I would also be inclined to say if we are going to add transaction size capping, we probably want some property to specify what we are capping to. Thanks, Charles > > Signed-off-by: Charles Keepax <ckeepax@opensource.cirrus.com> > > --- > > drivers/soundwire/bus.c | 47 +++++++++++++++++++++++------------------ > > 1 file changed, 26 insertions(+), 21 deletions(-) > > > > diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c > > index 3c67266f94834..bdd251e871694 100644 > > --- a/drivers/soundwire/bus.c > > +++ b/drivers/soundwire/bus.c > > @@ -386,37 +386,42 @@ int sdw_fill_msg(struct sdw_msg *msg, struct sdw_slave *slave, > > * Read/Write IO functions. > > */ > > > > -int sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) > > +static int sdw_ntransfer_no_pm(struct sdw_slave *slave, u32 addr, u8 flags, > > + size_t count, u8 *val) > > { > > struct sdw_msg msg; > > + size_t size; > > int ret; > > > > - ret = sdw_fill_msg(&msg, slave, addr, count, > > - slave->dev_num, SDW_MSG_FLAG_READ, val); > > - if (ret < 0) > > - return ret; > > + while (count) { > > + // Only handle bytes up to next page boundary > > + size = min(count, (SDW_REGADDR + 1) - (addr & SDW_REGADDR)); > > > > - ret = sdw_transfer(slave->bus, &msg); > > - if (slave->is_mockup_device) > > - ret = 0; > > - return ret; > > + ret = sdw_fill_msg(&msg, slave, addr, size, slave->dev_num, flags, val); > > + if (ret < 0) > > + return ret; > > + > > + ret = sdw_transfer(slave->bus, &msg); > > + if (ret < 0 && !slave->is_mockup_device) > > + return ret; > > + > > + addr += size; > > + val += size; > > + count -= size; > > + } > > + > > + return 0; > > +} > > + > > +int sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) > > +{ > > + return sdw_ntransfer_no_pm(slave, addr, SDW_MSG_FLAG_READ, count, val); > > } > > EXPORT_SYMBOL(sdw_nread_no_pm); > > > > int sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val) > > { > > - struct sdw_msg msg; > > - int ret; > > - > > - ret = sdw_fill_msg(&msg, slave, addr, count, > > - slave->dev_num, SDW_MSG_FLAG_WRITE, (u8 *)val); > > - if (ret < 0) > > - return ret; > > - > > - ret = sdw_transfer(slave->bus, &msg); > > - if (slave->is_mockup_device) > > - ret = 0; > > - return ret; > > + return sdw_ntransfer_no_pm(slave, addr, SDW_MSG_FLAG_WRITE, count, (u8 *)val); > > } > > EXPORT_SYMBOL(sdw_nwrite_no_pm); > >
On 3/17/23 09:08, Charles Keepax wrote: > On Thu, Mar 16, 2023 at 01:46:57PM -0500, Pierre-Louis Bossart wrote: >> >> >> On 3/16/23 10:57, Charles Keepax wrote: >>> Currently issuing a sdw_nread/nwrite_no_pm across a page boundary >>> will silently fail to write correctly as nothing updates the page >>> registers, meaning the same page of the chip will get rewritten >>> with each successive page of data. >>> >>> As the sdw_msg structure contains page information it seems >>> reasonable that a single sdw_msg should always be within one >>> page. It is also mostly simpler to handle the paging at the >>> bus level rather than each master having to handle it in their >>> xfer_msg callback. >>> >>> As such add handling to the bus code to split up a transfer into >>> multiple sdw_msg's when they go across page boundaries. >> >> This sounds good but we need to clarify that the multiple sdw_msg's will >> not necessarily be sent one after the other, the msg_lock is held in the >> sdw_transfer() function, so there should be no expectation that e.g. one >> big chunk of firmware code can be sent without interruption. >> > > I will update the kdoc for nread/nwrite to specify that > transactions that cross a page boundry are not expected to be > atomic. Sounds good. >> I also wonder if we should have a lower bar than the page to avoid >> hogging the bus with large read/write transactions. If there are >> multiple devices on the same link and one of them signals an alert >> status while a large transfer is on-going, the alert handling will >> mechanically be delayed by up to a page - that's 32k reads/writes, isn't it? >> > > I think its 16k, but I would be inclined to say this is a > separate fix. The current code will tie up the bus for longer > than my fix does, since it only calls sdw_transfer once, and it > will write the wrong registers whilst doing it. Also to be clear > this wasn't found with super large transfers just medium sized > ones that happened to cross a page boundry. > > If we want to add some transaction size capping that is really > a new feature, this patch a bug fix. I would also be inclined > to say if we are going to add transaction size capping, we > probably want some property to specify what we are capping to. Yes indeed, this would be a new feature. I think this should be a manager property, depending on which peripherals are integrated and what latencies are expected.
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 3c67266f94834..bdd251e871694 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -386,37 +386,42 @@ int sdw_fill_msg(struct sdw_msg *msg, struct sdw_slave *slave, * Read/Write IO functions. */ -int sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) +static int sdw_ntransfer_no_pm(struct sdw_slave *slave, u32 addr, u8 flags, + size_t count, u8 *val) { struct sdw_msg msg; + size_t size; int ret; - ret = sdw_fill_msg(&msg, slave, addr, count, - slave->dev_num, SDW_MSG_FLAG_READ, val); - if (ret < 0) - return ret; + while (count) { + // Only handle bytes up to next page boundary + size = min(count, (SDW_REGADDR + 1) - (addr & SDW_REGADDR)); - ret = sdw_transfer(slave->bus, &msg); - if (slave->is_mockup_device) - ret = 0; - return ret; + ret = sdw_fill_msg(&msg, slave, addr, size, slave->dev_num, flags, val); + if (ret < 0) + return ret; + + ret = sdw_transfer(slave->bus, &msg); + if (ret < 0 && !slave->is_mockup_device) + return ret; + + addr += size; + val += size; + count -= size; + } + + return 0; +} + +int sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) +{ + return sdw_ntransfer_no_pm(slave, addr, SDW_MSG_FLAG_READ, count, val); } EXPORT_SYMBOL(sdw_nread_no_pm); int sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val) { - struct sdw_msg msg; - int ret; - - ret = sdw_fill_msg(&msg, slave, addr, count, - slave->dev_num, SDW_MSG_FLAG_WRITE, (u8 *)val); - if (ret < 0) - return ret; - - ret = sdw_transfer(slave->bus, &msg); - if (slave->is_mockup_device) - ret = 0; - return ret; + return sdw_ntransfer_no_pm(slave, addr, SDW_MSG_FLAG_WRITE, count, (u8 *)val); } EXPORT_SYMBOL(sdw_nwrite_no_pm);