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: qcom-adm: stop abusing slave_id config

The slave_id was previously used to pick one DMA slave instead of another,
but this is now done through the DMA descriptors in device tree.

For the qcom_adm driver, the configuration is documented in the DT
binding to contain a tuple of device identifier and a "crci" field,
but the implementation ends up using only a single cell for identifying
the slave, with the crci getting passed in nonstandard properties of
the device, and passed through the dma driver using the old slave_id
field. Part of the problem apparently is that the nand driver ends up
using only a single DMA request ID, but requires distinct values for
"crci" depending on the type of transfer.

Change both the dmaengine driver and the two slave drivers to allow
the documented binding to work in addition to the ad-hoc passing
of crci values. In order to no longer abuse the slave_id field, pass
the data using the "peripheral_config" mechanism instead.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Mark Brown <broonie@kernel.org>
Link: https://lore.kernel.org/r/20211122222203.4103644-9-arnd@kernel.org
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Arnd Bergmann and committed by
Vinod Koul
03de6b27 722d6d2b

+86 -11
+49 -7
drivers/dma/qcom/qcom_adm.c
··· 8 8 #include <linux/device.h> 9 9 #include <linux/dmaengine.h> 10 10 #include <linux/dma-mapping.h> 11 + #include <linux/dma/qcom_adm.h> 11 12 #include <linux/init.h> 12 13 #include <linux/interrupt.h> 13 14 #include <linux/io.h> ··· 141 140 142 141 struct adm_async_desc *curr_txd; 143 142 struct dma_slave_config slave; 143 + u32 crci; 144 + u32 mux; 144 145 struct list_head node; 145 146 146 147 int error; ··· 382 379 return ERR_PTR(-EINVAL); 383 380 } 384 381 385 - crci = achan->slave.slave_id & 0xf; 386 - if (!crci || achan->slave.slave_id > 0x1f) { 382 + crci = achan->crci & 0xf; 383 + if (!crci || achan->crci > 0x1f) { 387 384 dev_err(adev->dev, "invalid crci value\n"); 388 385 return ERR_PTR(-EINVAL); 389 386 } ··· 406 403 if (!async_desc) 407 404 return ERR_PTR(-ENOMEM); 408 405 409 - if (crci) 410 - async_desc->mux = achan->slave.slave_id & ADM_CRCI_MUX_SEL ? 411 - ADM_CRCI_CTL_MUX_SEL : 0; 406 + async_desc->mux = achan->mux ? ADM_CRCI_CTL_MUX_SEL : 0; 412 407 async_desc->crci = crci; 413 408 async_desc->blk_size = blk_size; 414 409 async_desc->dma_len = single_count * sizeof(struct adm_desc_hw_single) + ··· 489 488 static int adm_slave_config(struct dma_chan *chan, struct dma_slave_config *cfg) 490 489 { 491 490 struct adm_chan *achan = to_adm_chan(chan); 491 + struct qcom_adm_peripheral_config *config = cfg->peripheral_config; 492 492 unsigned long flag; 493 493 494 494 spin_lock_irqsave(&achan->vc.lock, flag); 495 495 memcpy(&achan->slave, cfg, sizeof(struct dma_slave_config)); 496 + if (cfg->peripheral_size == sizeof(config)) 497 + achan->crci = config->crci; 496 498 spin_unlock_irqrestore(&achan->vc.lock, flag); 497 499 498 500 return 0; ··· 698 694 achan->vc.desc_free = adm_dma_free_desc; 699 695 } 700 696 697 + /** 698 + * adm_dma_xlate 699 + * @dma_spec: pointer to DMA specifier as found in the device tree 700 + * @ofdma: pointer to DMA controller data 701 + * 702 + * This can use either 1-cell or 2-cell formats, the first cell 703 + * identifies the slave device, while the optional second cell 704 + * contains the crci value. 705 + * 706 + * Returns pointer to appropriate dma channel on success or NULL on error. 707 + */ 708 + static struct dma_chan *adm_dma_xlate(struct of_phandle_args *dma_spec, 709 + struct of_dma *ofdma) 710 + { 711 + struct dma_device *dev = ofdma->of_dma_data; 712 + struct dma_chan *chan, *candidate = NULL; 713 + struct adm_chan *achan; 714 + 715 + if (!dev || dma_spec->args_count > 2) 716 + return NULL; 717 + 718 + list_for_each_entry(chan, &dev->channels, device_node) 719 + if (chan->chan_id == dma_spec->args[0]) { 720 + candidate = chan; 721 + break; 722 + } 723 + 724 + if (!candidate) 725 + return NULL; 726 + 727 + achan = to_adm_chan(candidate); 728 + if (dma_spec->args_count == 2) 729 + achan->crci = dma_spec->args[1]; 730 + else 731 + achan->crci = 0; 732 + 733 + return dma_get_slave_channel(candidate); 734 + } 735 + 701 736 static int adm_dma_probe(struct platform_device *pdev) 702 737 { 703 738 struct adm_device *adev; ··· 881 838 goto err_disable_clks; 882 839 } 883 840 884 - ret = of_dma_controller_register(pdev->dev.of_node, 885 - of_dma_xlate_by_chan_id, 841 + ret = of_dma_controller_register(pdev->dev.of_node, adm_dma_xlate, 886 842 &adev->common); 887 843 if (ret) 888 844 goto err_unregister_dma;
+12 -2
drivers/mtd/nand/raw/qcom_nandc.c
··· 6 6 #include <linux/clk.h> 7 7 #include <linux/slab.h> 8 8 #include <linux/bitops.h> 9 + #include <linux/dma/qcom_adm.h> 9 10 #include <linux/dma-mapping.h> 10 11 #include <linux/dmaengine.h> 11 12 #include <linux/module.h> ··· 953 952 struct dma_async_tx_descriptor *dma_desc; 954 953 struct scatterlist *sgl; 955 954 struct dma_slave_config slave_conf; 955 + struct qcom_adm_peripheral_config periph_conf = {}; 956 956 enum dma_transfer_direction dir_eng; 957 957 int ret; 958 958 ··· 985 983 if (read) { 986 984 slave_conf.src_maxburst = 16; 987 985 slave_conf.src_addr = nandc->base_dma + reg_off; 988 - slave_conf.slave_id = nandc->data_crci; 986 + if (nandc->data_crci) { 987 + periph_conf.crci = nandc->data_crci; 988 + slave_conf.peripheral_config = &periph_conf; 989 + slave_conf.peripheral_size = sizeof(periph_conf); 990 + } 989 991 } else { 990 992 slave_conf.dst_maxburst = 16; 991 993 slave_conf.dst_addr = nandc->base_dma + reg_off; 992 - slave_conf.slave_id = nandc->cmd_crci; 994 + if (nandc->cmd_crci) { 995 + periph_conf.crci = nandc->cmd_crci; 996 + slave_conf.peripheral_config = &periph_conf; 997 + slave_conf.peripheral_size = sizeof(periph_conf); 998 + } 993 999 } 994 1000 995 1001 ret = dmaengine_slave_config(nandc->chan, &slave_conf);
+13 -2
drivers/tty/serial/msm_serial.c
··· 9 9 10 10 #include <linux/kernel.h> 11 11 #include <linux/atomic.h> 12 + #include <linux/dma/qcom_adm.h> 12 13 #include <linux/dma-mapping.h> 13 14 #include <linux/dmaengine.h> 14 15 #include <linux/module.h> ··· 291 290 { 292 291 struct device *dev = msm_port->uart.dev; 293 292 struct dma_slave_config conf; 293 + struct qcom_adm_peripheral_config periph_conf = {}; 294 294 struct msm_dma *dma; 295 295 u32 crci = 0; 296 296 int ret; ··· 310 308 conf.device_fc = true; 311 309 conf.dst_addr = base + UARTDM_TF; 312 310 conf.dst_maxburst = UARTDM_BURST_SIZE; 313 - conf.slave_id = crci; 311 + if (crci) { 312 + conf.peripheral_config = &periph_conf; 313 + conf.peripheral_size = sizeof(periph_conf); 314 + periph_conf.crci = crci; 315 + } 314 316 315 317 ret = dmaengine_slave_config(dma->chan, &conf); 316 318 if (ret) ··· 339 333 { 340 334 struct device *dev = msm_port->uart.dev; 341 335 struct dma_slave_config conf; 336 + struct qcom_adm_peripheral_config periph_conf = {}; 342 337 struct msm_dma *dma; 343 338 u32 crci = 0; 344 339 int ret; ··· 362 355 conf.device_fc = true; 363 356 conf.src_addr = base + UARTDM_RF; 364 357 conf.src_maxburst = UARTDM_BURST_SIZE; 365 - conf.slave_id = crci; 358 + if (crci) { 359 + conf.peripheral_config = &periph_conf; 360 + conf.peripheral_size = sizeof(periph_conf); 361 + periph_conf.crci = crci; 362 + } 366 363 367 364 ret = dmaengine_slave_config(dma->chan, &conf); 368 365 if (ret)
+12
include/linux/dma/qcom_adm.h
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + #ifndef __LINUX_DMA_QCOM_ADM_H 3 + #define __LINUX_DMA_QCOM_ADM_H 4 + 5 + #include <linux/types.h> 6 + 7 + struct qcom_adm_peripheral_config { 8 + u32 crci; 9 + u32 mux; 10 + }; 11 + 12 + #endif /* __LINUX_DMA_QCOM_ADM_H */