diff options
author | Akihiro Tsukada <tskd2@yahoo.co.jp> | 2012-03-10 09:38:13 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-03-19 14:46:36 -0400 |
commit | 847e87659620890bfc80ce7bf682f2a5354543b2 (patch) | |
tree | b9929128874639472b0892e58ab10eddc8db71e0 /drivers/media/dvb | |
parent | 2321acf2962514088c2230b6d54f7a56368576c5 (diff) |
[media] dvb: earth-pt1: stop polling data when no one accesses the device
The driver started a kthread to poll the DMA buffers soon after probing,
which relsuleted in 1000/sec sleeps and wakeups of the thread doing nothing
useful until someone started feeding.
This patch changes the creation and destruction of the kthread depending on the number of users.
Signed-off-by: Akihiro Tsukada <tskd2@yahoo.co.jp>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/dvb')
-rw-r--r-- | drivers/media/dvb/pt1/pt1.c | 73 |
1 files changed, 50 insertions, 23 deletions
diff --git a/drivers/media/dvb/pt1/pt1.c b/drivers/media/dvb/pt1/pt1.c index b81df5fafe26..463f7849c44c 100644 --- a/drivers/media/dvb/pt1/pt1.c +++ b/drivers/media/dvb/pt1/pt1.c | |||
@@ -77,6 +77,8 @@ struct pt1 { | |||
77 | struct pt1_adapter *adaps[PT1_NR_ADAPS]; | 77 | struct pt1_adapter *adaps[PT1_NR_ADAPS]; |
78 | struct pt1_table *tables; | 78 | struct pt1_table *tables; |
79 | struct task_struct *kthread; | 79 | struct task_struct *kthread; |
80 | int table_index; | ||
81 | int buf_index; | ||
80 | 82 | ||
81 | struct mutex lock; | 83 | struct mutex lock; |
82 | int power; | 84 | int power; |
@@ -303,30 +305,25 @@ static int pt1_filter(struct pt1 *pt1, struct pt1_buffer_page *page) | |||
303 | static int pt1_thread(void *data) | 305 | static int pt1_thread(void *data) |
304 | { | 306 | { |
305 | struct pt1 *pt1; | 307 | struct pt1 *pt1; |
306 | int table_index; | ||
307 | int buf_index; | ||
308 | struct pt1_buffer_page *page; | 308 | struct pt1_buffer_page *page; |
309 | 309 | ||
310 | pt1 = data; | 310 | pt1 = data; |
311 | set_freezable(); | 311 | set_freezable(); |
312 | 312 | ||
313 | table_index = 0; | ||
314 | buf_index = 0; | ||
315 | |||
316 | while (!kthread_should_stop()) { | 313 | while (!kthread_should_stop()) { |
317 | try_to_freeze(); | 314 | try_to_freeze(); |
318 | 315 | ||
319 | page = pt1->tables[table_index].bufs[buf_index].page; | 316 | page = pt1->tables[pt1->table_index].bufs[pt1->buf_index].page; |
320 | if (!pt1_filter(pt1, page)) { | 317 | if (!pt1_filter(pt1, page)) { |
321 | schedule_timeout_interruptible((HZ + 999) / 1000); | 318 | schedule_timeout_interruptible((HZ + 999) / 1000); |
322 | continue; | 319 | continue; |
323 | } | 320 | } |
324 | 321 | ||
325 | if (++buf_index >= PT1_NR_BUFS) { | 322 | if (++pt1->buf_index >= PT1_NR_BUFS) { |
326 | pt1_increment_table_count(pt1); | 323 | pt1_increment_table_count(pt1); |
327 | buf_index = 0; | 324 | pt1->buf_index = 0; |
328 | if (++table_index >= pt1_nr_tables) | 325 | if (++pt1->table_index >= pt1_nr_tables) |
329 | table_index = 0; | 326 | pt1->table_index = 0; |
330 | } | 327 | } |
331 | } | 328 | } |
332 | 329 | ||
@@ -477,21 +474,60 @@ err: | |||
477 | return ret; | 474 | return ret; |
478 | } | 475 | } |
479 | 476 | ||
477 | static int pt1_start_polling(struct pt1 *pt1) | ||
478 | { | ||
479 | int ret = 0; | ||
480 | |||
481 | mutex_lock(&pt1->lock); | ||
482 | if (!pt1->kthread) { | ||
483 | pt1->kthread = kthread_run(pt1_thread, pt1, "earth-pt1"); | ||
484 | if (IS_ERR(pt1->kthread)) { | ||
485 | ret = PTR_ERR(pt1->kthread); | ||
486 | pt1->kthread = NULL; | ||
487 | } | ||
488 | } | ||
489 | mutex_unlock(&pt1->lock); | ||
490 | return ret; | ||
491 | } | ||
492 | |||
480 | static int pt1_start_feed(struct dvb_demux_feed *feed) | 493 | static int pt1_start_feed(struct dvb_demux_feed *feed) |
481 | { | 494 | { |
482 | struct pt1_adapter *adap; | 495 | struct pt1_adapter *adap; |
483 | adap = container_of(feed->demux, struct pt1_adapter, demux); | 496 | adap = container_of(feed->demux, struct pt1_adapter, demux); |
484 | if (!adap->users++) | 497 | if (!adap->users++) { |
498 | int ret; | ||
499 | |||
500 | ret = pt1_start_polling(adap->pt1); | ||
501 | if (ret) | ||
502 | return ret; | ||
485 | pt1_set_stream(adap->pt1, adap->index, 1); | 503 | pt1_set_stream(adap->pt1, adap->index, 1); |
504 | } | ||
486 | return 0; | 505 | return 0; |
487 | } | 506 | } |
488 | 507 | ||
508 | static void pt1_stop_polling(struct pt1 *pt1) | ||
509 | { | ||
510 | int i, count; | ||
511 | |||
512 | mutex_lock(&pt1->lock); | ||
513 | for (i = 0, count = 0; i < PT1_NR_ADAPS; i++) | ||
514 | count += pt1->adaps[i]->users; | ||
515 | |||
516 | if (count == 0 && pt1->kthread) { | ||
517 | kthread_stop(pt1->kthread); | ||
518 | pt1->kthread = NULL; | ||
519 | } | ||
520 | mutex_unlock(&pt1->lock); | ||
521 | } | ||
522 | |||
489 | static int pt1_stop_feed(struct dvb_demux_feed *feed) | 523 | static int pt1_stop_feed(struct dvb_demux_feed *feed) |
490 | { | 524 | { |
491 | struct pt1_adapter *adap; | 525 | struct pt1_adapter *adap; |
492 | adap = container_of(feed->demux, struct pt1_adapter, demux); | 526 | adap = container_of(feed->demux, struct pt1_adapter, demux); |
493 | if (!--adap->users) | 527 | if (!--adap->users) { |
494 | pt1_set_stream(adap->pt1, adap->index, 0); | 528 | pt1_set_stream(adap->pt1, adap->index, 0); |
529 | pt1_stop_polling(adap->pt1); | ||
530 | } | ||
495 | return 0; | 531 | return 0; |
496 | } | 532 | } |
497 | 533 | ||
@@ -1020,7 +1056,8 @@ static void __devexit pt1_remove(struct pci_dev *pdev) | |||
1020 | pt1 = pci_get_drvdata(pdev); | 1056 | pt1 = pci_get_drvdata(pdev); |
1021 | regs = pt1->regs; | 1057 | regs = pt1->regs; |
1022 | 1058 | ||
1023 | kthread_stop(pt1->kthread); | 1059 | if (pt1->kthread) |
1060 | kthread_stop(pt1->kthread); | ||
1024 | pt1_cleanup_tables(pt1); | 1061 | pt1_cleanup_tables(pt1); |
1025 | pt1_cleanup_frontends(pt1); | 1062 | pt1_cleanup_frontends(pt1); |
1026 | pt1_disable_ram(pt1); | 1063 | pt1_disable_ram(pt1); |
@@ -1043,7 +1080,6 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1043 | void __iomem *regs; | 1080 | void __iomem *regs; |
1044 | struct pt1 *pt1; | 1081 | struct pt1 *pt1; |
1045 | struct i2c_adapter *i2c_adap; | 1082 | struct i2c_adapter *i2c_adap; |
1046 | struct task_struct *kthread; | ||
1047 | 1083 | ||
1048 | ret = pci_enable_device(pdev); | 1084 | ret = pci_enable_device(pdev); |
1049 | if (ret < 0) | 1085 | if (ret < 0) |
@@ -1139,17 +1175,8 @@ pt1_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1139 | if (ret < 0) | 1175 | if (ret < 0) |
1140 | goto err_pt1_cleanup_frontends; | 1176 | goto err_pt1_cleanup_frontends; |
1141 | 1177 | ||
1142 | kthread = kthread_run(pt1_thread, pt1, "pt1"); | ||
1143 | if (IS_ERR(kthread)) { | ||
1144 | ret = PTR_ERR(kthread); | ||
1145 | goto err_pt1_cleanup_tables; | ||
1146 | } | ||
1147 | |||
1148 | pt1->kthread = kthread; | ||
1149 | return 0; | 1178 | return 0; |
1150 | 1179 | ||
1151 | err_pt1_cleanup_tables: | ||
1152 | pt1_cleanup_tables(pt1); | ||
1153 | err_pt1_cleanup_frontends: | 1180 | err_pt1_cleanup_frontends: |
1154 | pt1_cleanup_frontends(pt1); | 1181 | pt1_cleanup_frontends(pt1); |
1155 | err_pt1_disable_ram: | 1182 | err_pt1_disable_ram: |