|
@@ -36,6 +36,7 @@
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/spinlock.h>
|
|
|
#include <linux/sched.h>
|
|
|
+#include <linux/kthread.h>
|
|
|
|
|
|
#include "dvb_ca_en50221.h"
|
|
|
#include "dvb_ringbuffer.h"
|
|
@@ -139,13 +140,7 @@ struct dvb_ca_private {
|
|
|
wait_queue_head_t wait_queue;
|
|
|
|
|
|
/* PID of the monitoring thread */
|
|
|
- pid_t thread_pid;
|
|
|
-
|
|
|
- /* Wait queue used when shutting thread down */
|
|
|
- wait_queue_head_t thread_queue;
|
|
|
-
|
|
|
- /* Flag indicating when thread should exit */
|
|
|
- unsigned int exit:1;
|
|
|
+ struct task_struct *thread;
|
|
|
|
|
|
/* Flag indicating if the CA device is open */
|
|
|
unsigned int open:1;
|
|
@@ -901,27 +896,9 @@ static void dvb_ca_en50221_thread_wakeup(struct dvb_ca_private *ca)
|
|
|
|
|
|
ca->wakeup = 1;
|
|
|
mb();
|
|
|
- wake_up_interruptible(&ca->thread_queue);
|
|
|
+ wake_up_process(ca->thread);
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * Used by the CA thread to determine if an early wakeup is necessary
|
|
|
- *
|
|
|
- * @param ca CA instance.
|
|
|
- */
|
|
|
-static int dvb_ca_en50221_thread_should_wakeup(struct dvb_ca_private *ca)
|
|
|
-{
|
|
|
- if (ca->wakeup) {
|
|
|
- ca->wakeup = 0;
|
|
|
- return 1;
|
|
|
- }
|
|
|
- if (ca->exit)
|
|
|
- return 1;
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
/**
|
|
|
* Update the delay used by the thread.
|
|
|
*
|
|
@@ -981,7 +958,6 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca)
|
|
|
static int dvb_ca_en50221_thread(void *data)
|
|
|
{
|
|
|
struct dvb_ca_private *ca = data;
|
|
|
- char name[15];
|
|
|
int slot;
|
|
|
int flags;
|
|
|
int status;
|
|
@@ -990,28 +966,17 @@ static int dvb_ca_en50221_thread(void *data)
|
|
|
|
|
|
dprintk("%s\n", __FUNCTION__);
|
|
|
|
|
|
- /* setup kernel thread */
|
|
|
- snprintf(name, sizeof(name), "kdvb-ca-%i:%i", ca->dvbdev->adapter->num, ca->dvbdev->id);
|
|
|
-
|
|
|
- lock_kernel();
|
|
|
- daemonize(name);
|
|
|
- sigfillset(¤t->blocked);
|
|
|
- unlock_kernel();
|
|
|
-
|
|
|
/* choose the correct initial delay */
|
|
|
dvb_ca_en50221_thread_update_delay(ca);
|
|
|
|
|
|
/* main loop */
|
|
|
- while (!ca->exit) {
|
|
|
+ while (!kthread_should_stop()) {
|
|
|
/* sleep for a bit */
|
|
|
- if (!ca->wakeup) {
|
|
|
- flags = wait_event_interruptible_timeout(ca->thread_queue,
|
|
|
- dvb_ca_en50221_thread_should_wakeup(ca),
|
|
|
- ca->delay);
|
|
|
- if ((flags == -ERESTARTSYS) || ca->exit) {
|
|
|
- /* got signal or quitting */
|
|
|
- break;
|
|
|
- }
|
|
|
+ while (!ca->wakeup) {
|
|
|
+ set_current_state(TASK_INTERRUPTIBLE);
|
|
|
+ schedule_timeout(ca->delay);
|
|
|
+ if (kthread_should_stop())
|
|
|
+ return 0;
|
|
|
}
|
|
|
ca->wakeup = 0;
|
|
|
|
|
@@ -1180,10 +1145,6 @@ static int dvb_ca_en50221_thread(void *data)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /* completed */
|
|
|
- ca->thread_pid = 0;
|
|
|
- mb();
|
|
|
- wake_up_interruptible(&ca->thread_queue);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1683,9 +1644,6 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
|
|
|
goto error;
|
|
|
}
|
|
|
init_waitqueue_head(&ca->wait_queue);
|
|
|
- ca->thread_pid = 0;
|
|
|
- init_waitqueue_head(&ca->thread_queue);
|
|
|
- ca->exit = 0;
|
|
|
ca->open = 0;
|
|
|
ca->wakeup = 0;
|
|
|
ca->next_read_slot = 0;
|
|
@@ -1711,14 +1669,14 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
|
|
|
mb();
|
|
|
|
|
|
/* create a kthread for monitoring this CA device */
|
|
|
-
|
|
|
- ret = kernel_thread(dvb_ca_en50221_thread, ca, 0);
|
|
|
-
|
|
|
- if (ret < 0) {
|
|
|
- printk("dvb_ca_init: failed to start kernel_thread (%d)\n", ret);
|
|
|
+ ca->thread = kthread_run(dvb_ca_en50221_thread, ca, "kdvb-ca-%i:%i",
|
|
|
+ ca->dvbdev->adapter->num, ca->dvbdev->id);
|
|
|
+ if (IS_ERR(ca->thread)) {
|
|
|
+ ret = PTR_ERR(ca->thread);
|
|
|
+ printk("dvb_ca_init: failed to start kernel_thread (%d)\n",
|
|
|
+ ret);
|
|
|
goto error;
|
|
|
}
|
|
|
- ca->thread_pid = ret;
|
|
|
return 0;
|
|
|
|
|
|
error:
|
|
@@ -1749,17 +1707,7 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)
|
|
|
dprintk("%s\n", __FUNCTION__);
|
|
|
|
|
|
/* shutdown the thread if there was one */
|
|
|
- if (ca->thread_pid) {
|
|
|
- if (kill_proc(ca->thread_pid, 0, 1) == -ESRCH) {
|
|
|
- printk("dvb_ca_release adapter %d: thread PID %d already died\n",
|
|
|
- ca->dvbdev->adapter->num, ca->thread_pid);
|
|
|
- } else {
|
|
|
- ca->exit = 1;
|
|
|
- mb();
|
|
|
- dvb_ca_en50221_thread_wakeup(ca);
|
|
|
- wait_event_interruptible(ca->thread_queue, ca->thread_pid == 0);
|
|
|
- }
|
|
|
- }
|
|
|
+ kthread_stop(ca->thread);
|
|
|
|
|
|
for (i = 0; i < ca->slot_count; i++) {
|
|
|
dvb_ca_en50221_slot_shutdown(ca, i);
|