From patchwork Tue Apr 16 16:28:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Serge Semin X-Patchwork-Id: 789714 Received: from mail-lf1-f44.google.com (mail-lf1-f44.google.com [209.85.167.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4AF62132C17; Tue, 16 Apr 2024 16:29:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713284958; cv=none; b=fYzi0tLHeDIN9TF82uohNGkZ8R5OHUkIdXdZS1M6FeriGF+WaCMPPUIXUY1Wo3iZY/OYYFYf1xzCQ0Xywp+Om8jCZax/qvfkHg+ONFlM/L525WXceGEX2+mHX5/+ciN8bhH26GWipHNRG1RsBfgGwfJzfZswMaPYCo3LvdD5qdg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713284958; c=relaxed/simple; bh=wbXPipj1z/yiZ0qViyUkJmUEI/KeyS2lZ3XgWX9qBW0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GgcpGhUN+gXEn9dPTOVOO5vM367bW94wPighjRnAk9Z6FpyBrbgAcRp7gSDmGIHoK5OOsnwR8Y16FD2jwKIt7qPEUnEtUIQNscgKaHaburm7r4m6nL+Zxkad3yAw6RjgB07smT8/GJElyCz2Esz0bJ9NruXRaSpJBB1De3YZws4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=WQkFot6c; arc=none smtp.client-ip=209.85.167.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="WQkFot6c" Received: by mail-lf1-f44.google.com with SMTP id 2adb3069b0e04-516d0c004b1so6125281e87.2; Tue, 16 Apr 2024 09:29:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1713284955; x=1713889755; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=hTFL+T9JUZzbZhTh3cZoXr6hKv9MUPaKo7eqvocdq/Y=; b=WQkFot6cZqg52El95cJDYPNTt1tdlkt/m4GvUaMRfDmEnRhn7lb9xYolW2X4ZEzOOE 5ox9aDBQA6lWj68fUhR0g3ZrrV583toK4jyGflDONviOyUJOeH1ifzToSrpS/mFHHMh4 0y3Bc4u+fFcqvzrzSn1DTMr1PdiXr3L9mGqhlooDAFdUCA1Vn0EbOmg234oWl7dQQLib S9ruLRfXGHoQ0TLABG5bHlZRoRDdpx3vXI+5FkScRI41IRK1YU3RQsIoVuGkdnG6H9Ad Eg9HCcFf98HkC7i4F3NSRp4LADC74WeheaBaScS3POzIw+f5r0f+lj+qxAkZZgzuQK6Y tCzw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1713284955; x=1713889755; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=hTFL+T9JUZzbZhTh3cZoXr6hKv9MUPaKo7eqvocdq/Y=; b=CLtOXGqiUcqV018okeS/+K3HsqY6Ol7cw1ZFYD4RW9jkoowSFuA3NO5NQ6UNpIZ2se TK2A97b5l9OnsShMkTNyAJpy2x9JPFfZx05F9d5nceJTJJNR+z0r46D01chXupsGZC1q QgZ622Rka50567U2ga0xAnEjn0oOoEDYIFSNbyvyn5MLxLLdGAF6MxwtejcqLPzcvU/x r7mpEDh+ERnMBUvKicExGVRC9XALxps+QB6OZJyTMowBt0y+Ew8v777qXFBQEZM2rwnZ zxGmhSGxq201PItpuDsaCkZ+FKfH90wW1uljQXwsoF1r4b7+VAg7mVXoetokHBe0p/J9 MNfQ== X-Forwarded-Encrypted: i=1; AJvYcCWGElPjrlwyCUIu9FnOxoQInD1tyAXoXP773oZNbqZ2KDjJ7/0/TBjbXarNhzHgcUjWznN44QY1IbgnBjhjCSLYQ6J2mkPv6TXSSI0h2/Tm/t9O1V9zhwuxUU2oaD+MbE8fAsz9i4gbfdCagEnr/nke52U+RT9fsg0sw1V1Roo1hTP63BOc X-Gm-Message-State: AOJu0Yw5FtNen2kVsQl5tV8h6S//NF4di8aMLu90rANhF/n2qUE4vr0o p/3CJkO0mnwE+W/+xwKBiOJZMfi8k5HI0PvMpQAJefNpyb+gsoht X-Google-Smtp-Source: AGHT+IEDTIxDjYIModNCTtD1DEKQhvCj8CjYHuU5aeiXZCwa1LbzClWr6ebERdhjFUsZmBpf6Sgpmg== X-Received: by 2002:a05:651c:b0b:b0:2d8:3e07:5651 with SMTP id b11-20020a05651c0b0b00b002d83e075651mr12850954ljr.34.1713284955355; Tue, 16 Apr 2024 09:29:15 -0700 (PDT) Received: from localhost (srv1.baikalchip.ru. [87.245.175.227]) by smtp.gmail.com with ESMTPSA id s26-20020a2e98da000000b002d9f3bed88dsm1515023ljj.77.2024.04.16.09.29.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Apr 2024 09:29:15 -0700 (PDT) From: Serge Semin To: Viresh Kumar , Andy Shevchenko , Vinod Koul Cc: Serge Semin , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Greg Kroah-Hartman , Jiri Slaby , dmaengine@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/4] dmaengine: dw: Add peripheral bus width verification Date: Tue, 16 Apr 2024 19:28:55 +0300 Message-ID: <20240416162908.24180-2-fancer.lancer@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240416162908.24180-1-fancer.lancer@gmail.com> References: <20240416162908.24180-1-fancer.lancer@gmail.com> Precedence: bulk X-Mailing-List: linux-serial@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Currently the src_addr_width and dst_addr_width fields of the dma_slave_config structure are mapped to the CTLx.SRC_TR_WIDTH and CTLx.DST_TR_WIDTH fields of the peripheral bus side in order to have the properly aligned data passed to the target device. It's done just by converting the passed peripheral bus width to the encoded value using the __ffs() function. This implementation has several problematic sides: 1. __ffs() is undefined if no bit exist in the passed value. Thus if the specified addr-width is DMA_SLAVE_BUSWIDTH_UNDEFINED, __ffs() may return unexpected value depending on the platform-specific implementation. 2. DW AHB DMA-engine permits having the power-of-2 transfer width limited by the DMAH_Mk_HDATA_WIDTH IP-core synthesize parameter. Specifying bus-width out of that constraints scope will definitely cause unexpected result since the destination reg will be only partly touched than the client driver implied. Let's fix all of that by adding the peripheral bus width verification method which would make sure that the passed source or destination address width is valid and if undefined then the driver will just fallback to the 1-byte width transfer. Fixes: 029a40e97d0d ("dmaengine: dw: provide DMA capabilities") Signed-off-by: Serge Semin --- drivers/dma/dw/core.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 5f7d690e3dba..c297ca9d5706 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -780,10 +781,43 @@ bool dw_dma_filter(struct dma_chan *chan, void *param) } EXPORT_SYMBOL_GPL(dw_dma_filter); +static int dwc_verify_p_buswidth(struct dma_chan *chan) +{ + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dw_dma *dw = to_dw_dma(chan->device); + u32 reg_width, max_width; + + if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV) + reg_width = dwc->dma_sconfig.dst_addr_width; + else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM) + reg_width = dwc->dma_sconfig.src_addr_width; + else /* DMA_MEM_TO_MEM */ + return 0; + + max_width = dw->pdata->data_width[dwc->dws.p_master]; + + /* Fall-back to 1byte transfer width if undefined */ + if (reg_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) + reg_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + else if (!is_power_of_2(reg_width) || reg_width > max_width) + return -EINVAL; + else /* bus width is valid */ + return 0; + + /* Update undefined addr width value */ + if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV) + dwc->dma_sconfig.dst_addr_width = reg_width; + else /* DMA_DEV_TO_MEM */ + dwc->dma_sconfig.src_addr_width = reg_width; + + return 0; +} + static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct dw_dma *dw = to_dw_dma(chan->device); + int err; memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig)); @@ -792,6 +826,10 @@ static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig) dwc->dma_sconfig.dst_maxburst = clamp(dwc->dma_sconfig.dst_maxburst, 0U, dwc->max_burst); + err = dwc_verify_p_buswidth(chan); + if (err) + return err; + dw->encode_maxburst(dwc, &dwc->dma_sconfig.src_maxburst); dw->encode_maxburst(dwc, &dwc->dma_sconfig.dst_maxburst); From patchwork Tue Apr 16 16:28:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Serge Semin X-Patchwork-Id: 790129 Received: from mail-lf1-f51.google.com (mail-lf1-f51.google.com [209.85.167.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 13BD913328B; Tue, 16 Apr 2024 16:29:18 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713284960; cv=none; b=lXId5QB5Js7KP5ZFCN9PNwJoBv+K1Xyv76qGv9RSIGYzsKQJKUFHw/Qelquz8IOHdt5452iPbnokLEMrJIoSGi+oFp0pGmGpCC8mlV+X0C5VxZMQJ+2Lr/uANNec2EHSuF/7NWLQKRuNSaUhu7a1Vf6uYn3SQI8ZqLedPiMAYJs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713284960; c=relaxed/simple; bh=QEwzQy4hq0flQyUiPAaECkev0IJ3+RmQQ2iYPOnd8YU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=O8VH7yrYXHN3UIy36+HEH746fFp07liwe+s8GqygokcYsyc43Prj5PHBETCVZetNzyvJza5C3fK1M5pqgspHjvYuwNE6VKRzEl0lAozSJoDcR9HcY10NST7K/MZnsUUzCQFCA/EMJGrooehXaHyczgRURsc48kRMnhavL9KjyZo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=hAZTl3mK; arc=none smtp.client-ip=209.85.167.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hAZTl3mK" Received: by mail-lf1-f51.google.com with SMTP id 2adb3069b0e04-516d3776334so5983749e87.1; Tue, 16 Apr 2024 09:29:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1713284957; x=1713889757; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=q+iM86l8TbMCs++JnytXC9niCPvo0pgTAJ4DYQyJ6t0=; b=hAZTl3mK8eJa842V0ZNy9b7brorVbGPYVI7W7of7dgXfi+xDUseTaUl7hCC+qTRadr ff7XrCzTAvyuTcg6ddYfzQH0hvmsCWteTyudN9+Gh1DKi9JFzzEpx4xUi/xVJfAb/kGm Dkqge4jBolWNVdfg6/e6WFI98hkMN03NHDq0ZXPnYtCdKusKky/w7UKVkr8MAGnC1Zax 9/10hFjMUDXHKvaI1Q5wfmyQWNeBqSmUMnjYnElsDvgNeg+6KYNgb+bbMIkoaKdfUmBi fZ0Svdng+bczmnuHWQjW5t+gDgRq81UcKwhrAo3XKlaGammcR4F0+pcievmKpOz5lNwc 7iow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1713284957; x=1713889757; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=q+iM86l8TbMCs++JnytXC9niCPvo0pgTAJ4DYQyJ6t0=; b=sips36LczQy4Tv/WCenJTFHNVxuLLvV3Jm7U/5pd9ZLQBzfeubSFuDbbviiYZheYQ5 aNlU3B8n7Wk+0KFULEGeLoqegxt+ZWug+0K2Celw3rpD4gZt6ChLSGL/1XhjhsuQRDpH lwSwvqQqWIa5svKEVP6Eb9mABGlHV6Kw8odAXwrvwtklfAYc4n5r9d2H5GZx3HqSfwXI aZwnc5FQ5I6jZgpgiHt24KK0MOaKlhmQwwb6FdzC7DWMJX57NNxwK6ocQvj/nSeVaQpS Oh9tTUcLt6KeUGgJqnLNHFItQUlgrI4RbN1iPtHY5gvW4E35578LIGkaULW6fXAeIZL2 04PA== X-Forwarded-Encrypted: i=1; AJvYcCUf5VOKQAl+VLI45WkGsFGfw5us0Nh7un7+x7/d3XLxnedwHqpWdkJw5aNKImmCv5BwdBawi4B6XRbmbvttMyFsH2AD6VlUmG+Lhs1+x6Zt4XF08CuOmraauCMZdlcJgIJpTkdm8EW8vsK+ZMInxolID81aJ5/iuj7Q3cjljkjHu4vVGF0m X-Gm-Message-State: AOJu0Yw4ALFO+9NrseXo24k2is26wpVMBAStde+tkVqKVDOHofmsEsyD buTL2WnsqJOAAJE6GQLVPTTJ0js7yQvhc3U6/bfyfrRt93oCuTil X-Google-Smtp-Source: AGHT+IGNEyR2lUrnboOQWsBT/5PQIlRhzBj46Qht3EE3SMLnHiDnAPhnJbOHcl367zY5XbJPrkB7rA== X-Received: by 2002:a05:6512:3e23:b0:519:29a2:d4b3 with SMTP id i35-20020a0565123e2300b0051929a2d4b3mr1892299lfv.15.1713284956976; Tue, 16 Apr 2024 09:29:16 -0700 (PDT) Received: from localhost (srv1.baikalchip.ru. [87.245.175.227]) by smtp.gmail.com with ESMTPSA id l21-20020a056512111500b0051901751d0esm486618lfg.126.2024.04.16.09.29.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Apr 2024 09:29:16 -0700 (PDT) From: Serge Semin To: Viresh Kumar , Andy Shevchenko , Vinod Koul Cc: Serge Semin , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Greg Kroah-Hartman , Jiri Slaby , dmaengine@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org, Viresh Kumar Subject: [PATCH 2/4] dmaengine: dw: Add memory bus width verification Date: Tue, 16 Apr 2024 19:28:56 +0300 Message-ID: <20240416162908.24180-3-fancer.lancer@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240416162908.24180-1-fancer.lancer@gmail.com> References: <20240416162908.24180-1-fancer.lancer@gmail.com> Precedence: bulk X-Mailing-List: linux-serial@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Currently in case of the DEV_TO_MEM or MEM_TO_DEV DMA transfers the memory data width (single transfer width) is determined based on the buffer length, buffer base address or DMA master-channel max address width capability. It isn't enough in case of the channel disabling prior the block transfer is finished. Here is what DW AHB DMA IP-core databook says regarding the port suspension (DMA-transfer pause) implementation in the controller: "When CTLx.SRC_TR_WIDTH < CTLx.DST_TR_WIDTH and the CFGx.CH_SUSP bit is high, the CFGx.FIFO_EMPTY is asserted once the contents of the FIFO do not permit a single word of CTLx.DST_TR_WIDTH to be formed. However, there may still be data in the channel FIFO, but not enough to form a single transfer of CTLx.DST_TR_WIDTH. In this scenario, once the channel is disabled, the remaining data in the channel FIFO is not transferred to the destination peripheral." So in case if the port gets to be suspended and then disabled it's possible to have the data silently discarded even though the controller reported that FIFO is empty and the CTLx.BLOCK_TS indicated the dropped data already received from the source device. This looks as if the data somehow got lost on a way from the peripheral device to memory and causes problems for instance in the DW APB UART driver, which pauses and disables the DMA-transfer as soon as the recv data timeout happens. Here is the way it looks: Memory <------- DMA FIFO <------ UART FIFO <---------------- UART DST_TR_WIDTH -+--------| | | | | | | No more data Current lvl -+--------| |---------+- DMA-burst lvl | | |---------+- Leftover data | | |---------+- SRC_TR_WIDTH -+--------+-------+---------+ In the example above: no more data is getting received over the UART port and BLOCK_TS is not even close to be fully received; some data is left in the UART FIFO, but not enough to perform a bursted DMA-xfer to the DMA FIFO; some data is left in the DMA FIFO, but not enough to be passed further to the system memory in a single transfer. In this situation the 8250 UART driver catches the recv timeout interrupt, pauses the DMA-transfer and terminates it completely, after which the IRQ handler manually fetches the leftover data from the UART FIFO into the recv-buffer. But since the DMA-channel has been disabled with the data left in the DMA FIFO, that data will be just discarded and the recv-buffer will have a gap of the "current lvl" size in the recv-buffer at the tail of the lately received data portion. So the data will be lost just due to the misconfigured DMA transfer. Note this is only relevant for the case of the transfer suspension and _disabling_. No problem will happen if the transfer will be re-enabled afterwards or the block transfer is fully completed. In the later case the "FIFO flush mode" will be executed at the transfer final stage in order to push out the data left in the DMA FIFO. In order to fix the denoted problem the DW AHB DMA-engine driver needs to make sure that the _bursted_ source transfer width is greater or equal to the single destination transfer (note the HW databook describes more strict constraint than actually required). Since the peripheral-device side is prescribed by the client driver logic, the memory-side can be only used for that. The solution can be easily implemented for the DEV_TO_MEM transfers just by adjusting the memory-channel address width. Sadly it's not that easy for the MEM_TO_DEV transfers since the mem-to-dma burst size is normally dynamically determined by the controller. So the only thing that can be done is to make sure that memory-side address width can be greater than the peripheral device address width. Fixes: a09820043c9e ("dw_dmac: autoconfigure data_width or get it via platform data") Signed-off-by: Serge Semin --- drivers/dma/dw/core.c | 41 ++++++++++++++++++++++++++++++++++------- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index c297ca9d5706..61e026310dd8 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -622,12 +622,10 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, struct dw_desc *prev; struct dw_desc *first; u32 ctllo, ctlhi; - u8 m_master = dwc->dws.m_master; - u8 lms = DWC_LLP_LMS(m_master); + u8 lms = DWC_LLP_LMS(dwc->dws.m_master); dma_addr_t reg; unsigned int reg_width; unsigned int mem_width; - unsigned int data_width = dw->pdata->data_width[m_master]; unsigned int i; struct scatterlist *sg; size_t total_len = 0; @@ -661,7 +659,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_dma_address(sg); len = sg_dma_len(sg); - mem_width = __ffs(data_width | mem | len); + mem_width = __ffs(sconfig->src_addr_width | mem | len); slave_sg_todev_fill_desc: desc = dwc_desc_get(dwc); @@ -721,7 +719,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, lli_write(desc, sar, reg); lli_write(desc, dar, mem); lli_write(desc, ctlhi, ctlhi); - mem_width = __ffs(data_width | mem); + mem_width = __ffs(sconfig->dst_addr_width | mem); lli_write(desc, ctllo, ctllo | DWC_CTLL_DST_WIDTH(mem_width)); desc->len = dlen; @@ -813,6 +811,31 @@ static int dwc_verify_p_buswidth(struct dma_chan *chan) return 0; } +static int dwc_verify_m_buswidth(struct dma_chan *chan) +{ + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + struct dw_dma *dw = to_dw_dma(chan->device); + u32 reg_width, reg_burst, mem_width; + + mem_width = dw->pdata->data_width[dwc->dws.m_master]; + + /* Make sure src and dst word widths are coherent */ + if (dwc->dma_sconfig.direction == DMA_MEM_TO_DEV) { + reg_width = dwc->dma_sconfig.dst_addr_width; + if (mem_width < reg_width) + return -EINVAL; + + dwc->dma_sconfig.src_addr_width = mem_width; + } else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM) { + reg_width = dwc->dma_sconfig.src_addr_width; + reg_burst = rounddown_pow_of_two(dwc->dma_sconfig.src_maxburst); + + dwc->dma_sconfig.dst_addr_width = min(mem_width, reg_width * reg_burst); + } + + return 0; +} + static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); @@ -822,14 +845,18 @@ static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig) memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig)); dwc->dma_sconfig.src_maxburst = - clamp(dwc->dma_sconfig.src_maxburst, 0U, dwc->max_burst); + clamp(dwc->dma_sconfig.src_maxburst, 1U, dwc->max_burst); dwc->dma_sconfig.dst_maxburst = - clamp(dwc->dma_sconfig.dst_maxburst, 0U, dwc->max_burst); + clamp(dwc->dma_sconfig.dst_maxburst, 1U, dwc->max_burst); err = dwc_verify_p_buswidth(chan); if (err) return err; + err = dwc_verify_m_buswidth(chan); + if (err) + return err; + dw->encode_maxburst(dwc, &dwc->dma_sconfig.src_maxburst); dw->encode_maxburst(dwc, &dwc->dma_sconfig.dst_maxburst); From patchwork Tue Apr 16 16:28:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Serge Semin X-Patchwork-Id: 789713 Received: from mail-lf1-f52.google.com (mail-lf1-f52.google.com [209.85.167.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AFDF113341E; Tue, 16 Apr 2024 16:29:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.52 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713284962; cv=none; b=RXdFmao+bxP05U9dfzwGcAw8NumqmZqcTfjGUfOQjEWufJEq6zYAJpaES4ZvHtEL64wQ7vkJNnictIMuj3hcUn98S6ZRCi0Rf+XTCGpCWBeDY1wOpUfX517AF9PG8XJd0BU2fglAQgs0viHRmyFYvA25p4irFkDSzqKl02zDm4A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713284962; c=relaxed/simple; bh=9TZDexUWMrvyNTz945MyInpdtCzKkNOQXNDF6Q4i2sw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=H08i3afyLzC5pfg+kMafLluD1KX7NsHLYQm4bDKUYrtjkTCQjhzqZIT9BqCSbpBTjjQojWkJSC0OKFDpriZDcLqmrXELUEYPX2N2DYw3DNpm4GCr8GLF1+Xw7MwLibon09eouk5OKndIB8v1mXxfcRFe0U6Xzqe6rvGOE27dxIc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=XtRzuXP9; arc=none smtp.client-ip=209.85.167.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="XtRzuXP9" Received: by mail-lf1-f52.google.com with SMTP id 2adb3069b0e04-516d727074eso5973349e87.0; Tue, 16 Apr 2024 09:29:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1713284959; x=1713889759; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=fryuWq8aUUJjTuLOMY39ltR5o86CjDEksNCZ9CfWDGA=; b=XtRzuXP9J3fGiHK0yq0ZB1wcy6cwdRhqPDArY8WKbRRSbpyK+ckaPM6udK2D8+jON2 AiGzIgwdqnbtR27Ed5VaDUOtkDYm8GBoeg83FHOLAQU30yz2K9DvEVFJvUQloGNiuisc nSPL8+vU6PdyIl0wxtci3sFzhsOWzOmAt8dRNGX06Twqv/XVdkEJM+eXcLoV972G+NMI 9l2/hpgP3AsnPi5R8rkyQ6FWaag20sNgupictjodVI8upHIDV7mKQCOTrClnGEKYbts4 Nh6QLKI1vRIxSkVrHYekhrqpXbidQuYadqJthvPFcVrEYshJdnyEiwspur+6IQds29iB Js3Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1713284959; x=1713889759; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fryuWq8aUUJjTuLOMY39ltR5o86CjDEksNCZ9CfWDGA=; b=OJV9qkmKI3HpfSqW3nPzr7ZNXJZRBaZB7JCLeFjACv5qhTEFDu1w7t3f1yrD0mpGPH FME7nOKyJeZHOL3u7wB099F00RFzUm2VWhQ0F8IlOaqU29TD3DaijHbE6y13i2HtWlzc JoARfJ/afK9SxVfcQ1uqCgJ3ZzHctSBJJWHzWv7eOGwsz0YWV+lVeqzfQA4/iuCaF1g3 J/iUPZdpjLQuNSRdTgoV9kkKj5tldl0fykM8ZdZiHVaVuyXSGAw/6UWHM3xY+/K0BOph n1TU4SuzQaHWdhE2PzX5xJxlRbIFhH28R26LS9sjDzVVsUSD9gdGCtL8+pr7y5JmCAmO qkJQ== X-Forwarded-Encrypted: i=1; AJvYcCX8I9LlGRwKMMHBoCAtKtdIuX1/PY8Jk56dKwIg1R5IuMbleIY6ZV8dBbLP/E37A0fqbG0J/HJXL0jDodBLFjcL0uou7FoEjW9GciIolUcUcPwUaJtt23W5za55ho5ckpi1jYdG3SOn7b2nbTjqTQsep+BFrxj1X4F/7+iS61oukYQ/Jvum X-Gm-Message-State: AOJu0YwzgR8qtUYFAM1t8F+Vo2tYbM/Qp7Er7FJKlsHpKhzOiy76gfyi 8iqRDbHZfy8YyfTqzoqM9BfYu1VQnECDA4AClOR05C8buA6o38ro X-Google-Smtp-Source: AGHT+IE5q9vXkq/lF2ntfeN2wCfL4chOLtmupmo4LAw8TRx87/kDOCdcT/vFJOFqmygagbos6Mwugg== X-Received: by 2002:a19:3806:0:b0:518:758f:2610 with SMTP id f6-20020a193806000000b00518758f2610mr7554152lfa.48.1713284958800; Tue, 16 Apr 2024 09:29:18 -0700 (PDT) Received: from localhost (srv1.baikalchip.ru. [87.245.175.227]) by smtp.gmail.com with ESMTPSA id p8-20020a056512328800b00516d123f3b8sm1630127lfe.59.2024.04.16.09.29.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Apr 2024 09:29:18 -0700 (PDT) From: Serge Semin To: Viresh Kumar , Andy Shevchenko , Vinod Koul Cc: Serge Semin , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Greg Kroah-Hartman , Jiri Slaby , dmaengine@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 3/4] dmaengine: dw: Simplify prepare CTL_LO methods Date: Tue, 16 Apr 2024 19:28:57 +0300 Message-ID: <20240416162908.24180-4-fancer.lancer@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240416162908.24180-1-fancer.lancer@gmail.com> References: <20240416162908.24180-1-fancer.lancer@gmail.com> Precedence: bulk X-Mailing-List: linux-serial@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Currently the CTL LO fields are calculated on the platform-specific basis. It's implemented by means of the prepare_ctllo() callbacks using the ternary operator within the local variables init block at the beginning of the block scope. The functions code currently is relatively hard to comprehend and isn't that optimal since implies four conditional statements executed and two additional local variables defined. Let's simplify the DW AHB DMA prepare_ctllo() method by unrolling the ternary operators into the normal if-else statement, dropping redundant master-interface ID variables and initializing the local variables based on the singly evaluated DMA-transfer direction check. Thus the method will look much more readable since now the fields content can be easily inferred right from the if-else branch. Provide the same update in the Intel DMA32 core driver for sake of the driver code unification. Note besides of the effects described above this update is basically a preparation before dropping the max burst encoding callback. It will require calling the burst fields calculation methods right in the prepare_ctllo() callbacks, which would have made the later function code even more complex. Signed-off-by: Serge Semin --- drivers/dma/dw/dw.c | 24 ++++++++++++++++++------ drivers/dma/dw/idma32.c | 14 ++++++++++++-- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/drivers/dma/dw/dw.c b/drivers/dma/dw/dw.c index a4862263ff14..c65438d1f1ff 100644 --- a/drivers/dma/dw/dw.c +++ b/drivers/dma/dw/dw.c @@ -67,12 +67,24 @@ static size_t dw_dma_block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width) static u32 dw_dma_prepare_ctllo(struct dw_dma_chan *dwc) { struct dma_slave_config *sconfig = &dwc->dma_sconfig; - u8 smsize = (dwc->direction == DMA_DEV_TO_MEM) ? sconfig->src_maxburst : 0; - u8 dmsize = (dwc->direction == DMA_MEM_TO_DEV) ? sconfig->dst_maxburst : 0; - u8 p_master = dwc->dws.p_master; - u8 m_master = dwc->dws.m_master; - u8 dms = (dwc->direction == DMA_MEM_TO_DEV) ? p_master : m_master; - u8 sms = (dwc->direction == DMA_DEV_TO_MEM) ? p_master : m_master; + u8 sms, smsize, dms, dmsize; + + if (dwc->direction == DMA_MEM_TO_DEV) { + sms = dwc->dws.m_master; + smsize = 0; + dms = dwc->dws.p_master; + dmsize = sconfig->dst_maxburst; + } else if (dwc->direction == DMA_DEV_TO_MEM) { + sms = dwc->dws.p_master; + smsize = sconfig->src_maxburst; + dms = dwc->dws.m_master; + dmsize = 0; + } else /* DMA_MEM_TO_MEM */ { + sms = dwc->dws.m_master; + smsize = 0; + dms = dwc->dws.m_master; + dmsize = 0; + } return DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN | DWC_CTLL_DST_MSIZE(dmsize) | DWC_CTLL_SRC_MSIZE(smsize) | diff --git a/drivers/dma/dw/idma32.c b/drivers/dma/dw/idma32.c index 58f4078d83fe..3a1b12517655 100644 --- a/drivers/dma/dw/idma32.c +++ b/drivers/dma/dw/idma32.c @@ -202,8 +202,18 @@ static size_t idma32_block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width) static u32 idma32_prepare_ctllo(struct dw_dma_chan *dwc) { struct dma_slave_config *sconfig = &dwc->dma_sconfig; - u8 smsize = (dwc->direction == DMA_DEV_TO_MEM) ? sconfig->src_maxburst : 0; - u8 dmsize = (dwc->direction == DMA_MEM_TO_DEV) ? sconfig->dst_maxburst : 0; + u8 smsize, dmsize; + + if (dwc->direction == DMA_MEM_TO_DEV) { + smsize = 0; + dmsize = sconfig->dst_maxburst; + } else if (dwc->direction == DMA_DEV_TO_MEM) { + smsize = sconfig->src_maxburst; + dmsize = 0; + } else /* DMA_MEM_TO_MEM */ { + smsize = 0; + dmsize = 0; + } return DWC_CTLL_LLP_D_EN | DWC_CTLL_LLP_S_EN | DWC_CTLL_DST_MSIZE(dmsize) | DWC_CTLL_SRC_MSIZE(smsize); From patchwork Tue Apr 16 16:28:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Serge Semin X-Patchwork-Id: 790128 Received: from mail-lf1-f48.google.com (mail-lf1-f48.google.com [209.85.167.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D7E6D132C17; Tue, 16 Apr 2024 16:29:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713284964; cv=none; b=u7G8jXeg2NqEeTwa1t5TPSYdFCDLgWxBuFqh7zMjjwP0WbAGtJW26d7sNJpAA5bnXwKjqsrkrKpk2BlfEZOxJ08cOhju8Bbp4F2skbl1zT/ttGin7fcRXe570hTtmOPs40Bx4+gSr1C1oHR+trSbq70ncnyDtkLS0lGuN0ieeRI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1713284964; c=relaxed/simple; bh=2Kd3DIDnTnUy4CbLobJwZ9WXWWQcfVElxl61UbnfXBg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hQ33TBeL+3zUWVBsa5WFtp6tHzZogr7i1EJWsVBKNNdQFGcNoH6Mt3X133E1Zdsbm5vupU0y/Qo2JBt3l/ZMBF0Xtg1HGW1RbZq461y5WtoipmKkFyczmYB8FLAiTS7sAH4/cQauqEoVH3XOHI7QRqlCEb1ZvXT78JjSr+MkXMM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=m5remeGD; arc=none smtp.client-ip=209.85.167.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="m5remeGD" Received: by mail-lf1-f48.google.com with SMTP id 2adb3069b0e04-518c9ff3e29so3174801e87.0; Tue, 16 Apr 2024 09:29:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1713284961; x=1713889761; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ERSdJnkxlnsAamkbGXEbd3rVP20U4VTq4AXaYwSzTK4=; b=m5remeGDhaa8m6vtpemN9IHJbNP48nVfOKmDYvADjaXCRlz6Xh+YnYkeMKNhWbz/WG YXe3PYSuemmN2TheJAXOz8f6eCMeBxqzu0nq4J7XmCDkHII6WGRfsEhAwsbQsgGayuF5 QxoSwY5Dhuj/r8jxz3lKhCkug47WQO7mmdv+YdfFqFPub3rz4qGwQONEbHENvjqeXvwT CkRglL/2dpxOr1LuxSWqdip8e7ydIbeXrFVokNRNKxilLvsNlayIsQ9WdImQBzJG2Z7w JwcIV9XPh4h+3pv+MFFDgR0u4NmHT0V42sgd1ZISWPxAc45rNzBqIiHobDTHH5y2GD1u c6dg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1713284961; x=1713889761; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ERSdJnkxlnsAamkbGXEbd3rVP20U4VTq4AXaYwSzTK4=; b=QGiMeNI1hxEFKNaPrefKMevhEjToBClU7tneANzmZx+ywqvzl1ZAHNrfQuXlnOFFzh wSEa7mgkeTld2M1rXARjYrf9GOMVt6az6iwQxEv+HLbjVSqT2/RNn3yYb5bMXv/mhw8Q qJgEo4Haz99SDuv+HQMgLL+aBMizgyjyZpmrgn2KH3XVnFClMClNFcyHPkV9e5VWxQBD pLUms3Bcc6QRMarEo1Uokl/cCkkMBQHXv0Ea/DGWY01Td11voJpVefW7hfZh7r1FQYvf Mg3QGkBLP1z9Z3DrgCLe+HPvCV3fWTKGYqUYVeGcUAEfHZGfMzSJEQAXcttx0vZG8N87 a5uw== X-Forwarded-Encrypted: i=1; AJvYcCXIzJw0q8Nl5rF4aKZWaIvRYPdks46bMN4NcnZw6/KAtfuEcYTSYcfmDx4Kas1X4D7QZnmneOKqcCyyOqWMAisLBHyOToAE5eBgTFAQK5q01L9b4iI6gH8qTrkAuzHGFZlJMsyApmFqPonaoPIWgap+qkEtOTq2tEOAN22BBZ5Hh+TdGvmF X-Gm-Message-State: AOJu0YzJVl48j/2oNBmakgcGBEGof5Gnbm2owpz5GsXWIWUfFpT2ItgR bDD3jShbYVY2EawdAd+taqU6LSrpo99vCE9HqGsWshR1xsRpSHVi X-Google-Smtp-Source: AGHT+IEgOpxZx3I5tU4e2wy/CEpm2oORaDSbppjjbJltxTZmqIiynZaKaL3dRR0kLnuX00xbwbTrtw== X-Received: by 2002:a05:6512:10c5:b0:518:c371:2db4 with SMTP id k5-20020a05651210c500b00518c3712db4mr7803127lfg.10.1713284960779; Tue, 16 Apr 2024 09:29:20 -0700 (PDT) Received: from localhost (srv1.baikalchip.ru. [87.245.175.227]) by smtp.gmail.com with ESMTPSA id a11-20020a056512374b00b0051926db8fe7sm223971lfs.228.2024.04.16.09.29.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Apr 2024 09:29:20 -0700 (PDT) From: Serge Semin To: Viresh Kumar , Andy Shevchenko , Vinod Koul Cc: Serge Semin , =?utf-8?q?Ilpo_J=C3=A4rvinen?= , Greg Kroah-Hartman , Jiri Slaby , dmaengine@vger.kernel.org, linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 4/4] dmaengine: dw: Simplify max-burst calculation procedure Date: Tue, 16 Apr 2024 19:28:58 +0300 Message-ID: <20240416162908.24180-5-fancer.lancer@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240416162908.24180-1-fancer.lancer@gmail.com> References: <20240416162908.24180-1-fancer.lancer@gmail.com> Precedence: bulk X-Mailing-List: linux-serial@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 In order to have a more coherent DW AHB DMA slave configuration method let's simplify the source and destination channel max-burst calculation procedure: 1. Create the max-burst verification method as it has been just done for the memory and peripheral address widths. Thus the DWC DMA slave config method will turn to a set of the verification methods execution. 2. Since both the generic DW AHB DMA and Intel DMA32 engines support the power-of-2 bursts only, then the specified by the client driver max-burst values can be converted to being power-of-2 right in the max-burst verification method. 3. Since max-burst encoded value is required on the CTL_LO fields calculation stage, the encode_maxburst() callback can be easily dropped from the dw_dma structure meanwhile the encoding procedure will be executed right in the CTL_LO register value calculation. Thus the update will provide the next positive effects: the internal DMA-slave config structure will contain only the real DMA-transfer config value, which will be encoded to the DMA-controller register fields only when it's required on the buffer mapping; the redundant encode_maxburst() callback will be dropped simplifying the internal HW-abstraction API; DWC-config method will look more readable executing the verification functions one-by-one. Signed-off-by: Serge Semin --- drivers/dma/dw/core.c | 26 +++++++++++++++++--------- drivers/dma/dw/dw.c | 23 +++++++++++------------ drivers/dma/dw/idma32.c | 15 +++++++-------- drivers/dma/dw/regs.h | 1 - 4 files changed, 35 insertions(+), 30 deletions(-) diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index 61e026310dd8..8b4ecd137ae2 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -779,6 +779,21 @@ bool dw_dma_filter(struct dma_chan *chan, void *param) } EXPORT_SYMBOL_GPL(dw_dma_filter); +static void dwc_verify_maxburst(struct dma_chan *chan) +{ + struct dw_dma_chan *dwc = to_dw_dma_chan(chan); + + dwc->dma_sconfig.src_maxburst = + clamp(dwc->dma_sconfig.src_maxburst, 1U, dwc->max_burst); + dwc->dma_sconfig.dst_maxburst = + clamp(dwc->dma_sconfig.dst_maxburst, 1U, dwc->max_burst); + + dwc->dma_sconfig.src_maxburst = + rounddown_pow_of_two(dwc->dma_sconfig.src_maxburst); + dwc->dma_sconfig.dst_maxburst = + rounddown_pow_of_two(dwc->dma_sconfig.dst_maxburst); +} + static int dwc_verify_p_buswidth(struct dma_chan *chan) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); @@ -828,7 +843,7 @@ static int dwc_verify_m_buswidth(struct dma_chan *chan) dwc->dma_sconfig.src_addr_width = mem_width; } else if (dwc->dma_sconfig.direction == DMA_DEV_TO_MEM) { reg_width = dwc->dma_sconfig.src_addr_width; - reg_burst = rounddown_pow_of_two(dwc->dma_sconfig.src_maxburst); + reg_burst = dwc->dma_sconfig.src_maxburst; dwc->dma_sconfig.dst_addr_width = min(mem_width, reg_width * reg_burst); } @@ -839,15 +854,11 @@ static int dwc_verify_m_buswidth(struct dma_chan *chan) static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig) { struct dw_dma_chan *dwc = to_dw_dma_chan(chan); - struct dw_dma *dw = to_dw_dma(chan->device); int err; memcpy(&dwc->dma_sconfig, sconfig, sizeof(*sconfig)); - dwc->dma_sconfig.src_maxburst = - clamp(dwc->dma_sconfig.src_maxburst, 1U, dwc->max_burst); - dwc->dma_sconfig.dst_maxburst = - clamp(dwc->dma_sconfig.dst_maxburst, 1U, dwc->max_burst); + dwc_verify_maxburst(chan); err = dwc_verify_p_buswidth(chan); if (err) @@ -857,9 +868,6 @@ static int dwc_config(struct dma_chan *chan, struct dma_slave_config *sconfig) if (err) return err; - dw->encode_maxburst(dwc, &dwc->dma_sconfig.src_maxburst); - dw->encode_maxburst(dwc, &dwc->dma_sconfig.dst_maxburst); - return 0; } diff --git a/drivers/dma/dw/dw.c b/drivers/dma/dw/dw.c index c65438d1f1ff..c52333646edd 100644 --- a/drivers/dma/dw/dw.c +++ b/drivers/dma/dw/dw.c @@ -64,6 +64,15 @@ static size_t dw_dma_block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width) return DWC_CTLH_BLOCK_TS(block) << width; } +static inline u8 dw_dma_encode_maxburst(u32 maxburst) +{ + /* + * Fix burst size according to dw_dmac. We need to convert them as: + * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. + */ + return maxburst > 1 ? fls(maxburst) - 2 : 0; +} + static u32 dw_dma_prepare_ctllo(struct dw_dma_chan *dwc) { struct dma_slave_config *sconfig = &dwc->dma_sconfig; @@ -73,10 +82,10 @@ static u32 dw_dma_prepare_ctllo(struct dw_dma_chan *dwc) sms = dwc->dws.m_master; smsize = 0; dms = dwc->dws.p_master; - dmsize = sconfig->dst_maxburst; + dmsize = dw_dma_encode_maxburst(sconfig->dst_maxburst); } else if (dwc->direction == DMA_DEV_TO_MEM) { sms = dwc->dws.p_master; - smsize = sconfig->src_maxburst; + smsize = dw_dma_encode_maxburst(sconfig->src_maxburst); dms = dwc->dws.m_master; dmsize = 0; } else /* DMA_MEM_TO_MEM */ { @@ -91,15 +100,6 @@ static u32 dw_dma_prepare_ctllo(struct dw_dma_chan *dwc) DWC_CTLL_DMS(dms) | DWC_CTLL_SMS(sms); } -static void dw_dma_encode_maxburst(struct dw_dma_chan *dwc, u32 *maxburst) -{ - /* - * Fix burst size according to dw_dmac. We need to convert them as: - * 1 -> 0, 4 -> 1, 8 -> 2, 16 -> 3. - */ - *maxburst = *maxburst > 1 ? fls(*maxburst) - 2 : 0; -} - static void dw_dma_set_device_name(struct dw_dma *dw, int id) { snprintf(dw->name, sizeof(dw->name), "dw:dmac%d", id); @@ -128,7 +128,6 @@ int dw_dma_probe(struct dw_dma_chip *chip) dw->suspend_chan = dw_dma_suspend_chan; dw->resume_chan = dw_dma_resume_chan; dw->prepare_ctllo = dw_dma_prepare_ctllo; - dw->encode_maxburst = dw_dma_encode_maxburst; dw->bytes2block = dw_dma_bytes2block; dw->block2bytes = dw_dma_block2bytes; diff --git a/drivers/dma/dw/idma32.c b/drivers/dma/dw/idma32.c index 3a1b12517655..428aba9fc2db 100644 --- a/drivers/dma/dw/idma32.c +++ b/drivers/dma/dw/idma32.c @@ -199,6 +199,11 @@ static size_t idma32_block2bytes(struct dw_dma_chan *dwc, u32 block, u32 width) return IDMA32C_CTLH_BLOCK_TS(block); } +static inline u32 idma32_encode_maxburst(u32 maxburst) +{ + return maxburst > 1 ? fls(maxburst) - 1 : 0; +} + static u32 idma32_prepare_ctllo(struct dw_dma_chan *dwc) { struct dma_slave_config *sconfig = &dwc->dma_sconfig; @@ -206,9 +211,9 @@ static u32 idma32_prepare_ctllo(struct dw_dma_chan *dwc) if (dwc->direction == DMA_MEM_TO_DEV) { smsize = 0; - dmsize = sconfig->dst_maxburst; + dmsize = idma32_encode_maxburst(sconfig->dst_maxburst); } else if (dwc->direction == DMA_DEV_TO_MEM) { - smsize = sconfig->src_maxburst; + smsize = idma32_encode_maxburst(sconfig->src_maxburst); dmsize = 0; } else /* DMA_MEM_TO_MEM */ { smsize = 0; @@ -219,11 +224,6 @@ static u32 idma32_prepare_ctllo(struct dw_dma_chan *dwc) DWC_CTLL_DST_MSIZE(dmsize) | DWC_CTLL_SRC_MSIZE(smsize); } -static void idma32_encode_maxburst(struct dw_dma_chan *dwc, u32 *maxburst) -{ - *maxburst = *maxburst > 1 ? fls(*maxburst) - 1 : 0; -} - static void idma32_set_device_name(struct dw_dma *dw, int id) { snprintf(dw->name, sizeof(dw->name), "idma32:dmac%d", id); @@ -280,7 +280,6 @@ int idma32_dma_probe(struct dw_dma_chip *chip) dw->suspend_chan = idma32_suspend_chan; dw->resume_chan = idma32_resume_chan; dw->prepare_ctllo = idma32_prepare_ctllo; - dw->encode_maxburst = idma32_encode_maxburst; dw->bytes2block = idma32_bytes2block; dw->block2bytes = idma32_block2bytes; diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h index 76654bd13c1a..5969d9cc8d7a 100644 --- a/drivers/dma/dw/regs.h +++ b/drivers/dma/dw/regs.h @@ -327,7 +327,6 @@ struct dw_dma { void (*suspend_chan)(struct dw_dma_chan *dwc, bool drain); void (*resume_chan)(struct dw_dma_chan *dwc, bool drain); u32 (*prepare_ctllo)(struct dw_dma_chan *dwc); - void (*encode_maxburst)(struct dw_dma_chan *dwc, u32 *maxburst); u32 (*bytes2block)(struct dw_dma_chan *dwc, size_t bytes, unsigned int width, size_t *len); size_t (*block2bytes)(struct dw_dma_chan *dwc, u32 block, u32 width);