Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 92456
b: refs/heads/master
c: 794b160
h: refs/heads/master
v: v3
  • Loading branch information
Mike Isely authored and Mauro Carvalho Chehab committed Apr 24, 2008
1 parent 7fc43f1 commit e96ccda
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 128 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 8f59100a42576c49e2170e9dc04f8b7ac922a74d
refs/heads/master: 794b16072e00d0a40a8c773dd4319fb1e460a632
113 changes: 70 additions & 43 deletions trunk/drivers/media/video/pvrusb2/pvrusb2-context.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,50 +23,86 @@
#include "pvrusb2-ioread.h"
#include "pvrusb2-hdw.h"
#include "pvrusb2-debug.h"
#include <linux/kthread.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/slab.h>


static void pvr2_context_destroy(struct pvr2_context *mp)
{
pvr2_trace(PVR2_TRACE_STRUCT,"Destroying pvr_main id=%p",mp);
pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp);
if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
kfree(mp);
}


static void pvr2_context_state_check(struct pvr2_context *mp)
static void pvr2_context_notify(struct pvr2_context *mp)
{
if (mp->init_flag) return;

switch (pvr2_hdw_get_state(mp->hdw)) {
case PVR2_STATE_WARM: break;
case PVR2_STATE_ERROR: break;
case PVR2_STATE_READY: break;
case PVR2_STATE_RUN: break;
default: return;
mp->notify_flag = !0;
wake_up(&mp->wait_data);
}


static int pvr2_context_thread(void *_mp)
{
struct pvr2_channel *ch1,*ch2;
struct pvr2_context *mp = _mp;
pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (thread start)",mp);

/* Finish hardware initialization */
if (pvr2_hdw_initialize(mp->hdw,
(void (*)(void *))pvr2_context_notify,mp)) {
mp->video_stream.stream =
pvr2_hdw_get_video_stream(mp->hdw);
/* Trigger interface initialization. By doing this here
initialization runs in our own safe and cozy thread
context. */
if (mp->setup_func) mp->setup_func(mp);
} else {
pvr2_trace(PVR2_TRACE_CTXT,
"pvr2_context %p (thread skipping setup)",mp);
/* Even though initialization did not succeed, we're still
going to enter the wait loop anyway. We need to do this
in order to await the expected disconnect (which we will
detect in the normal course of operation). */
}

pvr2_context_enter(mp); do {
mp->init_flag = !0;
mp->video_stream.stream = pvr2_hdw_get_video_stream(mp->hdw);
if (mp->setup_func) {
mp->setup_func(mp);
/* Now just issue callbacks whenever hardware state changes or if
there is a disconnect. If there is a disconnect and there are
no channels left, then there's no reason to stick around anymore
so we'll self-destruct - tearing down the rest of this driver
instance along the way. */
pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (thread enter loop)",mp);
while (!mp->disconnect_flag || mp->mc_first) {
if (mp->notify_flag) {
mp->notify_flag = 0;
pvr2_trace(PVR2_TRACE_CTXT,
"pvr2_context %p (thread notify)",mp);
for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
ch2 = ch1->mc_next;
if (ch1->check_func) ch1->check_func(ch1);
}
}
} while (0); pvr2_context_exit(mp);
}
wait_event_interruptible(mp->wait_data, mp->notify_flag);
}
pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (thread end)",mp);
pvr2_context_destroy(mp);
return 0;
}


struct pvr2_context *pvr2_context_create(
struct usb_interface *intf,
const struct usb_device_id *devid,
void (*setup_func)(struct pvr2_context *))
{
struct task_struct *thread;
struct pvr2_context *mp = NULL;
mp = kzalloc(sizeof(*mp),GFP_KERNEL);
if (!mp) goto done;
pvr2_trace(PVR2_TRACE_STRUCT,"Creating pvr_main id=%p",mp);
pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (create)",mp);
init_waitqueue_head(&mp->wait_data);
mp->setup_func = setup_func;
mutex_init(&mp->mutex);
mp->hdw = pvr2_hdw_create(intf,devid);
Expand All @@ -75,57 +111,45 @@ struct pvr2_context *pvr2_context_create(
mp = NULL;
goto done;
}
pvr2_hdw_initialize(mp->hdw,
(void (*)(void *))pvr2_context_state_check,
mp);
thread = kthread_run(pvr2_context_thread, mp, "pvrusb2-context");
if (!thread) {
pvr2_context_destroy(mp);
mp = NULL;
goto done;
}
done:
return mp;
}


