lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 21 Mar 2024 09:37:21 +0100
From: Krzysztof Kozlowski <krzysztof.kozlowski@...aro.org>
To: bin.yao@...enic.com, vkoul@...nel.org
Cc: robh+dt@...nel.org, krzysztof.kozlowski+dt@...aro.org,
 conor+dt@...nel.org, dmaengine@...r.kernel.org, devicetree@...r.kernel.org,
 linux-kernel@...r.kernel.org, 1587636487@...com
Subject: Re: [PATCH 1/2] dmaengine: ingenic: add Ingenic PDMA controller
 support.

On 21/03/2024 09:02, bin.yao@...enic.com wrote:
> From: "bin.yao" <bin.yao@...enic.com>
> 
> This module can be found on ingenic victory soc.
> 
> Signed-off-by: bin.yao <bin.yao@...enic.com>
> ---
>  drivers/dma/Kconfig        |    6 +
>  drivers/dma/Makefile       |    1 +
>  drivers/dma/ingenic-pdma.c | 1356 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 1363 insertions(+)
>  create mode 100644 drivers/dma/ingenic-pdma.c

..

> +static int ingenic_dma_chan_init(struct ingenic_dma_engine *dma, int id)
> +{
> +	struct ingenic_dma_chan *dmac = NULL;
> +
> +	if ((id < 0) || (id >= INGENIC_DMA_CHAN_CNT))
> +		return -EINVAL;
> +
> +	dmac = devm_kzalloc(dma->dev, sizeof(*dmac), GFP_KERNEL);
> +	if (!dmac)
> +		return -ENOMEM;
> +
> +	dmac->id = id;
> +	dmac->iomem = dma->iomem + dmac->id * DMACH_OFF;
> +	dmac->engine = dma;
> +
> +	spin_lock_init(&dmac->hdesc_lock);
> +	init_completion(&dmac->completion);
> +
> +	dmac->slave_id = pdma_maps[id] & INGENIC_DMA_TYPE_REQ_MSK;
> +	dma->chan[id] = dmac;
> +	INIT_LIST_HEAD(&dmac->ingenic_dma_sdesc_list_submitted);
> +	INIT_LIST_HEAD(&dmac->ingenic_dma_sdesc_list_issued);
> +
> +	dma_cookie_init(&dmac->chan);
> +	dmac->chan.device = &dma->dma_device;
> +	dmac->working_sdesc = NULL;
> +	list_add_tail(&dmac->chan.device_node, &dma->dma_device.channels);
> +	tasklet_init(&dmac->task, ingenic_dma_complete, (unsigned long)dmac);
> +
> +	return 0;
> +}
> +
> +static int ingenic_dma_probe(struct platform_device *pdev)
> +{
> +	struct ingenic_dma_engine *ingenic_dma = NULL;
> +	unsigned int reg_dmac = DMAC_DMAE;
> +	struct device *dev = &pdev->dev;
> +	struct resource *iores;
> +	int i, ret = 0;
> +
> +	if (!dev->of_node) {
> +		dev_err(dev, "This driver must be probed from devicetree\n");

This driver cannot be probed other way. Drop.

> +		return -EINVAL;
> +	}
> +
> +	ingenic_dma = devm_kzalloc(&pdev->dev, sizeof(struct ingenic_dma_engine),

ssizeof(*(

> +				   GFP_KERNEL);
> +	if (!ingenic_dma)
> +		return -ENOMEM;
> +
> +	ingenic_dma->dma_data = (struct ingenic_dma_data *)device_get_match_data(dev);

Why the cast?

> +	if (!ingenic_dma->dma_data)
> +		return -EINVAL;
> +
> +	/*
> +	 * Obtaining parameters from the device tree.
> +	 */

Drop obvious comments.

> +	ingenic_dma->dev = dev;
> +	if (!of_property_read_u32(pdev->dev.of_node, "programed-chs",

No, there is no such property. NAK.

Upstream your DTS or I will be NAKing your patches. Because otherwise
you try to sneak a lot of undocumented stuff here.

> +				  &ingenic_dma->chan_programed))
> +		ingenic_dma->chan_reserved |= ingenic_dma->chan_programed;
> +
> +	if (HWATTR_SPECIAL_CH01_SUP(ingenic_dma->dma_data->hwattr) &&
> +	    of_property_read_bool(pdev->dev.of_node, "special-chs")) {
> +		ingenic_dma->chan_reserved  |= DMA_SPECAIL_CHS;
> +		ingenic_dma->chan_programed |= DMA_SPECAIL_CHS;
> +		ingenic_dma->special_ch = true;
> +	}
> +
> +	ingenic_dma->intc_ch = -1;
> +	if (HWATTR_INTC_IRQ_SUP(ingenic_dma->dma_data->hwattr) &&
> +	    !of_property_read_u32(pdev->dev.of_node, "intc-ch",
> +				  &ingenic_dma->intc_ch)) {
> +
> +		if (BIT(ingenic_dma->intc_ch) & ingenic_dma->chan_reserved)
> +			dev_warn(ingenic_dma->dev,
> +				 "intc irq channel %d is already reserved\n",
> +				 ingenic_dma->intc_ch);
> +
> +		ingenic_dma->chan_reserved |= BIT(ingenic_dma->intc_ch);
> +	}
> +
> +	/*
> +	 * obtaining the base address of the DMA peripheral.
> +	 */

Drop obvious comments.

> +	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (iores) {
> +		ingenic_dma->iomem = devm_ioremap_resource(&pdev->dev, iores);

Combine these two, there's helper for this.

> +		if (IS_ERR(ingenic_dma->iomem))
> +			return PTR_ERR(ingenic_dma->iomem);
> +	} else {
> +		dev_err(dev, "Failed to get I/O memory\n");
> +		return -EINVAL;
> +	}
> +
> +	/*
> +	 * Get PDMA interrupt.
> +	 */

Drop

> +	ingenic_dma->irq_pdma = platform_get_irq_byname(pdev, "pdma");
> +	if (ingenic_dma->irq_pdma < 0) {
> +		dev_err(dev, "Unable to get pdma irq\n");
> +		return ingenic_dma->irq_pdma;

Syntax is return dev_err_probe().

> +	}
> +
> +	ret = devm_request_irq(&pdev->dev, ingenic_dma->irq_pdma,
> +			       pdma_int_handler, 0, "pdma", ingenic_dma);
> +	if (ret) {
> +		dev_err(dev, "Failed to request pdma irq\n");
> +		return ret;
> +	}
> +
> +	/*
> +	 * Get PDMA descriptor interrupt.
> +	 */
> +	if (HWATTR_DESC_INTER_SUP(ingenic_dma->dma_data->hwattr)) {
> +		ingenic_dma->irq_pdmad = platform_get_irq_byname(pdev, "pdmad");

NAK, you must be joking. You do not have second interrupt.

You must clean your code before upstream from all downstream weirdness
and incorrectness. You cannot send different binding than driver.

What's more, I don't trust that you will send usable binding, judging by
the driver, so I expect to see upstreamed DTS.

> +		if (ingenic_dma->irq_pdmad < 0) {
> +			dev_err(&pdev->dev, "Unable to get pdmad irq\n");
> +			return ingenic_dma->irq_pdmad;
> +		}
> +		ret = devm_request_irq(&pdev->dev, ingenic_dma->irq_pdmad,
> +				       pdmad_int_handler, 0, "pdmad", ingenic_dma);
> +		if (ret) {
> +			dev_err(dev, "Failed to request pdmad irq\n");
> +			return ret;
> +		}
> +	}
> +
> +	/*
> +	 * Initialize dma channel.
> +	 */
> +	INIT_LIST_HEAD(&ingenic_dma->dma_device.channels);
> +	for (i = 0; i < ingenic_dma->dma_data->nb_channels; i++) {
> +		/*reserved one channel for intc interrupt*/
> +		if (ingenic_dma->intc_ch == i)
> +			continue;
> +		ingenic_dma_chan_init(ingenic_dma, i);
> +	}
> +
> +	dma_cap_set(DMA_MEMCPY, ingenic_dma->dma_device.cap_mask);
> +	dma_cap_set(DMA_SLAVE, ingenic_dma->dma_device.cap_mask);
> +	dma_cap_set(DMA_CYCLIC, ingenic_dma->dma_device.cap_mask);
> +
> +	ingenic_dma->dma_device.dev = &pdev->dev;
> +	ingenic_dma->dma_device.device_alloc_chan_resources = ingenic_dma_alloc_chan_resources;
> +	ingenic_dma->dma_device.device_free_chan_resources = ingenic_dma_free_chan_resources;
> +	ingenic_dma->dma_device.device_tx_status = ingenic_dma_tx_status;
> +	ingenic_dma->dma_device.device_prep_slave_sg = ingenic_dma_prep_slave_sg;
> +	ingenic_dma->dma_device.device_prep_dma_cyclic = ingenic_dma_prep_dma_cyclic;
> +	ingenic_dma->dma_device.device_prep_dma_memcpy = ingenic_dma_prep_dma_memcpy;
> +	ingenic_dma->dma_device.device_config = ingenic_dma_config;
> +	ingenic_dma->dma_device.device_terminate_all = ingenic_dma_terminate_all;
> +	ingenic_dma->dma_device.device_issue_pending = ingenic_dma_issue_pending;
> +	ingenic_dma->dma_device.copy_align = DMAENGINE_ALIGN_4_BYTES;
> +	ingenic_dma->dma_device.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> +						  BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> +						  BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
> +	ingenic_dma->dma_device.dst_addr_widths = ingenic_dma->dma_device.src_addr_widths;
> +	ingenic_dma->dma_device.directions = BIT(DMA_DEV_TO_MEM) |
> +					     BIT(DMA_MEM_TO_DEV) |
> +					     BIT(DMA_MEM_TO_MEM);
> +	ingenic_dma->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
> +
> +	dma_set_max_seg_size(ingenic_dma->dma_device.dev, DTC_TC_MSK);
> +
> +	ingenic_dma->gate_clk = devm_clk_get(&pdev->dev, "gate_pdma");
> +	if (IS_ERR(ingenic_dma->gate_clk))
> +		return PTR_ERR(ingenic_dma->gate_clk);
> +
> +	ret = dma_async_device_register(&ingenic_dma->dma_device);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Unable to register dma\n");
> +		clk_disable(ingenic_dma->gate_clk);
> +		return ret;
> +	}
> +
> +	of_ingenic_dma_info.dma_cap = ingenic_dma->dma_device.cap_mask;
> +	ret = of_dma_controller_register(pdev->dev.of_node,
> +					 of_dma_simple_xlate,
> +					 &of_ingenic_dma_info);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Unable to register dma to device tree\n");
> +		dma_async_device_unregister(&ingenic_dma->dma_device);
> +		clk_disable(ingenic_dma->gate_clk);
> +		return ret;
> +	}
> +
> +	platform_set_drvdata(pdev, ingenic_dma);
> +
> +	clk_prepare_enable(ingenic_dma->gate_clk);
> +
> +	if (ingenic_dma->chan_programed)
> +		writel(ingenic_dma->chan_programed, ingenic_dma->iomem + DMACP);
> +	if (ingenic_dma->intc_ch >= 0)
> +		reg_dmac |= DMAC_INTCE |
> +			    ((ingenic_dma->intc_ch << DMAC_INTCC_SFT) & DMAC_INTCC_MSK);
> +	if (ingenic_dma->special_ch)
> +		reg_dmac |= DMAC_CH01;
> +	writel(reg_dmac, ingenic_dma->iomem + DMAC);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused ingenic_dma_suspend(struct device *dev)
> +{
> +	struct ingenic_dma_engine *ingenic_dma = dev_get_drvdata(dev);
> +	struct ingenic_dma_chan *dmac;
> +	unsigned long flg;
> +	int i;
> +
> +	for (i = 0; i < ingenic_dma->dma_data->nb_channels; i++) {
> +		dmac = ingenic_dma->chan[i];
> +		spin_lock_irqsave(&dmac->hdesc_lock, flg);
> +		if (!list_empty(&dmac->ingenic_dma_sdesc_list_submitted)) {
> +			spin_unlock_irqrestore(&dmac->hdesc_lock, flg);
> +			return -EBUSY;
> +		}
> +		if (!list_empty(&dmac->ingenic_dma_sdesc_list_issued)) {
> +			spin_unlock_irqrestore(&dmac->hdesc_lock, flg);
> +			return -EBUSY;
> +		}
> +		spin_unlock_irqrestore(&dmac->hdesc_lock, flg);
> +	}
> +	clk_disable_unprepare(ingenic_dma->gate_clk);
> +
> +	return 0;
> +}
> +
> +static int __maybe_unused ingenic_dma_resume(struct device *dev)
> +{
> +	struct ingenic_dma_engine *ingenic_dma = dev_get_drvdata(dev);
> +
> +	clk_prepare_enable(ingenic_dma->gate_clk);
> +
> +	return 0;
> +}
> +
> +static const struct dev_pm_ops ingenic_dma_dev_pm_ops = {
> +	SET_SYSTEM_SLEEP_PM_OPS(ingenic_dma_suspend, ingenic_dma_resume)
> +};
> +
> +static const struct ingenic_dma_data t33_soc_data = {
> +	.nb_channels = 32,
> +};
> +
> +static const struct of_device_id ingenic_dma_dt_match[] = {
> +	{ .compatible = "ingenic,t33-pdma",   .data = &t33_soc_data },

Don't merge lines. Open existing code and look how it is done there.

> +	{},
> +};
> +MODULE_DEVICE_TABLE(of, ingenic_dma_dt_match);
> +
> +static struct platform_driver ingenic_dma_driver = {
> +	.probe			= ingenic_dma_probe,
> +	.driver = {
> +		.name		= "ingenic-dma",
> +		.of_match_table = ingenic_dma_dt_match,
> +		.pm		= &ingenic_dma_dev_pm_ops,
> +	},
> +};
> +
> +static int __init ingenic_dma_init(void)
> +{
> +	return platform_driver_register(&ingenic_dma_driver);
> +}
> +subsys_initcall(ingenic_dma_init);
> +
> +static void __exit ingenic_dma_exit(void)
> +{
> +	platform_driver_unregister(&ingenic_dma_driver);
> +}
> +module_exit(ingenic_dma_exit);
> +
> +MODULE_AUTHOR("bin.yao <bin.yao@...enic.com>");
> +MODULE_DESCRIPTION("Ingenic dma driver");

Why do you add second Ingenic dma driver? That's duplication.

Best regards,
Krzysztof


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