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

Add `devm_dma_request_chan()` to simplify probe

Merge series from Bence Csókás <csokas.bence@prolan.hu>:

The probe function of the atmel-quadspi driver got quite convoluted,
especially since the addition of SAMA7G5 support, that was forward-ported
from an older vendor kernel. To alleivate this - and similar problems in
the future - an effort was made to migrate as many functions as possible,
to their devm_ managed counterparts. Patch 1/2 adds the new
`devm_dma_request_chan()` function. Patch 2/2 then uses this APIs to
simplify the probe() function.

+50 -35
+30
drivers/dma/dmaengine.c
··· 926 926 } 927 927 EXPORT_SYMBOL_GPL(dma_release_channel); 928 928 929 + static void dmaenginem_release_channel(void *chan) 930 + { 931 + dma_release_channel(chan); 932 + } 933 + 934 + /** 935 + * devm_dma_request_chan - try to allocate an exclusive slave channel 936 + * @dev: pointer to client device structure 937 + * @name: slave channel name 938 + * 939 + * Returns pointer to appropriate DMA channel on success or an error pointer. 940 + * 941 + * The operation is managed and will be undone on driver detach. 942 + */ 943 + 944 + struct dma_chan *devm_dma_request_chan(struct device *dev, const char *name) 945 + { 946 + struct dma_chan *chan = dma_request_chan(dev, name); 947 + int ret = 0; 948 + 949 + if (!IS_ERR(chan)) 950 + ret = devm_add_action_or_reset(dev, dmaenginem_release_channel, chan); 951 + 952 + if (ret) 953 + return ERR_PTR(ret); 954 + 955 + return chan; 956 + } 957 + EXPORT_SYMBOL_GPL(devm_dma_request_chan); 958 + 929 959 /** 930 960 * dmaengine_get - register interest in dma_channels 931 961 */
+13 -35
drivers/spi/atmel-quadspi.c
··· 1285 1285 struct atmel_qspi *aq = spi_controller_get_devdata(ctrl); 1286 1286 int ret; 1287 1287 1288 - aq->rx_chan = dma_request_chan(&aq->pdev->dev, "rx"); 1288 + aq->rx_chan = devm_dma_request_chan(&aq->pdev->dev, "rx"); 1289 1289 if (IS_ERR(aq->rx_chan)) { 1290 1290 ret = dev_err_probe(&aq->pdev->dev, PTR_ERR(aq->rx_chan), 1291 1291 "RX DMA channel is not available\n"); 1292 - goto null_rx_chan; 1292 + aq->rx_chan = NULL; 1293 + return ret; 1293 1294 } 1294 1295 1295 - aq->tx_chan = dma_request_chan(&aq->pdev->dev, "tx"); 1296 + aq->tx_chan = devm_dma_request_chan(&aq->pdev->dev, "tx"); 1296 1297 if (IS_ERR(aq->tx_chan)) { 1297 1298 ret = dev_err_probe(&aq->pdev->dev, PTR_ERR(aq->tx_chan), 1298 1299 "TX DMA channel is not available\n"); 1299 - goto release_rx_chan; 1300 + aq->rx_chan = NULL; 1301 + aq->tx_chan = NULL; 1302 + return ret; 1300 1303 } 1301 1304 1302 1305 ctrl->dma_rx = aq->rx_chan; ··· 1310 1307 dma_chan_name(aq->tx_chan), dma_chan_name(aq->rx_chan)); 1311 1308 1312 1309 return 0; 1313 - 1314 - release_rx_chan: 1315 - dma_release_channel(aq->rx_chan); 1316 - aq->tx_chan = NULL; 1317 - null_rx_chan: 1318 - aq->rx_chan = NULL; 1319 - return ret; 1320 - } 1321 - 1322 - static void atmel_qspi_dma_release(struct atmel_qspi *aq) 1323 - { 1324 - if (aq->rx_chan) 1325 - dma_release_channel(aq->rx_chan); 1326 - if (aq->tx_chan) 1327 - dma_release_channel(aq->tx_chan); 1328 1310 } 1329 1311 1330 1312 static const struct atmel_qspi_ops atmel_qspi_ops = { ··· 1414 1426 1415 1427 /* Request the IRQ */ 1416 1428 irq = platform_get_irq(pdev, 0); 1417 - if (irq < 0) { 1418 - err = irq; 1419 - goto dma_release; 1420 - } 1429 + if (irq < 0) 1430 + return irq; 1431 + 1421 1432 err = devm_request_irq(&pdev->dev, irq, atmel_qspi_interrupt, 1422 1433 0, dev_name(&pdev->dev), aq); 1423 1434 if (err) 1424 - goto dma_release; 1435 + return err; 1425 1436 1426 1437 pm_runtime_set_autosuspend_delay(&pdev->dev, 500); 1427 1438 pm_runtime_use_autosuspend(&pdev->dev); ··· 1429 1442 1430 1443 err = atmel_qspi_init(aq); 1431 1444 if (err) 1432 - goto dma_release; 1445 + return err; 1433 1446 1434 1447 err = spi_register_controller(ctrl); 1435 1448 if (err) 1436 - goto dma_release; 1449 + return err; 1437 1450 1438 1451 pm_runtime_mark_last_busy(&pdev->dev); 1439 1452 pm_runtime_put_autosuspend(&pdev->dev); 1440 1453 1441 1454 return 0; 1442 - 1443 - dma_release: 1444 - if (aq->caps->has_dma) 1445 - atmel_qspi_dma_release(aq); 1446 - 1447 - return err; 1448 1455 } 1449 1456 1450 1457 static int atmel_qspi_sama7g5_suspend(struct atmel_qspi *aq) ··· 1488 1507 1489 1508 ret = pm_runtime_get_sync(&pdev->dev); 1490 1509 if (ret >= 0) { 1491 - if (aq->caps->has_dma) 1492 - atmel_qspi_dma_release(aq); 1493 - 1494 1510 if (aq->caps->has_gclk) { 1495 1511 ret = atmel_qspi_sama7g5_suspend(aq); 1496 1512 if (ret)
+7
include/linux/dmaengine.h
··· 1524 1524 1525 1525 struct dma_chan *dma_request_chan(struct device *dev, const char *name); 1526 1526 struct dma_chan *dma_request_chan_by_mask(const dma_cap_mask_t *mask); 1527 + struct dma_chan *devm_dma_request_chan(struct device *dev, const char *name); 1527 1528 1528 1529 void dma_release_channel(struct dma_chan *chan); 1529 1530 int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps); ··· 1561 1560 { 1562 1561 return ERR_PTR(-ENODEV); 1563 1562 } 1563 + 1564 + static inline struct dma_chan *devm_dma_request_chan(struct device *dev, const char *name) 1565 + { 1566 + return ERR_PTR(-ENODEV); 1567 + } 1568 + 1564 1569 static inline void dma_release_channel(struct dma_chan *chan) 1565 1570 { 1566 1571 }