clear-pkgs-linux-iot-lts2018/0015-Fix-for-cbc-kernel-dri...

126 lines
4.2 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: padmarao edapalapati <padmarao.edapalapati@intel.com>
Date: Thu, 6 Sep 2018 10:38:22 +0530
Subject: [PATCH] Fix for cbc kernel driver crash during warm reboot
Added a Sync mechanism with spinlocks between demuxed_receive
and cbc_device_open, cbc_device_release
Change-Id: Id5c71eb59bb390a0b39b7bc66d5536d9eecf607f
Signed-off-by: padmarao edapalapati <padmarao.edapalapati@intel.com>
---
drivers/tty/cbc/cbc_device.c | 4 +++-
drivers/tty/cbc/cbc_device.h | 3 +++
drivers/tty/cbc/cbc_device_manager.c | 12 ++++++++++++
3 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/drivers/tty/cbc/cbc_device.c b/drivers/tty/cbc/cbc_device.c
index 1933a8527015..23728c04dd6e 100644
--- a/drivers/tty/cbc/cbc_device.c
+++ b/drivers/tty/cbc/cbc_device.c
@@ -18,8 +18,10 @@
void cbc_device_init(struct cbc_device_data *cd)
{
- if (cd)
+ if (cd) {
+ spin_lock_init(&cd->cbc_device_lock);
INIT_LIST_HEAD(&cd->open_files_head);
+ }
}
void cbc_file_init(struct cbc_file_data *file)
diff --git a/drivers/tty/cbc/cbc_device.h b/drivers/tty/cbc/cbc_device.h
index deb0cd922316..09c806716557 100644
--- a/drivers/tty/cbc/cbc_device.h
+++ b/drivers/tty/cbc/cbc_device.h
@@ -22,6 +22,7 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/wait.h>
+#include <linux/spinlock.h>
#include "cbc_types.h"
@@ -49,6 +50,8 @@ struct cbc_device_data {
char *device_name;
enum cbc_device_type device_type;
struct device *device;
+ /* lock to sync demuxed_receive with cbc_device_release and open */
+ spinlock_t cbc_device_lock;
struct list_head open_files_head;
};
diff --git a/drivers/tty/cbc/cbc_device_manager.c b/drivers/tty/cbc/cbc_device_manager.c
index 0e74183d9828..2c8c1cf966ca 100644
--- a/drivers/tty/cbc/cbc_device_manager.c
+++ b/drivers/tty/cbc/cbc_device_manager.c
@@ -234,6 +234,7 @@ static int cbc_device_open(struct inode *inode, struct file *file)
inode->i_rdev)];
int ret = 0;
u32 num_open_files = 0;
+ unsigned long flags;
struct cbc_file_data *file_data = kmalloc(sizeof(struct cbc_file_data),
GFP_KERNEL);
@@ -267,7 +268,9 @@ static int cbc_device_open(struct inode *inode, struct file *file)
if (ret == 0) {
cbc_file_init(file_data);
file_data->cbc_device = device_data;
+ spin_lock_irqsave(&device_data->cbc_device_lock, flags);
list_add(&file_data->list, &device_data->open_files_head);
+ spin_unlock_irqrestore(&device_data->cbc_device_lock, flags);
file->private_data = file_data;
} else {
kfree(file_data);
@@ -285,9 +288,14 @@ static int cbc_device_release(struct inode *inode, struct file *file)
{
u32 dev_idx = MINOR(inode->i_rdev);
struct cbc_file_data *file_data = file->private_data;
+ unsigned long flags;
if (file_data) {
+ spin_lock_irqsave(
+ &file_data->cbc_device->cbc_device_lock, flags);
list_del(&file_data->list);
+ spin_unlock_irqrestore(
+ &file_data->cbc_device->cbc_device_lock, flags);
pr_debug("cbc-core: device_release: %d.%d %s\n",
MAJOR(inode->i_rdev), dev_idx,
@@ -299,6 +307,7 @@ static int cbc_device_release(struct inode *inode, struct file *file)
kfree(file_data);
file->private_data = NULL;
}
+
return 0;
}
@@ -796,6 +805,7 @@ static void demuxed_receive(void *void_data, struct cbc_buffer *cbc_buffer)
(struct cbc_device_data *) void_data;
struct list_head *current_item;
struct cbc_file_data *current_file_data;
+ unsigned long flags;
if (device_data && cbc_buffer
&& cbc_buffer->frame_length >
@@ -836,6 +846,7 @@ static void demuxed_receive(void *void_data, struct cbc_buffer *cbc_buffer)
/* else, do not touch payload_length in a debug-channel */
/* Enqueue */
+ spin_lock_irqsave(&device_data->cbc_device_lock, flags);
for (current_item = device_data->open_files_head.next
; current_item != &device_data->open_files_head; current_item =
current_item->next) {
@@ -845,6 +856,7 @@ static void demuxed_receive(void *void_data, struct cbc_buffer *cbc_buffer)
/* File_enqueue increases ref. count. */
cbc_file_enqueue(current_file_data, cbc_buffer);
}
+ spin_unlock_irqrestore(&device_data->cbc_device_lock, flags);
} else {
pr_err("cbc-core: (<- IOC) dev_receive data is null\n");
}
--
https://clearlinux.org