@@ -31,6 +31,12 @@ struct ec_cmd_desc {
31
31
32
32
struct olpc_ec_priv {
33
33
struct olpc_ec_driver * drv ;
34
+ struct work_struct worker ;
35
+ struct mutex cmd_lock ;
36
+
37
+ /* Pending EC commands */
38
+ struct list_head cmd_q ;
39
+ spinlock_t cmd_q_lock ;
34
40
35
41
struct dentry * dbgfs_dir ;
36
42
@@ -46,16 +52,9 @@ struct olpc_ec_priv {
46
52
bool suspended ;
47
53
};
48
54
49
- static void olpc_ec_worker (struct work_struct * w );
50
-
51
- static DECLARE_WORK (ec_worker , olpc_ec_worker ) ;
52
- static LIST_HEAD (ec_cmd_q );
53
- static DEFINE_SPINLOCK (ec_cmd_q_lock );
54
-
55
55
static struct olpc_ec_driver * ec_driver ;
56
56
static struct olpc_ec_priv * ec_priv ;
57
57
static void * ec_cb_arg ;
58
- static DEFINE_MUTEX (ec_cb_lock );
59
58
60
59
void olpc_ec_driver_register (struct olpc_ec_driver * drv , void * arg )
61
60
{
@@ -66,49 +65,51 @@ EXPORT_SYMBOL_GPL(olpc_ec_driver_register);
66
65
67
66
static void olpc_ec_worker (struct work_struct * w )
68
67
{
68
+ struct olpc_ec_priv * ec = container_of (w , struct olpc_ec_priv , worker );
69
69
struct ec_cmd_desc * desc = NULL ;
70
70
unsigned long flags ;
71
71
72
72
/* Grab the first pending command from the queue */
73
- spin_lock_irqsave (& ec_cmd_q_lock , flags );
74
- if (!list_empty (& ec_cmd_q )) {
75
- desc = list_first_entry (& ec_cmd_q , struct ec_cmd_desc , node );
73
+ spin_lock_irqsave (& ec -> cmd_q_lock , flags );
74
+ if (!list_empty (& ec -> cmd_q )) {
75
+ desc = list_first_entry (& ec -> cmd_q , struct ec_cmd_desc , node );
76
76
list_del (& desc -> node );
77
77
}
78
- spin_unlock_irqrestore (& ec_cmd_q_lock , flags );
78
+ spin_unlock_irqrestore (& ec -> cmd_q_lock , flags );
79
79
80
80
/* Do we actually have anything to do? */
81
81
if (!desc )
82
82
return ;
83
83
84
84
/* Protect the EC hw with a mutex; only run one cmd at a time */
85
- mutex_lock (& ec_cb_lock );
85
+ mutex_lock (& ec -> cmd_lock );
86
86
desc -> err = ec_driver -> ec_cmd (desc -> cmd , desc -> inbuf , desc -> inlen ,
87
87
desc -> outbuf , desc -> outlen , ec_cb_arg );
88
- mutex_unlock (& ec_cb_lock );
88
+ mutex_unlock (& ec -> cmd_lock );
89
89
90
90
/* Finished, wake up olpc_ec_cmd() */
91
91
complete (& desc -> finished );
92
92
93
93
/* Run the worker thread again in case there are more cmds pending */
94
- schedule_work (& ec_worker );
94
+ schedule_work (& ec -> worker );
95
95
}
96
96
97
97
/*
98
98
* Throw a cmd descripter onto the list. We now have SMP OLPC machines, so
99
99
* locking is pretty critical.
100
100
*/
101
- static void queue_ec_descriptor (struct ec_cmd_desc * desc )
101
+ static void queue_ec_descriptor (struct ec_cmd_desc * desc ,
102
+ struct olpc_ec_priv * ec )
102
103
{
103
104
unsigned long flags ;
104
105
105
106
INIT_LIST_HEAD (& desc -> node );
106
107
107
- spin_lock_irqsave (& ec_cmd_q_lock , flags );
108
- list_add_tail (& desc -> node , & ec_cmd_q );
109
- spin_unlock_irqrestore (& ec_cmd_q_lock , flags );
108
+ spin_lock_irqsave (& ec -> cmd_q_lock , flags );
109
+ list_add_tail (& desc -> node , & ec -> cmd_q );
110
+ spin_unlock_irqrestore (& ec -> cmd_q_lock , flags );
110
111
111
- schedule_work (& ec_worker );
112
+ schedule_work (& ec -> worker );
112
113
}
113
114
114
115
int olpc_ec_cmd (u8 cmd , u8 * inbuf , size_t inlen , u8 * outbuf , size_t outlen )
@@ -137,7 +138,7 @@ int olpc_ec_cmd(u8 cmd, u8 *inbuf, size_t inlen, u8 *outbuf, size_t outlen)
137
138
desc .err = 0 ;
138
139
init_completion (& desc .finished );
139
140
140
- queue_ec_descriptor (& desc );
141
+ queue_ec_descriptor (& desc , ec );
141
142
142
143
/* Timeouts must be handled in the platform-specific EC hook */
143
144
wait_for_completion (& desc .finished );
@@ -266,7 +267,14 @@ static int olpc_ec_probe(struct platform_device *pdev)
266
267
ec = kzalloc (sizeof (* ec ), GFP_KERNEL );
267
268
if (!ec )
268
269
return - ENOMEM ;
270
+
269
271
ec -> drv = ec_driver ;
272
+ INIT_WORK (& ec -> worker , olpc_ec_worker );
273
+ mutex_init (& ec -> cmd_lock );
274
+
275
+ INIT_LIST_HEAD (& ec -> cmd_q );
276
+ spin_lock_init (& ec -> cmd_q_lock );
277
+
270
278
ec_priv = ec ;
271
279
platform_set_drvdata (pdev , ec );
272
280
0 commit comments