@@ -96,6 +96,7 @@ struct hdmi_cec_event {
96
96
};
97
97
98
98
99
+ static LIST_HEAD (ev_idle );
99
100
static LIST_HEAD (ev_pending );
100
101
101
102
static int hdmi_cec_irq ;
@@ -109,6 +110,60 @@ static u8 is_initialized;
109
110
static wait_queue_head_t rx_queue ;
110
111
static wait_queue_head_t tx_queue ;
111
112
113
+ static struct hdmi_cec_event * alloc_event (void )
114
+ {
115
+ int i ;
116
+ struct hdmi_cec_event * event ;
117
+
118
+ if (list_empty (& ev_idle )) {
119
+ event = (void * )__get_free_page (GFP_KERNEL );
120
+
121
+ if (!event ) {
122
+ pr_err ("HDMI-CEC: Failed to allocate event buffer\n" );
123
+ return NULL ;
124
+ }
125
+
126
+ for (i = 1 ; i < PAGE_SIZE / sizeof (struct hdmi_cec_event ); i ++ )
127
+ list_add_tail (& event [i ].list , & ev_idle );
128
+
129
+ pr_debug ("HDMI-CEC: Allocated event buffer page: @%08lx (%d)\n" ,
130
+ (unsigned long )event , i );
131
+ } else {
132
+ event = list_first_entry (& ev_idle , struct hdmi_cec_event , list );
133
+ list_del (& event -> list );
134
+ }
135
+
136
+ memset (event , 0 , sizeof (struct hdmi_cec_event ));
137
+ return event ;
138
+ }
139
+
140
+ static void free_events (void )
141
+ {
142
+ struct hdmi_cec_event * event , * tmp_event ;
143
+
144
+ /* Flush events which have not been read by user space */
145
+ list_splice_init (& ev_pending , & ev_idle );
146
+
147
+ /* Find item(s) starting on a page boundary */
148
+ list_for_each_entry_safe (event , tmp_event , & ev_idle , list ) {
149
+ if (((unsigned long )event & ~PAGE_MASK ) == 0 )
150
+ list_move_tail (& event -> list , & ev_pending );
151
+ }
152
+
153
+ /* Discard idle list */
154
+ INIT_LIST_HEAD (& ev_idle );
155
+
156
+ /* Empty pending list and free page(s) */
157
+ while (!list_empty (& ev_pending )) {
158
+ event = list_first_entry (& ev_pending , struct hdmi_cec_event , list );
159
+ list_del (& event -> list );
160
+ free_page ((unsigned long )event );
161
+
162
+ pr_debug ("HDMI-CEC: Freed event buffer page: @%08lx\n" ,
163
+ (unsigned long )event );
164
+ }
165
+ }
166
+
112
167
static u32 get_hpd_stat (struct hdmi_cec_priv * hdmi_cec )
113
168
{
114
169
u32 cec_stat0 = 0 ;
@@ -156,12 +211,29 @@ static irqreturn_t mxc_hdmi_cec_isr(int irq, void *data)
156
211
157
212
static void mxc_hdmi_cec_handle (u32 cec_stat )
158
213
{
159
- u8 i = 0 ;
160
- struct hdmi_cec_event * event = NULL ;
214
+ int i ;
215
+ struct hdmi_cec_event * event ;
161
216
162
217
if (!hdmi_cec_data .open_count )
163
218
return ;
164
219
220
+ /*HDMI cable connected: handle first*/
221
+ if (cec_stat & CEC_STAT0_EX_CONNECTED ) {
222
+ pr_info ("HDMI-CEC: link connected\n" );
223
+
224
+ mutex_lock (& hdmi_cec_data .lock );
225
+ event = alloc_event ();
226
+ if (!event ) {
227
+ mutex_unlock (& hdmi_cec_data .lock );
228
+ return ;
229
+ }
230
+ event -> event_type = MESSAGE_TYPE_CONNECTED ;
231
+ list_add_tail (& event -> list , & ev_pending );
232
+ mutex_unlock (& hdmi_cec_data .lock );
233
+
234
+ wake_up (& rx_queue );
235
+ }
236
+
165
237
/* The current transmission is successful (for initiator only). */
166
238
if (cec_stat & HDMI_IH_CEC_STAT0_DONE ) {
167
239
hdmi_cec_data .tx_answer = cec_stat ;
@@ -170,25 +242,28 @@ static void mxc_hdmi_cec_handle(u32 cec_stat)
170
242
171
243
/*EOM is detected so that the received data is ready in the receiver data buffer*/
172
244
if (cec_stat & HDMI_IH_CEC_STAT0_EOM ) {
173
- event = vmalloc (sizeof (struct hdmi_cec_event ));
174
- if (NULL == event ) {
175
- pr_err ("%s: Not enough memory!\n" , __func__ );
245
+ mutex_lock (& hdmi_cec_data .lock );
246
+ event = alloc_event ();
247
+ if (!event ) {
248
+ mutex_unlock (& hdmi_cec_data .lock );
176
249
return ;
177
250
}
178
- memset ( event , 0 , sizeof ( struct hdmi_cec_event ));
251
+
179
252
event -> msg_len = hdmi_readb (HDMI_CEC_RX_CNT );
180
- if (!event -> msg_len ) {
181
- pr_err ("%s: Invalid CEC message length!\n" , __func__ );
182
- vfree (event );
253
+ if (!event -> msg_len || event -> msg_len > MAX_MESSAGE_LEN ) {
254
+ pr_err ("HDMI-CEC: Invalid CEC message length\n" );
255
+ list_add_tail (& event -> list , & ev_idle );
256
+ mutex_unlock (& hdmi_cec_data .lock );
183
257
return ;
184
258
}
259
+
185
260
event -> event_type = MESSAGE_TYPE_RECEIVE_SUCCESS ;
186
261
for (i = 0 ; i < event -> msg_len ; i ++ )
187
- event -> msg [i ] = hdmi_readb (HDMI_CEC_RX_DATA0 + i );
188
- hdmi_writeb (0x0 , HDMI_CEC_LOCK );
189
- mutex_lock (& hdmi_cec_data .lock );
262
+ event -> msg [i ] = hdmi_readb (HDMI_CEC_RX_DATA0 + i );
263
+
190
264
list_add_tail (& event -> list , & ev_pending );
191
265
mutex_unlock (& hdmi_cec_data .lock );
266
+
192
267
wake_up (& rx_queue );
193
268
}
194
269
@@ -215,35 +290,20 @@ static void mxc_hdmi_cec_handle(u32 cec_stat)
215
290
hdmi_cec_data .receive_error ++ ;
216
291
}
217
292
218
- /* HDMI cable connected */
219
- if (cec_stat & CEC_STAT0_EX_CONNECTED ) {
220
- pr_info ("HDMI-CEC: link connected\n" );
221
- pr_info ("HDMI link connected\n" );
222
- event = vmalloc (sizeof (struct hdmi_cec_event ));
223
- if (NULL == event ) {
224
- pr_err ("%s: Not enough memory\n" , __func__ );
225
- return ;
226
- }
227
- memset (event , 0 , sizeof (struct hdmi_cec_event ));
228
- event -> event_type = MESSAGE_TYPE_CONNECTED ;
229
- mutex_lock (& hdmi_cec_data .lock );
230
- list_add_tail (& event -> list , & ev_pending );
231
- mutex_unlock (& hdmi_cec_data .lock );
232
- wake_up (& rx_queue );
233
- }
234
- /*HDMI cable disconnected*/
293
+ /*HDMI cable disconnected: handle last*/
235
294
if (cec_stat & CEC_STAT0_EX_DISCONNECTED ) {
236
295
pr_info ("HDMI-CEC: link disconnected\n" );
237
- event = vmalloc (sizeof (struct hdmi_cec_event ));
238
- if (NULL == event ) {
239
- pr_err ("%s: Not enough memory!\n" , __func__ );
296
+
297
+ mutex_lock (& hdmi_cec_data .lock );
298
+ event = alloc_event ();
299
+ if (!event ) {
300
+ mutex_unlock (& hdmi_cec_data .lock );
240
301
return ;
241
302
}
242
- memset (event , 0 , sizeof (struct hdmi_cec_event ));
243
303
event -> event_type = MESSAGE_TYPE_DISCONNECTED ;
244
- mutex_lock (& hdmi_cec_data .lock );
245
304
list_add_tail (& event -> list , & ev_pending );
246
305
mutex_unlock (& hdmi_cec_data .lock );
306
+
247
307
wake_up (& rx_queue );
248
308
}
249
309
}
@@ -254,6 +314,9 @@ static void mxc_hdmi_cec_worker(struct work_struct *work)
254
314
255
315
mxc_hdmi_cec_handle (hdmi_cec_data .cec_stat0 );
256
316
317
+ if (hdmi_cec_data .cec_stat0 & HDMI_IH_CEC_STAT0_EOM )
318
+ hdmi_writeb (0x0 , HDMI_CEC_LOCK );
319
+
257
320
spin_lock_irqsave (& hdmi_cec_data .irq_lock , flags );
258
321
hdmi_cec_data .cec_stat0 = 0 ;
259
322
if (hdmi_cec_data .is_started )
@@ -279,7 +342,8 @@ static int hdmi_cec_open(struct inode *inode, struct file *file)
279
342
static ssize_t hdmi_cec_read (struct file * file , char __user * buf , size_t count ,
280
343
loff_t * ppos )
281
344
{
282
- struct hdmi_cec_event * event = NULL ;
345
+ ssize_t len ;
346
+ struct hdmi_cec_event * event ;
283
347
284
348
pr_debug ("function : %s\n" , __func__ );
285
349
@@ -293,26 +357,24 @@ static ssize_t hdmi_cec_read(struct file *file, char __user *buf, size_t count,
293
357
if (file -> f_flags & O_NONBLOCK ) {
294
358
mutex_unlock (& hdmi_cec_data .lock );
295
359
return - EAGAIN ;
296
- } else {
297
- do {
298
- mutex_unlock (& hdmi_cec_data .lock );
299
- if (wait_event_interruptible (rx_queue , !list_empty (& ev_pending )))
300
- return - ERESTARTSYS ;
301
- mutex_lock (& hdmi_cec_data .lock );
302
- } while (list_empty (& ev_pending ));
303
360
}
361
+
362
+ do {
363
+ mutex_unlock (& hdmi_cec_data .lock );
364
+ if (wait_event_interruptible (rx_queue , !list_empty (& ev_pending )))
365
+ return - ERESTARTSYS ;
366
+ mutex_lock (& hdmi_cec_data .lock );
367
+ } while (list_empty (& ev_pending ));
304
368
}
305
369
370
+ len = offsetof(struct hdmi_cec_event , list );
306
371
event = list_first_entry (& ev_pending , struct hdmi_cec_event , list );
307
- list_del (& event -> list );
372
+ if (copy_to_user (buf , event , len ))
373
+ len = - EFAULT ;
374
+ list_move_tail (& event -> list , & ev_idle );
308
375
mutex_unlock (& hdmi_cec_data .lock );
309
- if (copy_to_user (buf , event ,
310
- sizeof (struct hdmi_cec_event ) - sizeof (struct list_head ))) {
311
- vfree (event );
312
- return - EFAULT ;
313
- }
314
- vfree (event );
315
- return (sizeof (struct hdmi_cec_event ) - sizeof (struct list_head ));
376
+
377
+ return len ;
316
378
}
317
379
318
380
static ssize_t hdmi_cec_write (struct file * file , const char __user * buf ,
@@ -503,8 +565,6 @@ static long hdmi_cec_ioctl(struct file *file, u_int cmd,
503
565
504
566
static int hdmi_cec_release (struct inode * inode , struct file * file )
505
567
{
506
- struct hdmi_cec_event * event , * tmp_event ;
507
-
508
568
pr_debug ("function : %s\n" , __func__ );
509
569
510
570
mutex_lock (& hdmi_cec_data .lock );
@@ -513,11 +573,7 @@ static int hdmi_cec_release(struct inode *inode, struct file *file)
513
573
hdmi_cec_data .is_started = false;
514
574
hdmi_cec_data .logical_address = 15 ;
515
575
516
- /* Flush eventual events which have not been read by user space */
517
- list_for_each_entry_safe (event , tmp_event , & ev_pending , list ) {
518
- list_del (& event -> list );
519
- vfree (event );
520
- }
576
+ free_events ();
521
577
}
522
578
mutex_unlock (& hdmi_cec_data .lock );
523
579
@@ -592,6 +648,7 @@ static int hdmi_cec_dev_probe(struct platform_device *pdev)
592
648
goto err_out_class ;
593
649
}
594
650
651
+ INIT_LIST_HEAD (& ev_idle );
595
652
INIT_LIST_HEAD (& ev_pending );
596
653
597
654
init_waitqueue_head (& rx_queue );
0 commit comments