This repository has been archived by the owner on Jul 6, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
0015-Fix-for-cbc-kernel-driver-crash-during-warm-reboot.patch
125 lines (110 loc) · 4.24 KB
/
0015-Fix-for-cbc-kernel-driver-crash-during-warm-reboot.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: padmarao edapalapati <[email protected]>
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 <[email protected]>
---
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