{
struct kpc_dma_descriptor *cur;
struct kpc_dma_device *eng = container_of(ws, struct kpc_dma_device, irq_work);
+
lock_engine(eng);
if (GetEngineCompletePtr(eng) == 0)
unlock_engine(eng);
}
-
/********** DMA Engine Init/Teardown **********/
void start_dma_engine(struct kpc_dma_device *eng)
{
dma_addr_t head_handle;
unsigned int i;
int rv;
+
dev_dbg(&eng->pldev->dev, "Setting up DMA engine [%p]\n", eng);
caps = GetEngineCapabilities(eng);
void stop_dma_engine(struct kpc_dma_device *eng)
{
unsigned long timeout;
+
dev_dbg(&eng->pldev->dev, "Destroying DMA engine [%p]\n", eng);
// Disable the descriptor engine
for (i = 0 ; i < eng->desc_pool_cnt ; i++) {
struct kpc_dma_descriptor *next = cur->Next;
dma_addr_t next_handle = cur->DescNextDescPtr;
+
dma_pool_free(eng->desc_pool, cur, cur_handle);
cur_handle = next_handle;
cur = next;
free_irq(eng->irq, eng);
}
-
-
/********** Helper Functions **********/
int count_descriptors_available(struct kpc_dma_device *eng)
{
u32 count = 0;
struct kpc_dma_descriptor *cur = eng->desc_next;
+
while (cur != eng->desc_completed) {
BUG_ON(cur == NULL);
count++;
{
unsigned long first = (iov_base & PAGE_MASK) >> PAGE_SHIFT;
unsigned long last = ((iov_base+iov_len-1) & PAGE_MASK) >> PAGE_SHIFT;
+
return last - first + 1;
}
unsigned int count_parts_for_sge(struct scatterlist *sg)
{
unsigned int sg_length = sg_dma_len(sg);
+
sg_length += (0x80000-1);
return (sg_length / 0x80000);
}
{
struct dev_private_data *priv;
struct kpc_dma_device *ldev = kpc_dma_lookup_device(iminor(inode));
+
if (ldev == NULL)
return -ENODEV;
struct kpc_dma_descriptor *cur;
struct dev_private_data *priv = (struct dev_private_data *)filp->private_data;
struct kpc_dma_device *eng = priv->ldev;
+
dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_close(inode = [%p], filp = [%p]) priv = [%p], ldev = [%p]\n", inode, filp, priv, priv->ldev);
lock_engine(eng);
int kpc_dma_aio_cancel(struct kiocb *kcb)
{
struct dev_private_data *priv = (struct dev_private_data *)kcb->ki_filp->private_data;
+
dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_aio_cancel(kcb = [%p]) priv = [%p], ldev = [%p]\n", kcb, priv, priv->ldev);
return 0;
}
ssize_t kpc_dma_aio_read(struct kiocb *kcb, const struct iovec *iov, unsigned long iov_count, loff_t pos)
{
struct dev_private_data *priv = (struct dev_private_data *)kcb->ki_filp->private_data;
+
dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_aio_read(kcb = [%p], iov = [%p], iov_count = %ld, pos = %lld) priv = [%p], ldev = [%p]\n", kcb, iov, iov_count, pos, priv, priv->ldev);
if (priv->ldev->dir != DMA_FROM_DEVICE)
ssize_t kpc_dma_aio_write(struct kiocb *kcb, const struct iovec *iov, unsigned long iov_count, loff_t pos)
{
struct dev_private_data *priv = (struct dev_private_data *)kcb->ki_filp->private_data;
+
dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_aio_write(kcb = [%p], iov = [%p], iov_count = %ld, pos = %lld) priv = [%p], ldev = [%p]\n", kcb, iov, iov_count, pos, priv, priv->ldev);
if (priv->ldev->dir != DMA_TO_DEVICE)
ssize_t kpc_dma_read(struct file *filp, char __user *user_buf, size_t count, loff_t *ppos)
{
struct dev_private_data *priv = (struct dev_private_data *)filp->private_data;
+
dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_read(filp = [%p], user_buf = [%p], count = %zu, ppos = [%p]) priv = [%p], ldev = [%p]\n", filp, user_buf, count, ppos, priv, priv->ldev);
if (priv->ldev->dir != DMA_FROM_DEVICE)
ssize_t kpc_dma_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *ppos)
{
struct dev_private_data *priv = (struct dev_private_data *)filp->private_data;
+
dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_write(filp = [%p], user_buf = [%p], count = %zu, ppos = [%p]) priv = [%p], ldev = [%p]\n", filp, user_buf, count, ppos, priv, priv->ldev);
if (priv->ldev->dir != DMA_TO_DEVICE)
long kpc_dma_ioctl(struct file *filp, unsigned int ioctl_num, unsigned long ioctl_param)
{
struct dev_private_data *priv = (struct dev_private_data *)filp->private_data;
+
dev_dbg(&priv->ldev->pldev->dev, "kpc_dma_ioctl(filp = [%p], ioctl_num = 0x%x, ioctl_param = 0x%lx) priv = [%p], ldev = [%p]\n", filp, ioctl_num, ioctl_param, priv, priv->ldev);
switch (ioctl_num) {
return -ENOTTY;
}
-
struct file_operations kpc_dma_fops = {
.owner = THIS_MODULE,
.open = kpc_dma_open,
static int assigned_major_num;
static LIST_HEAD(kpc_dma_list);
-
/********** kpc_dma_list list management **********/
struct kpc_dma_device *kpc_dma_lookup_device(int minor)
{
struct kpc_dma_device *c;
+
mutex_lock(&kpc_dma_mtx);
list_for_each_entry(c, &kpc_dma_list, list) {
if (c->pldev->id == minor) {
}
}
c = NULL; // not-found case
- out:
+out:
mutex_unlock(&kpc_dma_mtx);
return c;
}
{
struct kpc_dma_device *ldev;
struct platform_device *pldev = to_platform_device(dev);
+
if (!pldev)
return 0;
ldev = platform_get_drvdata(pldev);
struct class *kpc_dma_class;
-
/********** Platform Driver Functions **********/
static
int kpc_dma_probe(struct platform_device *pldev)
dev_t dev;
struct kpc_dma_device *ldev = kzalloc(sizeof(struct kpc_dma_device), GFP_KERNEL);
+
if (!ldev) {
dev_err(&pldev->dev, "kpc_dma_probe: unable to kzalloc space for kpc_dma_device\n");
rv = -ENOMEM;
int kpc_dma_remove(struct platform_device *pldev)
{
struct kpc_dma_device *ldev = platform_get_drvdata(pldev);
+
if (!ldev)
return -ENXIO;
return 0;
}
-
/********** Driver Functions **********/
struct platform_driver kpc_dma_plat_driver_i = {
.probe = kpc_dma_probe,
return err;
- fail_platdriver_register:
+fail_platdriver_register:
class_destroy(kpc_dma_class);
- fail_class_create:
+fail_class_create:
__unregister_chrdev(KPC_DMA_CHAR_MAJOR, 0, KPC_DMA_NUM_MINORS, "kpc_dma");
- fail_chrdev_register:
+fail_chrdev_register:
return err;
}
module_init(kpc_dma_driver_init);
#include <linux/bitops.h>
#include "../kpc.h"
-
struct kp2000_device;
struct kpc_dma_device {
struct list_head list;
{
writel(value, eng->eng_regs + 1);
}
+
static inline
u32 GetEngineControl(struct kpc_dma_device *eng)
{
return readl(eng->eng_regs + 1);
}
+
static inline
void SetClearEngineControl(struct kpc_dma_device *eng, u32 set_bits, u32 clear_bits)
{
u32 val = GetEngineControl(eng);
+
val |= set_bits;
val &= ~clear_bits;
WriteEngineControl(eng, val);
{
writel(desc->MyDMAAddr, eng->eng_regs + 2);
}
+
static inline
void SetEngineSWPtr(struct kpc_dma_device *eng, struct kpc_dma_descriptor *desc)
{
writel(desc->MyDMAAddr, eng->eng_regs + 3);
}
+
static inline
void ClearEngineCompletePtr(struct kpc_dma_device *eng)
{
writel(0, eng->eng_regs + 4);
}
+
static inline
u32 GetEngineCompletePtr(struct kpc_dma_device *eng)
{
mutex_unlock(&eng->sem);
}
-
/// Shared Functions
void start_dma_engine(struct kpc_dma_device *eng);
int setup_dma_engine(struct kpc_dma_device *eng, u32 desc_cnt);