void pvr2_context_enter(struct pvr2_context *mp)
static void pvr2_context_enter(struct pvr2_context *mp)
{
mutex_lock(&mp->mutex);
pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_enter(id=%p)",mp);
}


void pvr2_context_exit(struct pvr2_context *mp)
static void pvr2_context_exit(struct pvr2_context *mp)
{
int destroy_flag = 0;
if (!(mp->mc_first || !mp->disconnect_flag)) {
destroy_flag = !0;
}
pvr2_trace(PVR2_TRACE_CREG,"pvr2_context_exit(id=%p) outside",mp);
mutex_unlock(&mp->mutex);
if (destroy_flag) pvr2_context_destroy(mp);
}


static void pvr2_context_run_checks(struct pvr2_context *mp)
{
struct pvr2_channel *ch1,*ch2;
for (ch1 = mp->mc_first; ch1; ch1 = ch2) {
ch2 = ch1->mc_next;
if (ch1->check_func) {
ch1->check_func(ch1);
}
}
if (destroy_flag) pvr2_context_notify(mp);
}


void pvr2_context_disconnect(struct pvr2_context *mp)
{
pvr2_context_enter(mp); do {
pvr2_hdw_disconnect(mp->hdw);
mp->disconnect_flag = !0;
pvr2_context_run_checks(mp);
} while (0); pvr2_context_exit(mp);
pvr2_hdw_disconnect(mp->hdw);
mp->disconnect_flag = !0;
pvr2_context_notify(mp);
}


void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
{
pvr2_context_enter(mp);
cp->hdw = mp->hdw;
cp->mc_head = mp;
cp->mc_next = NULL;
Expand All @@ -136,6 +160,7 @@ void pvr2_channel_init(struct pvr2_channel *cp,struct pvr2_context *mp)
mp->mc_first = cp;
}
mp->mc_last = cp;
pvr2_context_exit(mp);
}


Expand All @@ -151,6 +176,7 @@ static void pvr2_channel_disclaim_stream(struct pvr2_channel *cp)
void pvr2_channel_done(struct pvr2_channel *cp)
{
struct pvr2_context *mp = cp->mc_head;
pvr2_context_enter(mp);
pvr2_channel_disclaim_stream(cp);
if (cp->mc_next) {
cp->mc_next->mc_prev = cp->mc_prev;
Expand All @@ -163,6 +189,7 @@ void pvr2_channel_done(struct pvr2_channel *cp)
mp->mc_first = cp->mc_next;
}
cp->hdw = NULL;
pvr2_context_exit(mp);
}


