Skip to content
Snippets Groups Projects
Commit d31df914 authored by Andreas Werner's avatar Andreas Werner
Browse files

add multibly devices support, .gitingore and install support

parent 1dac4c1a
No related branches found
No related tags found
No related merge requests found
.gitignore.swp
.remoteproc-shm.ko.cmd
.remoteproc-shm.mod.o.cmd
.remoteproc-shm.o.cmd
.tmp_versions/
Module.symvers
modules.order
remoteproc-shm.ko
remoteproc-shm.mod.c
remoteproc-shm.mod.o
remoteproc-shm.o
**.swp
**.cmd
.tmp_versions
Module.symvers
modules.order
**.ko
**.mod.c
**.o
Makefile 100755 → 100644
......@@ -12,8 +12,14 @@ dtbs: $(dtb-y)
dtc -I dts -O dtb -o $@ $^
clean:
make -C $(KERNEL_SRC) M=$(PWD) clean
rm *.dtb
-make -C $(KERNEL_SRC) M=$(PWD) clean
-rm *.dtb
install:
make -C $(KERNEL_SRC) M=$(PWD) modules_install
modules_install:
make -C $(KERNEL_SRC) M=$(PWD) modules_install
$(KERNEL_SRC)/scripts/basic/fixdep:
cd $(KERNEL_SRC)
make -C $(KERNEL_SRC) scripts/basic/
......
/*
* Copyright (C) 2018 Hochschule RheinMain
* Copyright (C) 2018 - 2019 Hochschule RheinMain
*
* Authors: Wilhelm Alexander, Wissfeld Aljoscha
* Authors: Wilhelm Alexander, Wissfeld Aljoscha, Andreas Werner <kernel@andy89.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
......@@ -28,7 +28,6 @@
#include <linux/types.h>
#define DRIVER_NAME "remoteproc-shm"
#define SHM_SIZE 0x800000
struct rproc_shm_device {
struct device *dev; /* device */
......@@ -39,20 +38,22 @@ struct rproc_shm_device {
struct fasync_struct *async_queue; /* used for async notifies */
wait_queue_head_t wait_queue; /* for waking for events */
dma_addr_t dma_handle; /* direct memory address */
uint32_t size; /* size of SHM */
void *shm_addr; /* virtual shared memory */
int major; /* major number */
struct list_head head; /* list head */
};
struct rproc_file {
struct list_head head; /* list head */
struct rproc_shm_device dev; /* rproc_shm_device */
struct rproc_shm_device *dev; /* rproc_shm_device */
bool interrupted; /* indicates interrupts */
};
struct class *rproc_class = NULL;
struct rproc_shm_device *dev;
//struct list_head dev_list; /* multiple devices approach*/
static struct dentry *root_debugfs_dir;
static struct class *rproc_class = NULL;
static struct list_head devs = LIST_HEAD_INIT(devs);
static int major = -1;
static int minor = 0;
/**
* rproc_shm_recv_message - receives messages from IPU, wakes up all threads
......@@ -133,18 +134,22 @@ static ssize_t rproc_shm_write(struct file *filp,
const char __user *userbuf,
size_t count, loff_t *ppos)
{
//struct rproc_shm_device *dev = filp->private_data;
struct rproc_file *file = (struct rproc_file *) filp->private_data;
struct rproc_shm_device *dev = file->dev;
int ret;
void *addr;
printk(KERN_INFO "%p: rproc_shm_write", filp);
if (count > (SHM_SIZE - (*ppos))) {
if (count > (dev->size - (*ppos))) {
dev_err(dev->dev,
"Message length %zd greater than max allowed %d or not"
" enough space left", count, SHM_SIZE);
" enough space left", count, dev->size);
return -EINVAL;
}
addr = dev->shm_addr + (*ppos);
dev_info(dev->dev, "%p: rproc_shm_write: addr: 0x%lx", filp, (uintptr_t) addr);
ret = copy_from_user(dev->shm_addr + (*ppos), userbuf, count);
ret = copy_from_user(addr, userbuf, count);
if (ret < 0)
dev_err(dev->dev, "Failed to copy into userspace\n");
......@@ -163,14 +168,17 @@ static ssize_t rproc_shm_write(struct file *filp,
static ssize_t rproc_shm_read(struct file *filp, char __user *userbuf,
size_t count, loff_t *ppos)
{
struct rproc_file *file = (struct rproc_file *) filp->private_data;
struct rproc_shm_device *dev = file->dev;
int ret;
void *addr;
printk(KERN_INFO "%p: rproc_shm_read", filp);
if (count > (dev->size - (*ppos)))
count = dev->size - (*ppos);
addr = dev->shm_addr + (*ppos);
dev_info(dev->dev, "%p: rproc_shm_read: ppos: %llu addr: 0x%lx", filp, (*ppos),(uintptr_t) addr);
if (count > (SHM_SIZE - (*ppos)))
count = SHM_SIZE - (*ppos);
ret = copy_to_user(userbuf, dev->shm_addr + (*ppos), count);
ret = copy_to_user(userbuf, addr, count);
if (ret < 0)
dev_err(dev->dev, "Failed to copy into userspace\n");
......@@ -186,6 +194,8 @@ static ssize_t rproc_shm_read(struct file *filp, char __user *userbuf,
*/
static int rproc_shm_mmap(struct file *filp, struct vm_area_struct *vma)
{
struct rproc_file *file = (struct rproc_file *) filp->private_data;
struct rproc_shm_device *dev = file->dev;
unsigned long len = vma->vm_end - vma->vm_start;
int ret;
......@@ -219,6 +229,8 @@ static int rproc_shm_mmap(struct file *filp, struct vm_area_struct *vma)
*/
static int rproc_shm_fasync(int fd, struct file *filp, int mode)
{
struct rproc_file *file = (struct rproc_file *) filp->private_data;
struct rproc_shm_device *dev = file->dev;
dev_info(dev->dev, "rproc_shm_fasync");
return fasync_helper(fd, filp, mode, &dev->async_queue);
......@@ -234,6 +246,8 @@ static int rproc_shm_fasync(int fd, struct file *filp, int mode)
*/
static int rproc_shm_fsync(struct file *filp, loff_t start, loff_t end, int datasync)
{
struct rproc_file *file = (struct rproc_file *) filp->private_data;
struct rproc_shm_device *dev = file->dev;
dev_info(dev->dev, "rproc_shm_fsync");
if (mbox_send_message(dev->mbox_channel, (void *)1) < 0)
......@@ -249,9 +263,11 @@ static int rproc_shm_fsync(struct file *filp, loff_t start, loff_t end, int data
*/
static unsigned int rproc_shm_poll(struct file *filp, struct poll_table_struct *poll_table)
{
struct rproc_file *file = (struct rproc_file *) filp->private_data;
struct rproc_shm_device *dev = file->dev;
unsigned int mask = 0;
printk(KERN_INFO "%p: rproc_shm_poll", filp);
dev_info(dev->dev, "%p: rproc_shm_poll", filp);
down(&dev->sem);
poll_wait(filp, &dev->wait_queue, poll_table);
......@@ -273,15 +289,30 @@ static unsigned int rproc_shm_poll(struct file *filp, struct poll_table_struct *
*/
static int rproc_shm_open(struct inode *i, struct file *filp)
{
struct rproc_shm_device *dev;
struct rproc_file *file;
printk(KERN_INFO "%p: rproc_shm_open", filp);
struct list_head *pos;
bool found = false;
printk(KERN_INFO "%p: rproc_shm_open: Major: %d Minor: %d", filp, MAJOR(i->i_rdev), MINOR(i->i_rdev));
list_for_each(pos, &devs) {
dev = list_entry(pos, struct rproc_shm_device, head);
if (MINOR(i->i_rdev) == MINOR(dev->cdev->devt)) {
dev_info(dev->dev, "%p: rproc_shm_open minor: %d", filp, MINOR(i->i_rdev));
found = true;
break;
}
}
if (!found) {
printk(KERN_ERR "%p: rproc_shm_open: device not found!", filp);
return -ENXIO;
}
/* Add file to list */
file = kmalloc(sizeof(struct rproc_file), GFP_KERNEL);
file->interrupted = false;
/* TODO */
//file->dev = dev;
file->dev = dev;
filp->private_data = file;
......@@ -296,7 +327,9 @@ static int rproc_shm_open(struct inode *i, struct file *filp)
*/
static int rproc_shm_close(struct inode *i, struct file *filp)
{
printk(KERN_INFO "%p: rproc_shm_close", filp);
struct rproc_file *file = (struct rproc_file *) filp->private_data;
struct rproc_shm_device *dev = file->dev;
dev_info(dev->dev, "%p: rproc_shm_close", filp);
/* Remove file from list */
list_del(&((struct rproc_file *)filp->private_data)->head);
......@@ -325,52 +358,70 @@ static const struct file_operations remoteproc_shm_ops = {
*/
static int shm_add(struct platform_device *pdev, struct rproc_shm_device *dev)
{
int major, minor;
minor = 0;
major = register_chrdev(0, DRIVER_NAME, &remoteproc_shm_ops);
if (major < 0)
dev_err(&pdev->dev, "Err - Major: %d\n", major);
if (major < 0) {
major = register_chrdev(0, DRIVER_NAME, &remoteproc_shm_ops);
if (major < 0) {
dev_err(&pdev->dev, "Err - Major: %d\n", major);
return -ENOMEM;
}
}
dev->major = major;
dev_info(&pdev->dev, "Device major-number: %d\n", major);
dev->cdev = device_create(rproc_class, &pdev->dev, MKDEV(major, minor),
dev, "rproc-shm%d", minor);
if (IS_ERR(dev->cdev))
if (IS_ERR(dev->cdev)) {
dev_err(&pdev->dev, "Failed to create device");
return -ENOMEM;
}
dev_info(&pdev->dev, "Major: %d Minor: %d\n", MAJOR(dev->cdev->devt), MINOR(dev->cdev->devt));
minor++;
list_add(&dev->head, &devs);
return 0;
}
static int rproc_shm_probe(struct platform_device *pdev)
{
struct rproc_shm_device *dev;
int ret;
//struct rpoc_shm_device dev;
void *virt_addr;
dma_addr_t dma;
u32 size;
dev_info(&pdev->dev, "rproc_shm_probe\n");
/* init memory region */
of_reserved_mem_device_init(&pdev->dev);
ret = of_property_read_u32(pdev->dev.of_node, "size", &size);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to get size");
return -ENOMEM;
}
/* Allocate Memory */
virt_addr = dma_alloc_coherent(&pdev->dev, SHM_SIZE, &dma, GFP_KERNEL);
virt_addr = dma_alloc_coherent(&pdev->dev, size, &dma, GFP_KERNEL);
if (!virt_addr) {
dev_err(&pdev->dev, "Failed to allocate reserved region\n");
return -ENOMEM;
}
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
if (!dev) {
dma_free_coherent(&pdev->dev, size, virt_addr, dma);
return -ENOMEM;
}
/* Fill device struct */
dev->dev = &pdev->dev;
dev->mbox_channel = rproc_shm_request_channel(pdev);
dev_info(&pdev->dev, "virt addr: 0x%p dma addr: 0x%llx size: %u\n", virt_addr, dma, size);
dev->shm_addr = virt_addr;
dev->dma_handle = dma;
dev->size = size;
init_waitqueue_head(&dev->wait_queue);
sema_init(&dev->sem, 1);
......@@ -402,24 +453,26 @@ static int rproc_shm_remove(struct platform_device *pdev)
virt_addr = dev->shm_addr;
dma = dev->dma_handle;
/* reset fasync */
//rproc_shm_fasync(-1, filp, 0);
/* Unregister Device and free the Memory */
device_unregister(dev->cdev);
class_destroy(rproc_class);
unregister_chrdev(dev->major, DRIVER_NAME);
dma_free_coherent(&pdev->dev, SHM_SIZE, virt_addr, dma);
dma_free_coherent(&pdev->dev, dev->size, virt_addr, dma);
/* release memory region */
of_reserved_mem_device_release(&pdev->dev);
debugfs_remove_recursive(root_debugfs_dir);
if (dev->mbox_channel)
mbox_free_channel(dev->mbox_channel);
list_del(&dev->head);
if (list_empty(&devs)) {
/* was the last dev destroy class and chrdev */
unregister_chrdev(dev->major, DRIVER_NAME);
class_destroy(rproc_class);
}
devm_kfree(&pdev->dev, dev);
return 0;
......@@ -442,5 +495,5 @@ static struct platform_driver rproc_shm_driver = {
module_platform_driver(rproc_shm_driver);
MODULE_DESCRIPTION("RPROC Shared Memory Driver");
MODULE_AUTHOR("Wilhem Alexander, Wissfeld Aljoscha");
MODULE_AUTHOR("Wilhem Alexander, Wissfeld Aljoscha", "Andreas Werner <kernel@andy89.org>");
MODULE_LICENSE("GPL v2");
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment