From: "Cédric Le Goater" <clg@kaod.org>
To: "Jamin Lin" <jamin_lin@aspeedtech.com>,
"Peter Maydell" <peter.maydell@linaro.org>,
"Andrew Jeffery" <andrew@codeconstruct.com.au>,
"Joel Stanley" <joel@jms.id.au>,
"Alistair Francis" <alistair@alistair23.me>,
"Cleber Rosa" <crosa@redhat.com>,
"Philippe Mathieu-Daudé" <philmd@linaro.org>,
"Wainer dos Santos Moschetta" <wainersm@redhat.com>,
"Beraldo Leal" <bleal@redhat.com>,
"open list:ASPEED BMCs" <qemu-arm@nongnu.org>,
"open list:All patches CC here" <qemu-devel@nongnu.org>
Cc: troy_lee@aspeedtech.com, yunlin.tang@aspeedtech.com
Subject: Re: [PATCH v3 07/16] aspeed/smc: fix dma moving incorrect data length issue
Date: Fri, 19 Apr 2024 15:41:43 +0200 [thread overview]
Message-ID: <90a930b9-ec7f-47fc-bfc9-f4ac0958ef83@kaod.org> (raw)
In-Reply-To: <20240416091904.935283-8-jamin_lin@aspeedtech.com>
On 4/16/24 11:18, Jamin Lin wrote:
> DMA length is from 1 byte to 32MB for AST2600 and AST10x0
> and DMA length is from 4 bytes to 32MB for AST2500.
>
> In other words, if "R_DMA_LEN" is 0, it should move at least 1 byte
> data for AST2600 and AST10x0 and 4 bytes data for AST2500.
>> To support all ASPEED SOCs, adds dma_start_length parameter to store
> the start length, add helper routines function to compute the dma length
> and update DMA_LENGTH mask to "1FFFFFF" to fix dma moving
> incorrect data length issue.
OK. There are two problems to address, the "zero" length transfer and
the DMA length unit, which is missing today. Newer SoC use a 1 bit / byte
and older ones, AST2400 and AST2500, use 1 bit / 4 bytes.
We can introduce a AspeedSMCClass::dma_len_unit and rework the loop to :
do {
....
if (s->regs[R_DMA_LEN]) {
s->regs[R_DMA_LEN] -= 4 / asc->dma_len_unit;
}
} while (s->regs[R_DMA_LEN]);
It should fix the current implementation.
I don't think this is necessary to add a Fixes tag because the problem
has been there for ages and no one reported it. Probably because the
only place DMA transfers are used is in U-Boot and transfers have a
non-zero length.
> Currently, only supports dma length 4 bytes aligned.
this looks like a third topic. So the minimum value R_DMA_LEN should
have on the AST2600 SoC and above is '3'. I would opt to replace the
DMA_LENGTH macro with a dma_length_sanitize() helper to fix the software
input of R_DMA_LEN.
Thanks,
C.
> Signed-off-by: Troy Lee <troy_lee@aspeedtech.com>
> Signed-off-by: Jamin Lin <jamin_lin@aspeedtech.com>
> ---
> hw/ssi/aspeed_smc.c | 52 ++++++++++++++++++++++++++++++++-----
> include/hw/ssi/aspeed_smc.h | 1 +
> 2 files changed, 46 insertions(+), 7 deletions(-)
>
> diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
> index 8a8d77b480..71abc7a2d8 100644
> --- a/hw/ssi/aspeed_smc.c
> +++ b/hw/ssi/aspeed_smc.c
> @@ -178,13 +178,17 @@
> * DMA flash addresses should be 4 bytes aligned and the valid address
> * range is 0x20000000 - 0x2FFFFFFF.
> *
> - * DMA length is from 4 bytes to 32MB
> + * DMA length is from 4 bytes to 32MB (AST2500)
> * 0: 4 bytes
> * 0x7FFFFF: 32M bytes
> + *
> + * DMA length is from 1 byte to 32MB (AST2600, AST10x0)
> + * 0: 1 byte
> + * 0x1FFFFFF: 32M bytes
> */
> #define DMA_DRAM_ADDR(asc, val) ((val) & (asc)->dma_dram_mask)
> #define DMA_FLASH_ADDR(asc, val) ((val) & (asc)->dma_flash_mask)
> -#define DMA_LENGTH(val) ((val) & 0x01FFFFFC)
> +#define DMA_LENGTH(val) ((val) & 0x01FFFFFF)
>
> /* Flash opcodes. */
> #define SPI_OP_READ 0x03 /* Read data bytes (low frequency) */
> @@ -843,6 +847,24 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState *s)
> }
> }
>
> +static uint32_t aspeed_smc_dma_len(AspeedSMCState *s)
> +{
> + AspeedSMCClass *asc = ASPEED_SMC_GET_CLASS(s);
> + uint32_t dma_len;
> + uint32_t extra;
> +
> + dma_len = s->regs[R_DMA_LEN] + asc->dma_start_length;
> +
> + /* dma length 4 bytes aligned */
> + extra = dma_len % 4;
> +
> + if (extra != 0) {
> + dma_len += 4 - extra;
> + }
> +
> + return dma_len;
> +}
> +
> /*
> * Accumulate the result of the reads to provide a checksum that will
> * be used to validate the read timing settings.
> @@ -850,6 +872,7 @@ static bool aspeed_smc_inject_read_failure(AspeedSMCState *s)
> static void aspeed_smc_dma_checksum(AspeedSMCState *s)
> {
> MemTxResult result;
> + uint32_t dma_len;
> uint32_t data;
>
> if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
> @@ -861,7 +884,9 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
> aspeed_smc_dma_calibration(s);
> }
>
> - while (s->regs[R_DMA_LEN]) {
> + dma_len = aspeed_smc_dma_len(s);
> +
> + while (dma_len) {
> data = address_space_ldl_le(&s->flash_as, s->regs[R_DMA_FLASH_ADDR],
> MEMTXATTRS_UNSPECIFIED, &result);
> if (result != MEMTX_OK) {
> @@ -877,7 +902,8 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
> */
> s->regs[R_DMA_CHECKSUM] += data;
> s->regs[R_DMA_FLASH_ADDR] += 4;
> - s->regs[R_DMA_LEN] -= 4;
> + dma_len -= 4;
> + s->regs[R_DMA_LEN] = dma_len;
> }
>
> if (s->inject_failure && aspeed_smc_inject_read_failure(s)) {
> @@ -889,14 +915,17 @@ static void aspeed_smc_dma_checksum(AspeedSMCState *s)
> static void aspeed_smc_dma_rw(AspeedSMCState *s)
> {
> MemTxResult result;
> + uint32_t dma_len;
> uint32_t data;
>
> + dma_len = aspeed_smc_dma_len(s);
> +
> trace_aspeed_smc_dma_rw(s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE ?
> "write" : "read",
> s->regs[R_DMA_FLASH_ADDR],
> s->regs[R_DMA_DRAM_ADDR],
> - s->regs[R_DMA_LEN]);
> - while (s->regs[R_DMA_LEN]) {
> + dma_len);
> + while (dma_len) {
> if (s->regs[R_DMA_CTRL] & DMA_CTRL_WRITE) {
> data = address_space_ldl_le(&s->dram_as, s->regs[R_DMA_DRAM_ADDR],
> MEMTXATTRS_UNSPECIFIED, &result);
> @@ -937,7 +966,8 @@ static void aspeed_smc_dma_rw(AspeedSMCState *s)
> */
> s->regs[R_DMA_FLASH_ADDR] += 4;
> s->regs[R_DMA_DRAM_ADDR] += 4;
> - s->regs[R_DMA_LEN] -= 4;
> + dma_len -= 4;
> + s->regs[R_DMA_LEN] = dma_len;
> s->regs[R_DMA_CHECKSUM] += data;
> }
> }
> @@ -1381,6 +1411,7 @@ static void aspeed_2400_fmc_class_init(ObjectClass *klass, void *data)
> asc->features = ASPEED_SMC_FEATURE_DMA;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x1FFFFFFC;
> + asc->dma_start_length = 4;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_smc_reg_to_segment;
> @@ -1464,6 +1495,7 @@ static void aspeed_2500_fmc_class_init(ObjectClass *klass, void *data)
> asc->features = ASPEED_SMC_FEATURE_DMA;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x3FFFFFFC;
> + asc->dma_start_length = 4;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_smc_reg_to_segment;
> @@ -1620,6 +1652,7 @@ static void aspeed_2600_fmc_class_init(ObjectClass *klass, void *data)
> ASPEED_SMC_FEATURE_WDT_CONTROL;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x3FFFFFFC;
> + asc->dma_start_length = 1;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> @@ -1658,6 +1691,7 @@ static void aspeed_2600_spi1_class_init(ObjectClass *klass, void *data)
> ASPEED_SMC_FEATURE_DMA_GRANT;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x3FFFFFFC;
> + asc->dma_start_length = 1;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> @@ -1697,6 +1731,7 @@ static void aspeed_2600_spi2_class_init(ObjectClass *klass, void *data)
> ASPEED_SMC_FEATURE_DMA_GRANT;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x3FFFFFFC;
> + asc->dma_start_length = 1;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> @@ -1778,6 +1813,7 @@ static void aspeed_1030_fmc_class_init(ObjectClass *klass, void *data)
> asc->features = ASPEED_SMC_FEATURE_DMA;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x000BFFFC;
> + asc->dma_start_length = 1;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_1030_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_1030_smc_reg_to_segment;
> @@ -1815,6 +1851,7 @@ static void aspeed_1030_spi1_class_init(ObjectClass *klass, void *data)
> asc->features = ASPEED_SMC_FEATURE_DMA;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x000BFFFC;
> + asc->dma_start_length = 1;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> @@ -1851,6 +1888,7 @@ static void aspeed_1030_spi2_class_init(ObjectClass *klass, void *data)
> asc->features = ASPEED_SMC_FEATURE_DMA;
> asc->dma_flash_mask = 0x0FFFFFFC;
> asc->dma_dram_mask = 0x000BFFFC;
> + asc->dma_start_length = 1;
> asc->nregs = ASPEED_SMC_R_MAX;
> asc->segment_to_reg = aspeed_2600_smc_segment_to_reg;
> asc->reg_to_segment = aspeed_2600_smc_reg_to_segment;
> diff --git a/include/hw/ssi/aspeed_smc.h b/include/hw/ssi/aspeed_smc.h
> index 8e1dda556b..f359ed22cc 100644
> --- a/include/hw/ssi/aspeed_smc.h
> +++ b/include/hw/ssi/aspeed_smc.h
> @@ -106,6 +106,7 @@ struct AspeedSMCClass {
> uint32_t features;
> hwaddr dma_flash_mask;
> hwaddr dma_dram_mask;
> + uint32_t dma_start_length;
> uint32_t nregs;
> uint32_t (*segment_to_reg)(const AspeedSMCState *s,
> const AspeedSegments *seg);
next prev parent reply other threads:[~2024-04-19 13:42 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-16 9:18 [PATCH v3 00/16] Add AST2700 support Jamin Lin via
2024-04-16 9:18 ` [PATCH v3 01/16] aspeed/wdt: " Jamin Lin via
2024-04-16 9:18 ` [PATCH v3 02/16] aspeed/sli: " Jamin Lin via
2024-04-16 15:29 ` Cédric Le Goater
2024-04-16 9:18 ` [PATCH v3 03/16] aspeed/sdmc: remove redundant macros Jamin Lin via
2024-04-16 15:30 ` Cédric Le Goater
2024-04-16 9:18 ` [PATCH v3 04/16] aspeed/sdmc: fix coding style Jamin Lin via
2024-04-16 15:30 ` Cédric Le Goater
2024-04-16 9:18 ` [PATCH v3 05/16] aspeed/sdmc: Add AST2700 support Jamin Lin via
2024-04-16 15:34 ` Cédric Le Goater
2024-04-16 9:18 ` [PATCH v3 06/16] aspeed/smc: correct device description Jamin Lin via
2024-04-16 15:34 ` Cédric Le Goater
2024-04-16 9:18 ` [PATCH v3 07/16] aspeed/smc: fix dma moving incorrect data length issue Jamin Lin via
2024-04-19 13:41 ` Cédric Le Goater [this message]
2024-04-30 7:22 ` Cédric Le Goater
2024-04-30 8:51 ` Jamin Lin
2024-05-03 14:35 ` Cédric Le Goater
2024-05-15 4:05 ` Jamin Lin
2024-04-16 9:18 ` [PATCH v3 08/16] aspeed/smc: support 64 bits dma dram address Jamin Lin via
2024-04-18 16:09 ` Cédric Le Goater
2024-04-19 6:00 ` Jamin Lin
2024-04-30 7:26 ` Cédric Le Goater
2024-04-30 7:56 ` Jamin Lin
2024-05-03 14:20 ` Cédric Le Goater
2024-05-15 8:56 ` Jamin Lin
2024-05-07 14:19 ` Cédric Le Goater
2024-05-15 9:01 ` Jamin Lin
2024-05-17 7:57 ` Cédric Le Goater
2024-05-20 2:40 ` Jamin Lin
2024-05-27 6:46 ` Cédric Le Goater
2024-05-27 6:48 ` Jamin Lin
2024-04-16 9:18 ` [PATCH v3 09/16] aspeed/smc: Add AST2700 support Jamin Lin via
2024-04-18 16:14 ` Cédric Le Goater
2024-04-16 9:18 ` [PATCH v3 10/16] aspeed/scu: " Jamin Lin via
2024-04-16 9:18 ` [PATCH v3 11/16] aspeed/intc: " Jamin Lin via
2024-05-07 13:33 ` Cédric Le Goater
2024-05-21 6:40 ` Jamin Lin
2024-05-21 7:44 ` Jamin Lin
2024-04-16 9:18 ` [PATCH v3 12/16] aspeed/soc: " Jamin Lin via
2024-04-19 7:10 ` Cédric Le Goater
2024-04-19 7:58 ` Jamin Lin
2024-05-17 7:58 ` Cédric Le Goater
2024-05-17 9:13 ` Jamin Lin
2024-05-07 13:06 ` Cédric Le Goater
2024-04-16 9:19 ` [PATCH v3 13/16] aspeed: Add an AST2700 eval board Jamin Lin via
2024-04-16 9:19 ` [PATCH v3 14/16] aspeed/soc: fix incorrect dram size for AST2700 Jamin Lin via
2024-04-16 9:19 ` [PATCH v3 15/16] test/avocado/machine_aspeed.py: Add AST2700 test case Jamin Lin via
2024-04-16 16:44 ` Cédric Le Goater
2024-04-16 9:19 ` [PATCH v3 16/16] docs:aspeed: Add AST2700 Evaluation board Jamin Lin via
2024-04-16 15:54 ` Cédric Le Goater
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=90a930b9-ec7f-47fc-bfc9-f4ac0958ef83@kaod.org \
--to=clg@kaod.org \
--cc=alistair@alistair23.me \
--cc=andrew@codeconstruct.com.au \
--cc=bleal@redhat.com \
--cc=crosa@redhat.com \
--cc=jamin_lin@aspeedtech.com \
--cc=joel@jms.id.au \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=troy_lee@aspeedtech.com \
--cc=wainersm@redhat.com \
--cc=yunlin.tang@aspeedtech.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).