Expand Down
7 changes: 3 additions & 4 deletions trunk/drivers/media/video/pvrusb2/pvrusb2-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,10 @@ struct pvr2_context {
struct pvr2_hdw *hdw;
struct pvr2_context_stream video_stream;
struct mutex mutex;
int notify_flag;
int disconnect_flag;
int init_flag;

wait_queue_head_t wait_data;

/* Called after pvr2_context initialization is complete */
void (*setup_func)(struct pvr2_context *);
Expand All @@ -60,9 +62,6 @@ struct pvr2_channel {
void (*check_func)(struct pvr2_channel *);
};

void pvr2_context_enter(struct pvr2_context *);
void pvr2_context_exit(struct pvr2_context *);

struct pvr2_context *pvr2_context_create(struct usb_interface *intf,
const struct usb_device_id *devid,
void (*setup_func)(struct pvr2_context *));
Expand Down
2 changes: 1 addition & 1 deletion trunk/drivers/media/video/pvrusb2/pvrusb2-debug.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ extern int pvrusb2_debug;
#define PVR2_TRACE_EEPROM (1 << 10) /* eeprom parsing / report */
#define PVR2_TRACE_STRUCT (1 << 11) /* internal struct creation */
#define PVR2_TRACE_OPEN_CLOSE (1 << 12) /* application open / close */
#define PVR2_TRACE_CREG (1 << 13) /* Main critical region entry / exit */
#define PVR2_TRACE_CTXT (1 << 13) /* Main context tracking */
#define PVR2_TRACE_SYSFS (1 << 14) /* Sysfs driven I/O */
#define PVR2_TRACE_FIRMWARE (1 << 15) /* firmware upload actions */
#define PVR2_TRACE_CHIPS (1 << 16) /* chip broadcast operation */
Expand Down
1 change: 0 additions & 1 deletion trunk/drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,6 @@ struct pvr2_hdw {
struct workqueue_struct *workqueue;
struct work_struct workpoll; /* Update driver state */
struct work_struct worki2csync; /* Update i2c clients */
struct work_struct workinit; /* Driver initialization sequence */

/* Video spigot */
struct pvr2_stream *vid_stream;
Expand Down
20 changes: 5 additions & 15 deletions trunk/drivers/media/video/pvrusb2/pvrusb2-hdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,6 @@ static int pvr2_hdw_state_eval(struct pvr2_hdw *);
static void pvr2_hdw_set_cur_freq(struct pvr2_hdw *,unsigned long);
static void pvr2_hdw_worker_i2c(struct work_struct *work);
static void pvr2_hdw_worker_poll(struct work_struct *work);
static void pvr2_hdw_worker_init(struct work_struct *work);
static int pvr2_hdw_wait(struct pvr2_hdw *,int state);
static int pvr2_hdw_untrip_unlocked(struct pvr2_hdw *);
static void pvr2_hdw_state_log_state(struct pvr2_hdw *);
Expand Down Expand Up @@ -1816,15 +1815,16 @@ static void pvr2_hdw_setup(struct pvr2_hdw *hdw)
/* Perform second stage initialization. Set callback pointer first so that
we can avoid a possible initialization race (if the kernel thread runs
before the callback has been set). */
void pvr2_hdw_initialize(struct pvr2_hdw *hdw,
void (*callback_func)(void *),
void *callback_data)
int pvr2_hdw_initialize(struct pvr2_hdw *hdw,
void (*callback_func)(void *),
void *callback_data)
{
LOCK_TAKE(hdw->big_lock); do {
hdw->state_data = callback_data;
hdw->state_func = callback_func;
} while (0); LOCK_GIVE(hdw->big_lock);
queue_work(hdw->workqueue,&hdw->workinit);
pvr2_hdw_setup(hdw);
return hdw->flag_init_ok;
}


Expand Down Expand Up @@ -2032,7 +2032,6 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
hdw->workqueue = create_singlethread_workqueue(hdw->name);
INIT_WORK(&hdw->workpoll,pvr2_hdw_worker_poll);
INIT_WORK(&hdw->worki2csync,pvr2_hdw_worker_i2c);
INIT_WORK(&hdw->workinit,pvr2_hdw_worker_init);

pvr2_trace(PVR2_TRACE_INIT,"Driver unit number is %d, name is %s",
hdw->unit_number,hdw->name);
Expand Down Expand Up @@ -2517,15 +2516,6 @@ static void pvr2_hdw_worker_poll(struct work_struct *work)
}


static void pvr2_hdw_worker_init(struct work_struct *work)
{
struct pvr2_hdw *hdw = container_of(work,struct pvr2_hdw,workinit);
LOCK_TAKE(hdw->big_lock); do {
pvr2_hdw_setup(hdw);
} while (0); LOCK_GIVE(hdw->big_lock);
}


static int pvr2_hdw_wait(struct pvr2_hdw *hdw,int state)
{
return wait_event_interruptible(
Expand Down
6 changes: 3 additions & 3 deletions trunk/drivers/media/video/pvrusb2/pvrusb2-hdw.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,

/* Perform second stage initialization, passing in a notification callback
for when the master state changes. */
void pvr2_hdw_initialize(struct pvr2_hdw *,
void (*callback_func)(void *),
void *callback_data);
int pvr2_hdw_initialize(struct pvr2_hdw *,
void (*callback_func)(void *),
void *callback_data);

/* Destroy hardware interaction structure */
void pvr2_hdw_destroy(struct pvr2_hdw *);
Expand Down
Loading

0 comments on commit e96ccda

Please sign in to comment.