mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 05:04:02 +02:00
dmaengine: dw-edma: Program endpoint function numbers
The eDMA/HDMA transfers the driver issues carry a requester function number in their TLPs, but nothing ever programs it: eDMA v0 leaves the FUNC_NUM field of the channel control word zero and HDMA leaves the per-channel func_num register at its reset value, so every transfer is attributed to function 0. That is invisible in single-function setups, but once the DMA block serves a non-zero endpoint function, its requests must carry that function's number for the host to attribute and translate them correctly. Record the function number in the chip data (PCI_FUNC() of the probing device for dw-edma-pcie) and program it per channel. Endpoint-local chip instances keep func_no at 0, so transfers issued by the endpoint-side driver remain PF0-attributed. Delegated channels are programmed by the host-side dw-edma-pcie instance when it takes over the channel, using that instance's PCI_FUNC(). Reviewed-by: Frank Li <Frank.Li@nxp.com> Signed-off-by: Koichiro Den <den@valinux.co.jp> Link: https://patch.msgid.link/20260721062815.4117887-15-den@valinux.co.jp Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
1d68178b34
commit
0613e7934e
|
|
@ -931,6 +931,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)
|
|||
chan = &dw->chan[i];
|
||||
|
||||
chan->dw = dw;
|
||||
chan->func_no = chip->func_no;
|
||||
|
||||
if (i < dw->wr_ch_cnt) {
|
||||
chan->id = i;
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ struct dw_edma_chan {
|
|||
struct dw_edma *dw;
|
||||
int id;
|
||||
enum dw_edma_dir dir;
|
||||
u8 func_no;
|
||||
|
||||
u32 ll_max;
|
||||
struct dw_edma_region ll_region; /* Linked list */
|
||||
|
|
|
|||
|
|
@ -473,6 +473,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
|
|||
|
||||
chip->mf = dma_data->mf;
|
||||
chip->flags = match->chip_flags;
|
||||
chip->func_no = PCI_FUNC(pdev->devfn);
|
||||
chip->nr_irqs = nr_irqs;
|
||||
chip->ops = match->plat_ops;
|
||||
chip->cfg_non_ll = dma_data->cfg_non_ll;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ enum dw_edma_control {
|
|||
DW_EDMA_V0_LLE = BIT(9),
|
||||
};
|
||||
|
||||
#define EDMA_V0_FUNC_NUM_MASK GENMASK(16, 12)
|
||||
|
||||
static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
|
||||
{
|
||||
return dw->chip->reg_base;
|
||||
|
|
@ -160,6 +162,11 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
|
|||
#define GET_CH_32(dw, dir, ch, name) \
|
||||
readl_ch(dw, dir, ch, &(__dw_ch_regs(dw, dir, ch)->name))
|
||||
|
||||
static u32 dw_edma_v0_func_num(struct dw_edma_chan *chan)
|
||||
{
|
||||
return FIELD_PREP(EDMA_V0_FUNC_NUM_MASK, chan->func_no);
|
||||
}
|
||||
|
||||
/* eDMA management callbacks */
|
||||
static void dw_edma_v0_core_ch_power(struct dw_edma *dw,
|
||||
enum dw_edma_dir dir, u16 id, bool enable)
|
||||
|
|
@ -463,7 +470,8 @@ static void dw_edma_v0_core_ch_enable(struct dw_edma_chan *chan)
|
|||
|
||||
/* Channel control */
|
||||
SET_CH_32(dw, chan->dir, chan->id, ch_control1,
|
||||
(DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
|
||||
DW_EDMA_V0_CCS | DW_EDMA_V0_LLE |
|
||||
dw_edma_v0_func_num(chan));
|
||||
/* Linked list */
|
||||
/* llp is not aligned on 64bit -> keep 32bit accesses */
|
||||
SET_CH_32(dw, chan->dir, chan->id, llp.lsb,
|
||||
|
|
|
|||
|
|
@ -345,6 +345,9 @@ static void dw_hdma_v0_core_ch_config(struct dw_edma_chan *chan)
|
|||
SET_CH_32(dw, chan->dir, chan->id, msi_abort.msb, chan->msi.address_hi);
|
||||
/* config MSI data */
|
||||
SET_CH_32(dw, chan->dir, chan->id, msi_msgdata, chan->msi.data);
|
||||
/* Configure the requester function number used by outbound TLPs. */
|
||||
SET_CH_32(dw, chan->dir, chan->id, func_num,
|
||||
FIELD_PREP(HDMA_V0_FUNC_NUM_PF_MASK, chan->func_no));
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#define HDMA_V0_CONSUMER_CYCLE_BIT BIT(0)
|
||||
#define HDMA_V0_DOORBELL_START BIT(0)
|
||||
#define HDMA_V0_CH_STATUS_MASK GENMASK(1, 0)
|
||||
#define HDMA_V0_FUNC_NUM_PF_MASK GENMASK(7, 0)
|
||||
|
||||
struct dw_hdma_v0_ch_regs {
|
||||
u32 ch_en; /* 0x0000 */
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ enum dw_edma_ch_irq_mode {
|
|||
* @db_irq: Virtual IRQ dedicated to interrupt emulation
|
||||
* @db_offset: Offset from DMA register base
|
||||
* @mf: DMA register map format
|
||||
* @func_no: PCI endpoint function number used by DMA TLPs
|
||||
* @dw: struct dw_edma that is filled by dw_edma_probe()
|
||||
*/
|
||||
struct dw_edma_chip {
|
||||
|
|
@ -142,6 +143,7 @@ struct dw_edma_chip {
|
|||
resource_size_t db_offset;
|
||||
|
||||
enum dw_edma_map_format mf;
|
||||
u8 func_no;
|
||||
|
||||
struct dw_edma *dw;
|
||||
bool cfg_non_ll;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user