Skip to content

Commit 9966c37

Browse files
Bruno PrémontJiri Kosina
authored andcommitted
HID: picoLCD: Replace own refcounting with fbdev's
Signed-off-by: Bruno Prémont <[email protected]> Signed-off-by: Jiri Kosina <[email protected]>
1 parent fabdbf2 commit 9966c37

File tree

3 files changed

+18
-103
lines changed

3 files changed

+18
-103
lines changed

drivers/hid/hid-picolcd.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@ struct picolcd_data {
9696
u8 *fb_vbitmap; /* local copy of what was sent to PicoLCD */
9797
u8 *fb_bitmap; /* framebuffer */
9898
struct fb_info *fb_info;
99-
struct fb_deferred_io fb_defio;
10099
#endif /* CONFIG_HID_PICOLCD_FB */
101100
#ifdef CONFIG_HID_PICOLCD_LCD
102101
struct lcd_device *lcd;
@@ -179,8 +178,6 @@ int picolcd_init_framebuffer(struct picolcd_data *data);
179178

180179
void picolcd_exit_framebuffer(struct picolcd_data *data);
181180

182-
void picolcd_fb_unload(void);
183-
184181
void picolcd_fb_refresh(struct picolcd_data *data);
185182
#define picolcd_fbinfo(d) ((d)->fb_info)
186183
#else
@@ -195,9 +192,6 @@ static inline int picolcd_init_framebuffer(struct picolcd_data *data)
195192
static inline void picolcd_exit_framebuffer(struct picolcd_data *data)
196193
{
197194
}
198-
static inline void picolcd_fb_unload(void)
199-
{
200-
}
201195
static inline void picolcd_fb_refresh(struct picolcd_data *data)
202196
{
203197
}

drivers/hid/hid-picolcd_core.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,7 +695,6 @@ static int __init picolcd_init(void)
695695
static void __exit picolcd_exit(void)
696696
{
697697
hid_unregister_driver(&picolcd_driver);
698-
picolcd_fb_unload();
699698
}
700699

701700
module_init(picolcd_init);

drivers/hid/hid-picolcd_fb.c

Lines changed: 18 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -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

328328
static 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

350343
static 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 */
483411
static 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

Comments
 (0)