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: at_xdmac: add runtime pm support

Add runtime PM support which involves disabling/enabling controller's
clocks on runtime PM suspend/resume ops. The runtime suspend/resume is
done based on the work submitted to the controller: runtime resume is
happening on at_xdmac_start_xfer() and runtime suspend on
at_xdmac_tasklet().

Signed-off-by: Claudiu Beznea <claudiu.beznea@microchip.com>
Link: https://lore.kernel.org/r/20221117131547.293044-2-claudiu.beznea@microchip.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Claudiu Beznea and committed by
Vinod Koul
650b0e99 610b573e

+203 -16
+203 -16
drivers/dma/at_xdmac.c
··· 21 21 #include <linux/of_platform.h> 22 22 #include <linux/platform_device.h> 23 23 #include <linux/pm.h> 24 + #include <linux/pm_runtime.h> 24 25 25 26 #include "dmaengine.h" 26 27 ··· 241 240 struct at_xdmac { 242 241 struct dma_device dma; 243 242 void __iomem *regs; 243 + struct device *dev; 244 244 int irq; 245 245 struct clk *clk; 246 246 u32 save_gim; ··· 363 361 "initial descriptors per channel (default: 64)"); 364 362 365 363 364 + static void at_xdmac_runtime_suspend_descriptors(struct at_xdmac_chan *atchan) 365 + { 366 + struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); 367 + struct at_xdmac_desc *desc, *_desc; 368 + 369 + list_for_each_entry_safe(desc, _desc, &atchan->xfers_list, xfer_node) { 370 + if (!desc->active_xfer) 371 + continue; 372 + 373 + pm_runtime_mark_last_busy(atxdmac->dev); 374 + pm_runtime_put_autosuspend(atxdmac->dev); 375 + } 376 + } 377 + 378 + static int at_xdmac_runtime_resume_descriptors(struct at_xdmac_chan *atchan) 379 + { 380 + struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); 381 + struct at_xdmac_desc *desc, *_desc; 382 + int ret; 383 + 384 + list_for_each_entry_safe(desc, _desc, &atchan->xfers_list, xfer_node) { 385 + if (!desc->active_xfer) 386 + continue; 387 + 388 + ret = pm_runtime_resume_and_get(atxdmac->dev); 389 + if (ret < 0) 390 + return ret; 391 + } 392 + 393 + return 0; 394 + } 395 + 366 396 static bool at_xdmac_chan_is_enabled(struct at_xdmac_chan *atchan) 367 397 { 368 - return at_xdmac_chan_read(atchan, AT_XDMAC_GS) & atchan->mask; 398 + struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); 399 + int ret; 400 + 401 + ret = pm_runtime_resume_and_get(atxdmac->dev); 402 + if (ret < 0) 403 + return false; 404 + 405 + ret = !!(at_xdmac_chan_read(atchan, AT_XDMAC_GS) & atchan->mask); 406 + 407 + pm_runtime_mark_last_busy(atxdmac->dev); 408 + pm_runtime_put_autosuspend(atxdmac->dev); 409 + 410 + return ret; 369 411 } 370 412 371 413 static void at_xdmac_off(struct at_xdmac *atxdmac) 372 414 { 415 + struct dma_chan *chan, *_chan; 416 + struct at_xdmac_chan *atchan; 417 + int ret; 418 + 419 + ret = pm_runtime_resume_and_get(atxdmac->dev); 420 + if (ret < 0) 421 + return; 422 + 373 423 at_xdmac_write(atxdmac, AT_XDMAC_GD, -1L); 374 424 375 425 /* Wait that all chans are disabled. */ ··· 429 375 cpu_relax(); 430 376 431 377 at_xdmac_write(atxdmac, AT_XDMAC_GID, -1L); 378 + 379 + /* Decrement runtime PM ref counter for each active descriptor. */ 380 + if (!list_empty(&atxdmac->dma.channels)) { 381 + list_for_each_entry_safe(chan, _chan, &atxdmac->dma.channels, 382 + device_node) { 383 + atchan = to_at_xdmac_chan(chan); 384 + at_xdmac_runtime_suspend_descriptors(atchan); 385 + } 386 + } 387 + 388 + pm_runtime_mark_last_busy(atxdmac->dev); 389 + pm_runtime_put_autosuspend(atxdmac->dev); 432 390 } 433 391 434 392 /* Call with lock hold. */ ··· 449 383 { 450 384 struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); 451 385 u32 reg; 386 + int ret; 387 + 388 + ret = pm_runtime_resume_and_get(atxdmac->dev); 389 + if (ret < 0) 390 + return; 452 391 453 392 dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, first); 454 393 ··· 1534 1463 struct at_xdmac_desc *desc, *_desc, *iter; 1535 1464 struct list_head *descs_list; 1536 1465 enum dma_status ret; 1537 - int residue, retry; 1466 + int residue, retry, pm_status; 1538 1467 u32 cur_nda, check_nda, cur_ubc, mask, value; 1539 1468 u8 dwidth = 0; 1540 1469 unsigned long flags; ··· 1543 1472 ret = dma_cookie_status(chan, cookie, txstate); 1544 1473 if (ret == DMA_COMPLETE || !txstate) 1545 1474 return ret; 1475 + 1476 + pm_status = pm_runtime_resume_and_get(atxdmac->dev); 1477 + if (pm_status < 0) 1478 + return DMA_ERROR; 1546 1479 1547 1480 spin_lock_irqsave(&atchan->lock, flags); 1548 1481 ··· 1665 1590 1666 1591 spin_unlock: 1667 1592 spin_unlock_irqrestore(&atchan->lock, flags); 1593 + pm_runtime_mark_last_busy(atxdmac->dev); 1594 + pm_runtime_put_autosuspend(atxdmac->dev); 1668 1595 return ret; 1669 1596 } 1670 1597 ··· 1713 1636 { 1714 1637 struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); 1715 1638 struct at_xdmac_desc *bad_desc; 1639 + int ret; 1640 + 1641 + ret = pm_runtime_resume_and_get(atxdmac->dev); 1642 + if (ret < 0) 1643 + return; 1716 1644 1717 1645 /* 1718 1646 * The descriptor currently at the head of the active list is ··· 1747 1665 __func__, &bad_desc->lld.mbr_sa, &bad_desc->lld.mbr_da, 1748 1666 bad_desc->lld.mbr_ubc); 1749 1667 1668 + pm_runtime_mark_last_busy(atxdmac->dev); 1669 + pm_runtime_put_autosuspend(atxdmac->dev); 1670 + 1750 1671 /* Then continue with usual descriptor management */ 1751 1672 } 1752 1673 1753 1674 static void at_xdmac_tasklet(struct tasklet_struct *t) 1754 1675 { 1755 1676 struct at_xdmac_chan *atchan = from_tasklet(atchan, t, tasklet); 1677 + struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); 1756 1678 struct at_xdmac_desc *desc; 1757 1679 struct dma_async_tx_descriptor *txd; 1758 1680 u32 error_mask; ··· 1806 1720 list_splice_tail_init(&desc->descs_list, &atchan->free_descs_list); 1807 1721 at_xdmac_advance_work(atchan); 1808 1722 spin_unlock_irq(&atchan->lock); 1723 + 1724 + /* 1725 + * Decrement runtime PM ref counter incremented in 1726 + * at_xdmac_start_xfer(). 1727 + */ 1728 + pm_runtime_mark_last_busy(atxdmac->dev); 1729 + pm_runtime_put_autosuspend(atxdmac->dev); 1809 1730 } 1810 1731 1811 1732 static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id) ··· 1904 1811 struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); 1905 1812 struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); 1906 1813 unsigned long flags; 1814 + int ret; 1907 1815 1908 1816 dev_dbg(chan2dev(chan), "%s\n", __func__); 1909 1817 1910 1818 if (test_and_set_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status)) 1911 1819 return 0; 1912 1820 1821 + ret = pm_runtime_resume_and_get(atxdmac->dev); 1822 + if (ret < 0) 1823 + return ret; 1824 + 1913 1825 spin_lock_irqsave(&atchan->lock, flags); 1914 1826 at_xdmac_write(atxdmac, atxdmac->layout->grws, atchan->mask); 1915 1827 while (at_xdmac_chan_read(atchan, AT_XDMAC_CC) 1916 1828 & (AT_XDMAC_CC_WRIP | AT_XDMAC_CC_RDIP)) 1917 1829 cpu_relax(); 1830 + 1831 + /* Decrement runtime PM ref counter for each active descriptor. */ 1832 + at_xdmac_runtime_suspend_descriptors(atchan); 1833 + 1918 1834 spin_unlock_irqrestore(&atchan->lock, flags); 1835 + 1836 + pm_runtime_mark_last_busy(atxdmac->dev); 1837 + pm_runtime_put_autosuspend(atxdmac->dev); 1919 1838 1920 1839 return 0; 1921 1840 } ··· 1937 1832 struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); 1938 1833 struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); 1939 1834 unsigned long flags; 1835 + int ret; 1940 1836 1941 1837 dev_dbg(chan2dev(chan), "%s\n", __func__); 1942 1838 1839 + ret = pm_runtime_resume_and_get(atxdmac->dev); 1840 + if (ret < 0) 1841 + return ret; 1842 + 1943 1843 spin_lock_irqsave(&atchan->lock, flags); 1944 - if (!at_xdmac_chan_is_paused(atchan)) { 1945 - spin_unlock_irqrestore(&atchan->lock, flags); 1946 - return 0; 1947 - } 1844 + if (!at_xdmac_chan_is_paused(atchan)) 1845 + goto unlock; 1846 + 1847 + /* Increment runtime PM ref counter for each active descriptor. */ 1848 + ret = at_xdmac_runtime_resume_descriptors(atchan); 1849 + if (ret < 0) 1850 + goto unlock; 1948 1851 1949 1852 at_xdmac_write(atxdmac, atxdmac->layout->grwr, atchan->mask); 1950 1853 clear_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status); 1951 - spin_unlock_irqrestore(&atchan->lock, flags); 1952 1854 1953 - return 0; 1855 + unlock: 1856 + spin_unlock_irqrestore(&atchan->lock, flags); 1857 + pm_runtime_mark_last_busy(atxdmac->dev); 1858 + pm_runtime_put_autosuspend(atxdmac->dev); 1859 + 1860 + return ret; 1954 1861 } 1955 1862 1956 1863 static int at_xdmac_device_terminate_all(struct dma_chan *chan) ··· 1971 1854 struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); 1972 1855 struct at_xdmac *atxdmac = to_at_xdmac(atchan->chan.device); 1973 1856 unsigned long flags; 1857 + int ret; 1974 1858 1975 1859 dev_dbg(chan2dev(chan), "%s\n", __func__); 1860 + 1861 + ret = pm_runtime_resume_and_get(atxdmac->dev); 1862 + if (ret < 0) 1863 + return ret; 1976 1864 1977 1865 spin_lock_irqsave(&atchan->lock, flags); 1978 1866 at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask); ··· 1989 1867 list_del(&desc->xfer_node); 1990 1868 list_splice_tail_init(&desc->descs_list, 1991 1869 &atchan->free_descs_list); 1870 + /* 1871 + * We incremented the runtime PM reference count on 1872 + * at_xdmac_start_xfer() for this descriptor. Now it's time 1873 + * to release it. 1874 + */ 1875 + if (desc->active_xfer) { 1876 + pm_runtime_put_autosuspend(atxdmac->dev); 1877 + pm_runtime_mark_last_busy(atxdmac->dev); 1878 + } 1992 1879 } 1993 1880 1994 1881 clear_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status); 1995 1882 clear_bit(AT_XDMAC_CHAN_IS_CYCLIC, &atchan->status); 1996 1883 spin_unlock_irqrestore(&atchan->lock, flags); 1884 + 1885 + pm_runtime_mark_last_busy(atxdmac->dev); 1886 + pm_runtime_put_autosuspend(atxdmac->dev); 1997 1887 1998 1888 return 0; 1999 1889 } ··· 2108 1974 { 2109 1975 struct at_xdmac *atxdmac = dev_get_drvdata(dev); 2110 1976 struct dma_chan *chan, *_chan; 1977 + int ret; 1978 + 1979 + ret = pm_runtime_resume_and_get(atxdmac->dev); 1980 + if (ret < 0) 1981 + return ret; 2111 1982 2112 1983 list_for_each_entry_safe(chan, _chan, &atxdmac->dma.channels, device_node) { 2113 1984 struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); ··· 2125 1986 atchan->save_cnda = at_xdmac_chan_read(atchan, AT_XDMAC_CNDA); 2126 1987 atchan->save_cndc = at_xdmac_chan_read(atchan, AT_XDMAC_CNDC); 2127 1988 } 1989 + 1990 + at_xdmac_runtime_suspend_descriptors(atchan); 2128 1991 } 2129 1992 atxdmac->save_gim = at_xdmac_read(atxdmac, AT_XDMAC_GIM); 2130 1993 2131 1994 at_xdmac_off(atxdmac); 2132 - clk_disable_unprepare(atxdmac->clk); 2133 - return 0; 1995 + return pm_runtime_force_suspend(atxdmac->dev); 2134 1996 } 2135 1997 2136 1998 static int __maybe_unused atmel_xdmac_resume(struct device *dev) ··· 2143 2003 int i; 2144 2004 int ret; 2145 2005 2146 - ret = clk_prepare_enable(atxdmac->clk); 2147 - if (ret) 2006 + ret = pm_runtime_force_resume(atxdmac->dev); 2007 + if (ret < 0) 2148 2008 return ret; 2149 2009 2150 2010 at_xdmac_axi_config(pdev); ··· 2159 2019 at_xdmac_write(atxdmac, AT_XDMAC_GIE, atxdmac->save_gim); 2160 2020 list_for_each_entry_safe(chan, _chan, &atxdmac->dma.channels, device_node) { 2161 2021 atchan = to_at_xdmac_chan(chan); 2022 + 2023 + ret = at_xdmac_runtime_resume_descriptors(atchan); 2024 + if (ret < 0) 2025 + return ret; 2026 + 2162 2027 at_xdmac_chan_write(atchan, AT_XDMAC_CC, atchan->save_cc); 2163 2028 if (at_xdmac_chan_is_cyclic(atchan)) { 2164 2029 if (at_xdmac_chan_is_paused(atchan)) ··· 2175 2030 at_xdmac_write(atxdmac, AT_XDMAC_GE, atchan->mask); 2176 2031 } 2177 2032 } 2033 + 2034 + pm_runtime_mark_last_busy(atxdmac->dev); 2035 + pm_runtime_put_autosuspend(atxdmac->dev); 2036 + 2178 2037 return 0; 2038 + } 2039 + 2040 + static int __maybe_unused atmel_xdmac_runtime_suspend(struct device *dev) 2041 + { 2042 + struct at_xdmac *atxdmac = dev_get_drvdata(dev); 2043 + 2044 + clk_disable(atxdmac->clk); 2045 + 2046 + return 0; 2047 + } 2048 + 2049 + static int __maybe_unused atmel_xdmac_runtime_resume(struct device *dev) 2050 + { 2051 + struct at_xdmac *atxdmac = dev_get_drvdata(dev); 2052 + 2053 + return clk_enable(atxdmac->clk); 2179 2054 } 2180 2055 2181 2056 static int at_xdmac_probe(struct platform_device *pdev) ··· 2236 2071 2237 2072 atxdmac->regs = base; 2238 2073 atxdmac->irq = irq; 2074 + atxdmac->dev = &pdev->dev; 2239 2075 2240 2076 atxdmac->layout = of_device_get_match_data(&pdev->dev); 2241 2077 if (!atxdmac->layout) ··· 2301 2135 atxdmac->dma.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); 2302 2136 atxdmac->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; 2303 2137 2304 - /* Disable all chans and interrupts. */ 2305 - at_xdmac_off(atxdmac); 2138 + platform_set_drvdata(pdev, atxdmac); 2139 + 2140 + pm_runtime_set_autosuspend_delay(&pdev->dev, 500); 2141 + pm_runtime_use_autosuspend(&pdev->dev); 2142 + pm_runtime_set_active(&pdev->dev); 2143 + pm_runtime_enable(&pdev->dev); 2144 + pm_runtime_get_noresume(&pdev->dev); 2306 2145 2307 2146 /* Init channels. */ 2308 2147 INIT_LIST_HEAD(&atxdmac->dma.channels); 2148 + 2149 + /* Disable all chans and interrupts. */ 2150 + at_xdmac_off(atxdmac); 2151 + 2309 2152 for (i = 0; i < nr_channels; i++) { 2310 2153 struct at_xdmac_chan *atchan = &atxdmac->chan[i]; 2311 2154 ··· 2334 2159 while (at_xdmac_chan_read(atchan, AT_XDMAC_CIS)) 2335 2160 cpu_relax(); 2336 2161 } 2337 - platform_set_drvdata(pdev, atxdmac); 2338 2162 2339 2163 ret = dma_async_device_register(&atxdmac->dma); 2340 2164 if (ret) { 2341 2165 dev_err(&pdev->dev, "fail to register DMA engine device\n"); 2342 - goto err_clk_disable; 2166 + goto err_pm_disable; 2343 2167 } 2344 2168 2345 2169 ret = of_dma_controller_register(pdev->dev.of_node, ··· 2353 2179 2354 2180 at_xdmac_axi_config(pdev); 2355 2181 2182 + pm_runtime_mark_last_busy(&pdev->dev); 2183 + pm_runtime_put_autosuspend(&pdev->dev); 2184 + 2356 2185 return 0; 2357 2186 2358 2187 err_dma_unregister: 2359 2188 dma_async_device_unregister(&atxdmac->dma); 2189 + err_pm_disable: 2190 + pm_runtime_put_noidle(&pdev->dev); 2191 + pm_runtime_disable(&pdev->dev); 2192 + pm_runtime_set_suspended(&pdev->dev); 2193 + pm_runtime_dont_use_autosuspend(&pdev->dev); 2360 2194 err_clk_disable: 2361 2195 clk_disable_unprepare(atxdmac->clk); 2362 2196 err_free_irq: ··· 2380 2198 at_xdmac_off(atxdmac); 2381 2199 of_dma_controller_free(pdev->dev.of_node); 2382 2200 dma_async_device_unregister(&atxdmac->dma); 2201 + pm_runtime_disable(atxdmac->dev); 2202 + pm_runtime_set_suspended(&pdev->dev); 2203 + pm_runtime_dont_use_autosuspend(&pdev->dev); 2383 2204 clk_disable_unprepare(atxdmac->clk); 2384 2205 2385 2206 free_irq(atxdmac->irq, atxdmac); ··· 2400 2215 static const struct dev_pm_ops __maybe_unused atmel_xdmac_dev_pm_ops = { 2401 2216 .prepare = atmel_xdmac_prepare, 2402 2217 SET_LATE_SYSTEM_SLEEP_PM_OPS(atmel_xdmac_suspend, atmel_xdmac_resume) 2218 + SET_RUNTIME_PM_OPS(atmel_xdmac_runtime_suspend, 2219 + atmel_xdmac_runtime_resume, NULL) 2403 2220 }; 2404 2221 2405 2222 static const struct of_device_id atmel_xdmac_dt_ids[] = {