mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-24 01:41:39 +00:00
![Guennadi Liakhovetski](/assets/img/avatar_default.png)
The SH DMA driver wrongly assigns negative cookies to transfer descriptors, also, its chaining of partial descriptors is broken. The latter problem is usually invisible, because maximum transfer size per chunk is 16M, but if you artificially set this limit lower, the driver fails. Since cookies are also used in chunk management, both these problems are fixed in one patch. As side effects a possible memory leak, when descriptors are prepared, but not submitted, and multiple races have also been fixed. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Acked-by: Paul Mundt <lethal@linux-sh.org> Acked-by: Nobuhiro Iwamatsu <iwamatsu@nigauri.org> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
67 lines
1.9 KiB
C
67 lines
1.9 KiB
C
/*
|
|
* Renesas SuperH DMA Engine support
|
|
*
|
|
* Copyright (C) 2009 Nobuhiro Iwamatsu <iwamatsu.nobuhiro@renesas.com>
|
|
* Copyright (C) 2009 Renesas Solutions, Inc. All rights reserved.
|
|
*
|
|
* This is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
*/
|
|
#ifndef __DMA_SHDMA_H
|
|
#define __DMA_SHDMA_H
|
|
|
|
#include <linux/dmaengine.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/list.h>
|
|
|
|
#define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */
|
|
|
|
struct sh_dmae_regs {
|
|
u32 sar; /* SAR / source address */
|
|
u32 dar; /* DAR / destination address */
|
|
u32 tcr; /* TCR / transfer count */
|
|
};
|
|
|
|
struct sh_desc {
|
|
struct sh_dmae_regs hw;
|
|
struct list_head node;
|
|
struct dma_async_tx_descriptor async_tx;
|
|
dma_cookie_t cookie;
|
|
int chunks;
|
|
int mark;
|
|
};
|
|
|
|
struct device;
|
|
|
|
struct sh_dmae_chan {
|
|
dma_cookie_t completed_cookie; /* The maximum cookie completed */
|
|
spinlock_t desc_lock; /* Descriptor operation lock */
|
|
struct list_head ld_queue; /* Link descriptors queue */
|
|
struct list_head ld_free; /* Link descriptors free */
|
|
struct dma_chan common; /* DMA common channel */
|
|
struct device *dev; /* Channel device */
|
|
struct tasklet_struct tasklet; /* Tasklet */
|
|
int descs_allocated; /* desc count */
|
|
int id; /* Raw id of this channel */
|
|
char dev_id[16]; /* unique name per DMAC of channel */
|
|
|
|
/* Set chcr */
|
|
int (*set_chcr)(struct sh_dmae_chan *sh_chan, u32 regs);
|
|
/* Set DMA resource */
|
|
int (*set_dmars)(struct sh_dmae_chan *sh_chan, u16 res);
|
|
};
|
|
|
|
struct sh_dmae_device {
|
|
struct dma_device common;
|
|
struct sh_dmae_chan *chan[MAX_DMA_CHANNELS];
|
|
struct sh_dmae_pdata pdata;
|
|
};
|
|
|
|
#define to_sh_chan(chan) container_of(chan, struct sh_dmae_chan, common)
|
|
#define to_sh_desc(lh) container_of(lh, struct sh_desc, node)
|
|
#define tx_to_sh_desc(tx) container_of(tx, struct sh_desc, async_tx)
|
|
|
|
#endif /* __DMA_SHDMA_H */
|