mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-04 04:02:26 +00:00
f0e870a0e9
The recently submitted fix-commit revealed a problem in the iDMA 32-bit platform code. Even though the controller supported only a single master the dw_dma_acpi_filter() method hard-coded two master interfaces with IDs 0 and 1. As a result the sanity check implemented in the commitb336268dde
("dmaengine: dw: Add peripheral bus width verification") got incorrect interface data width and thus prevented the client drivers from configuring the DMA-channel with the EINVAL error returned. E.g., the next error was printed for the PXA2xx SPI controller driver trying to configure the requested channels: > [ 164.525604] pxa2xx_spi_pci 0000:00:07.1: DMA slave config failed > [ 164.536105] pxa2xx_spi_pci 0000:00:07.1: failed to get DMA TX descriptor > [ 164.543213] spidev spi-SPT0001:00: SPI transfer failed: -16 The problem would have been spotted much earlier if the iDMA 32-bit controller supported more than one master interfaces. But since it supports just a single master and the iDMA 32-bit specific code just ignores the master IDs in the CTLLO preparation method, the issue has been gone unnoticed so far. Fix the problem by specifying the default master ID for both memory and peripheral devices in the driver data. Thus the issue noticed for the iDMA 32-bit controllers will be eliminated and the ACPI-probed DW DMA controllers will be configured with the correct master ID by default. Cc: stable@vger.kernel.org Fixes:b336268dde
("dmaengine: dw: Add peripheral bus width verification") Fixes:199244d694
("dmaengine: dw: add support of iDMA 32-bit hardware") Reported-by: Ferry Toth <fntoth@gmail.com> Closes: https://lore.kernel.org/dmaengine/ZuXbCKUs1iOqFu51@black.fi.intel.com/ Reported-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Closes: https://lore.kernel.org/dmaengine/ZuXgI-VcHpMgbZ91@black.fi.intel.com/ Tested-by: Ferry Toth <fntoth@gmail.com> Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://lore.kernel.org/r/20241104095142.157925-1-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
102 lines
2.7 KiB
C
102 lines
2.7 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Driver for the Synopsys DesignWare DMA Controller
|
|
*
|
|
* Copyright (C) 2013 Intel Corporation
|
|
*/
|
|
|
|
#ifndef _DMA_DW_INTERNAL_H
|
|
#define _DMA_DW_INTERNAL_H
|
|
|
|
#include <linux/dma/dw.h>
|
|
|
|
#include "regs.h"
|
|
|
|
int do_dma_probe(struct dw_dma_chip *chip);
|
|
int do_dma_remove(struct dw_dma_chip *chip);
|
|
|
|
void do_dw_dma_on(struct dw_dma *dw);
|
|
void do_dw_dma_off(struct dw_dma *dw);
|
|
|
|
int do_dw_dma_disable(struct dw_dma_chip *chip);
|
|
int do_dw_dma_enable(struct dw_dma_chip *chip);
|
|
|
|
extern bool dw_dma_filter(struct dma_chan *chan, void *param);
|
|
|
|
#ifdef CONFIG_ACPI
|
|
void dw_dma_acpi_controller_register(struct dw_dma *dw);
|
|
void dw_dma_acpi_controller_free(struct dw_dma *dw);
|
|
#else /* !CONFIG_ACPI */
|
|
static inline void dw_dma_acpi_controller_register(struct dw_dma *dw) {}
|
|
static inline void dw_dma_acpi_controller_free(struct dw_dma *dw) {}
|
|
#endif /* !CONFIG_ACPI */
|
|
|
|
struct platform_device;
|
|
|
|
#ifdef CONFIG_OF
|
|
struct dw_dma_platform_data *dw_dma_parse_dt(struct platform_device *pdev);
|
|
void dw_dma_of_controller_register(struct dw_dma *dw);
|
|
void dw_dma_of_controller_free(struct dw_dma *dw);
|
|
#else
|
|
static inline struct dw_dma_platform_data *dw_dma_parse_dt(struct platform_device *pdev)
|
|
{
|
|
return NULL;
|
|
}
|
|
static inline void dw_dma_of_controller_register(struct dw_dma *dw) {}
|
|
static inline void dw_dma_of_controller_free(struct dw_dma *dw) {}
|
|
#endif
|
|
|
|
struct dw_dma_chip_pdata {
|
|
const struct dw_dma_platform_data *pdata;
|
|
int (*probe)(struct dw_dma_chip *chip);
|
|
int (*remove)(struct dw_dma_chip *chip);
|
|
struct dw_dma_chip *chip;
|
|
u8 m_master;
|
|
u8 p_master;
|
|
};
|
|
|
|
static __maybe_unused const struct dw_dma_chip_pdata dw_dma_chip_pdata = {
|
|
.probe = dw_dma_probe,
|
|
.remove = dw_dma_remove,
|
|
.m_master = 0,
|
|
.p_master = 1,
|
|
};
|
|
|
|
static const struct dw_dma_platform_data idma32_pdata = {
|
|
.nr_channels = 8,
|
|
.chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
|
|
.chan_priority = CHAN_PRIORITY_ASCENDING,
|
|
.block_size = 131071,
|
|
.nr_masters = 1,
|
|
.data_width = {4},
|
|
.multi_block = {1, 1, 1, 1, 1, 1, 1, 1},
|
|
};
|
|
|
|
static __maybe_unused const struct dw_dma_chip_pdata idma32_chip_pdata = {
|
|
.pdata = &idma32_pdata,
|
|
.probe = idma32_dma_probe,
|
|
.remove = idma32_dma_remove,
|
|
.m_master = 0,
|
|
.p_master = 0,
|
|
};
|
|
|
|
static const struct dw_dma_platform_data xbar_pdata = {
|
|
.nr_channels = 8,
|
|
.chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
|
|
.chan_priority = CHAN_PRIORITY_ASCENDING,
|
|
.block_size = 131071,
|
|
.nr_masters = 1,
|
|
.data_width = {4},
|
|
.quirks = DW_DMA_QUIRK_XBAR_PRESENT,
|
|
};
|
|
|
|
static __maybe_unused const struct dw_dma_chip_pdata xbar_chip_pdata = {
|
|
.pdata = &xbar_pdata,
|
|
.probe = idma32_dma_probe,
|
|
.remove = idma32_dma_remove,
|
|
.m_master = 0,
|
|
.p_master = 0,
|
|
};
|
|
|
|
#endif /* _DMA_DW_INTERNAL_H */
|