diff options
Diffstat (limited to 'drivers/media/dvb/pt1')
-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: |