@@ -256,7 +256,7 @@ static void picolcd_fb_update(struct picolcd_data *data)
256256 data -> fb_bitmap , data -> fb_bpp , chip , tile ) ||
257257 data -> fb_force ) {
258258 n += 2 ;
259- if (! data -> fb_info -> par )
259+ if (data -> status & PICOLCD_FAILED )
260260 return ; /* device lost! */
261261 if (n >= HID_OUTPUT_FIFO_SIZE / 2 ) {
262262 usbhid_wait_io (data -> hdev );
@@ -327,24 +327,17 @@ static int picolcd_fb_blank(int blank, struct fb_info *info)
327327
328328static void picolcd_fb_destroy (struct fb_info * info )
329329{
330- struct picolcd_data * data = info -> par ;
331- u32 * ref_cnt = info -> pseudo_palette ;
332- int may_release ;
330+ struct picolcd_data * data ;
333331
332+ /* make sure no work is deferred */
333+ cancel_delayed_work_sync (& info -> deferred_work );
334+ data = info -> par ;
334335 info -> par = NULL ;
335336 if (data )
336337 data -> fb_info = NULL ;
337- fb_deferred_io_cleanup (info );
338338
339- ref_cnt -- ;
340- mutex_lock (& info -> lock );
341- (* ref_cnt )-- ;
342- may_release = !* ref_cnt ;
343- mutex_unlock (& info -> lock );
344- if (may_release ) {
345- vfree ((u8 * )info -> fix .smem_start );
346- framebuffer_release (info );
347- }
339+ vfree ((u8 * )info -> fix .smem_start );
340+ framebuffer_release (info );
348341}
349342
350343static int picolcd_fb_check_var (struct fb_var_screeninfo * var , struct fb_info * info )
@@ -414,77 +407,10 @@ static int picolcd_set_par(struct fb_info *info)
414407 return 0 ;
415408}
416409
417- /* Do refcounting on our FB and cleanup per worker if FB is
418- * closed after unplug of our device
419- * (fb_release holds info->lock and still touches info after
420- * we return so we can't release it immediately.
421- */
422- struct picolcd_fb_cleanup_item {
423- struct fb_info * info ;
424- struct picolcd_fb_cleanup_item * next ;
425- };
426- static struct picolcd_fb_cleanup_item * fb_pending ;
427- static DEFINE_SPINLOCK (fb_pending_lock );
428-
429- static void picolcd_fb_do_cleanup (struct work_struct * data )
430- {
431- struct picolcd_fb_cleanup_item * item ;
432- unsigned long flags ;
433-
434- do {
435- spin_lock_irqsave (& fb_pending_lock , flags );
436- item = fb_pending ;
437- fb_pending = item ? item -> next : NULL ;
438- spin_unlock_irqrestore (& fb_pending_lock , flags );
439-
440- if (item ) {
441- u8 * fb = (u8 * )item -> info -> fix .smem_start ;
442- /* make sure we do not race against fb core when
443- * releasing */
444- mutex_lock (& item -> info -> lock );
445- mutex_unlock (& item -> info -> lock );
446- framebuffer_release (item -> info );
447- vfree (fb );
448- }
449- } while (item );
450- }
451-
452- static DECLARE_WORK (picolcd_fb_cleanup , picolcd_fb_do_cleanup ) ;
453-
454- static int picolcd_fb_open (struct fb_info * info , int u )
455- {
456- u32 * ref_cnt = info -> pseudo_palette ;
457- ref_cnt -- ;
458-
459- (* ref_cnt )++ ;
460- return 0 ;
461- }
462-
463- static int picolcd_fb_release (struct fb_info * info , int u )
464- {
465- u32 * ref_cnt = info -> pseudo_palette ;
466- ref_cnt -- ;
467-
468- (* ref_cnt )++ ;
469- if (!* ref_cnt ) {
470- unsigned long flags ;
471- struct picolcd_fb_cleanup_item * item = (struct picolcd_fb_cleanup_item * )ref_cnt ;
472- item -- ;
473- spin_lock_irqsave (& fb_pending_lock , flags );
474- item -> next = fb_pending ;
475- fb_pending = item ;
476- spin_unlock_irqrestore (& fb_pending_lock , flags );
477- schedule_work (& picolcd_fb_cleanup );
478- }
479- return 0 ;
480- }
481-
482410/* Note this can't be const because of struct fb_info definition */
483411static struct fb_ops picolcdfb_ops = {
484412 .owner = THIS_MODULE ,
485413 .fb_destroy = picolcd_fb_destroy ,
486- .fb_open = picolcd_fb_open ,
487- .fb_release = picolcd_fb_release ,
488414 .fb_read = fb_sys_read ,
489415 .fb_write = picolcd_fb_write ,
490416 .fb_blank = picolcd_fb_blank ,
@@ -550,7 +476,7 @@ static ssize_t picolcd_fb_update_rate_store(struct device *dev,
550476 u = PICOLCDFB_UPDATE_RATE_DEFAULT ;
551477
552478 data -> fb_update_rate = u ;
553- data -> fb_defio . delay = HZ / data -> fb_update_rate ;
479+ data -> fb_info -> fbdefio -> delay = HZ / data -> fb_update_rate ;
554480 return count ;
555481}
556482
@@ -580,25 +506,23 @@ int picolcd_init_framebuffer(struct picolcd_data *data)
580506 }
581507
582508 data -> fb_update_rate = PICOLCDFB_UPDATE_RATE_DEFAULT ;
583- data -> fb_defio = picolcd_fb_defio ;
584509 /* The extra memory is:
585- * - struct picolcd_fb_cleanup_item
586- * - u32 for ref_count
587510 * - 256*u32 for pseudo_palette
511+ * - struct fb_deferred_io
588512 */
589- info = framebuffer_alloc (257 * sizeof (u32 ) + sizeof (struct picolcd_fb_cleanup_item ), dev );
513+ info = framebuffer_alloc (256 * sizeof (u32 ) +
514+ sizeof (struct fb_deferred_io ), dev );
590515 if (info == NULL ) {
591516 dev_err (dev , "failed to allocate a framebuffer\n" );
592517 goto err_nomem ;
593518 }
594519
595- palette = info -> par + sizeof ( struct picolcd_fb_cleanup_item ) ;
596- * palette = 1 ;
597- palette ++ ;
520+ info -> fbdefio = info -> par ;
521+ * info -> fbdefio = picolcd_fb_defio ;
522+ palette = info -> par + sizeof ( struct fb_deferred_io ) ;
598523 for (i = 0 ; i < 256 ; i ++ )
599524 palette [i ] = i > 0 && i < 16 ? 0xff : 0 ;
600525 info -> pseudo_palette = palette ;
601- info -> fbdefio = & data -> fb_defio ;
602526 info -> screen_base = (char __force __iomem * )fb_bitmap ;
603527 info -> fbops = & picolcdfb_ops ;
604528 info -> var = picolcdfb_var ;
@@ -658,16 +582,14 @@ void picolcd_exit_framebuffer(struct picolcd_data *data)
658582 return ;
659583
660584 device_remove_file (& data -> hdev -> dev , & dev_attr_fb_update_rate );
585+ mutex_lock (& info -> lock );
586+ fb_deferred_io_cleanup (info );
587+ info -> par = NULL ;
588+ mutex_unlock (& info -> lock );
661589 unregister_framebuffer (info );
662590 data -> fb_vbitmap = NULL ;
663591 data -> fb_bitmap = NULL ;
664592 data -> fb_bpp = 0 ;
665593 data -> fb_info = NULL ;
666594 kfree (fb_vbitmap );
667595}
668-
669- void picolcd_fb_unload ()
670- {
671- flush_work_sync (& picolcd_fb_cleanup );
672- WARN_ON (fb_pending );
673- }
0 commit comments