Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

dmaengine: stm32-dma3: restore channel semaphore status after suspend

Depending on the power state reached during suspend, the CxSEMCR register
could have been reset, and the semaphore released.
On resume, try to take the semaphore again. If the semaphore cannot be
taken, an error log displaying the channel number and channel user is
generated.

This requires introducing two new functions:
stm32_dma3_pm_suspend(), where the status of each channel is checked
because suspension is not allowed if a channel is still running;
stm32_dma3_pm_resume(), where the channel semaphore is restored if it was
taken before suspend.

Signed-off-by: Amelie Delaunay <amelie.delaunay@foss.st.com>
Link: https://patch.msgid.link/20251121-dma3_improv-v2-3-76a207b13ea6@foss.st.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Amelie Delaunay and committed by
Vinod Koul
dea737e3 d26eb4a7

+74 -1
+74 -1
drivers/dma/stm32/stm32-dma3.c
··· 1237 1237 bool prevent_refactor = !!FIELD_GET(STM32_DMA3_DT_NOPACK, chan->dt_config.tr_conf) || 1238 1238 !!FIELD_GET(STM32_DMA3_DT_NOREFACT, chan->dt_config.tr_conf); 1239 1239 1240 + /* Semaphore could be lost during suspend/resume */ 1241 + if (chan->semaphore_mode && !chan->semaphore_taken) 1242 + return NULL; 1243 + 1240 1244 count = stm32_dma3_get_ll_count(chan, len, prevent_refactor); 1241 1245 1242 1246 swdesc = stm32_dma3_chan_desc_alloc(chan, count); ··· 1300 1296 bool prevent_refactor = !!FIELD_GET(STM32_DMA3_DT_NOPACK, chan->dt_config.tr_conf) || 1301 1297 !!FIELD_GET(STM32_DMA3_DT_NOREFACT, chan->dt_config.tr_conf); 1302 1298 int ret; 1299 + 1300 + /* Semaphore could be lost during suspend/resume */ 1301 + if (chan->semaphore_mode && !chan->semaphore_taken) 1302 + return NULL; 1303 1303 1304 1304 count = 0; 1305 1305 for_each_sg(sgl, sg, sg_len, i) ··· 1390 1382 dma_addr_t src, dst; 1391 1383 u32 count, i, ctr1, ctr2; 1392 1384 int ret; 1385 + 1386 + /* Semaphore could be lost during suspend/resume */ 1387 + if (chan->semaphore_mode && !chan->semaphore_taken) 1388 + return NULL; 1393 1389 1394 1390 if (!buf_len || !period_len || period_len > STM32_DMA3_MAX_BLOCK_SIZE) { 1395 1391 dev_err(chan2dev(chan), "Invalid buffer/period length\n"); ··· 1944 1932 return ret; 1945 1933 } 1946 1934 1935 + static int stm32_dma3_pm_suspend(struct device *dev) 1936 + { 1937 + struct stm32_dma3_ddata *ddata = dev_get_drvdata(dev); 1938 + struct dma_device *dma_dev = &ddata->dma_dev; 1939 + struct dma_chan *c; 1940 + int ccr, ret; 1941 + 1942 + ret = pm_runtime_resume_and_get(dev); 1943 + if (ret < 0) 1944 + return ret; 1945 + 1946 + list_for_each_entry(c, &dma_dev->channels, device_node) { 1947 + struct stm32_dma3_chan *chan = to_stm32_dma3_chan(c); 1948 + 1949 + ccr = readl_relaxed(ddata->base + STM32_DMA3_CCR(chan->id)); 1950 + if (ccr & CCR_EN) { 1951 + dev_warn(dev, "Suspend is prevented: %s still in use by %s\n", 1952 + dma_chan_name(c), dev_name(c->slave)); 1953 + pm_runtime_put_sync(dev); 1954 + return -EBUSY; 1955 + } 1956 + } 1957 + 1958 + pm_runtime_put_sync(dev); 1959 + 1960 + pm_runtime_force_suspend(dev); 1961 + 1962 + return 0; 1963 + } 1964 + 1965 + static int stm32_dma3_pm_resume(struct device *dev) 1966 + { 1967 + struct stm32_dma3_ddata *ddata = dev_get_drvdata(dev); 1968 + struct dma_device *dma_dev = &ddata->dma_dev; 1969 + struct dma_chan *c; 1970 + int ret; 1971 + 1972 + ret = pm_runtime_force_resume(dev); 1973 + if (ret < 0) 1974 + return ret; 1975 + 1976 + ret = pm_runtime_resume_and_get(dev); 1977 + if (ret < 0) 1978 + return ret; 1979 + 1980 + /* 1981 + * Channel semaphores need to be restored in case of registers reset during low power. 1982 + * stm32_dma3_get_chan_sem() will prior check the semaphore status. 1983 + */ 1984 + list_for_each_entry(c, &dma_dev->channels, device_node) { 1985 + struct stm32_dma3_chan *chan = to_stm32_dma3_chan(c); 1986 + 1987 + if (chan->semaphore_mode && chan->semaphore_taken) 1988 + stm32_dma3_get_chan_sem(chan); 1989 + } 1990 + 1991 + pm_runtime_put_sync(dev); 1992 + 1993 + return 0; 1994 + } 1995 + 1947 1996 static const struct dev_pm_ops stm32_dma3_pm_ops = { 1948 - SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) 1997 + SYSTEM_SLEEP_PM_OPS(stm32_dma3_pm_suspend, stm32_dma3_pm_resume) 1949 1998 RUNTIME_PM_OPS(stm32_dma3_runtime_suspend, stm32_dma3_runtime_resume, NULL) 1950 1999 }; 1951 2000