ser_gigaset: convert mutex to completion
The ser_gigaset ISDN driver was using a mutex in its close() method for waiting for other running ldisc methods to finish. That's what completions are for. Incidentally, this also avoids a spurious "BUG: lock held at task exit time" message when the driver's userspace daemon daemonizes itself. Signed-off-by: Tilman Schmidt <tilman@imap.cc> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
e468c04894
commit
ee51ef0ecb
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
|
#include <linux/completion.h>
|
||||||
|
|
||||||
/* Version Information */
|
/* Version Information */
|
||||||
#define DRIVER_AUTHOR "Tilman Schmidt"
|
#define DRIVER_AUTHOR "Tilman Schmidt"
|
||||||
|
@ -48,7 +49,7 @@ struct ser_cardstate {
|
||||||
struct platform_device dev;
|
struct platform_device dev;
|
||||||
struct tty_struct *tty;
|
struct tty_struct *tty;
|
||||||
atomic_t refcnt;
|
atomic_t refcnt;
|
||||||
struct mutex dead_mutex;
|
struct completion dead_cmp;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct platform_driver device_driver = {
|
static struct platform_driver device_driver = {
|
||||||
|
@ -498,7 +499,7 @@ static struct cardstate *cs_get(struct tty_struct *tty)
|
||||||
static void cs_put(struct cardstate *cs)
|
static void cs_put(struct cardstate *cs)
|
||||||
{
|
{
|
||||||
if (atomic_dec_and_test(&cs->hw.ser->refcnt))
|
if (atomic_dec_and_test(&cs->hw.ser->refcnt))
|
||||||
mutex_unlock(&cs->hw.ser->dead_mutex);
|
complete(&cs->hw.ser->dead_cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -527,8 +528,8 @@ gigaset_tty_open(struct tty_struct *tty)
|
||||||
|
|
||||||
cs->dev = &cs->hw.ser->dev.dev;
|
cs->dev = &cs->hw.ser->dev.dev;
|
||||||
cs->hw.ser->tty = tty;
|
cs->hw.ser->tty = tty;
|
||||||
mutex_init(&cs->hw.ser->dead_mutex);
|
|
||||||
atomic_set(&cs->hw.ser->refcnt, 1);
|
atomic_set(&cs->hw.ser->refcnt, 1);
|
||||||
|
init_completion(&cs->hw.ser->dead_cmp);
|
||||||
|
|
||||||
tty->disc_data = cs;
|
tty->disc_data = cs;
|
||||||
|
|
||||||
|
@ -543,7 +544,6 @@ gigaset_tty_open(struct tty_struct *tty)
|
||||||
}
|
}
|
||||||
|
|
||||||
gig_dbg(DEBUG_INIT, "Startup of HLL done");
|
gig_dbg(DEBUG_INIT, "Startup of HLL done");
|
||||||
mutex_lock(&cs->hw.ser->dead_mutex);
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -577,7 +577,7 @@ gigaset_tty_close(struct tty_struct *tty)
|
||||||
else {
|
else {
|
||||||
/* wait for running methods to finish */
|
/* wait for running methods to finish */
|
||||||
if (!atomic_dec_and_test(&cs->hw.ser->refcnt))
|
if (!atomic_dec_and_test(&cs->hw.ser->refcnt))
|
||||||
mutex_lock(&cs->hw.ser->dead_mutex);
|
wait_for_completion(&cs->hw.ser->dead_cmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* stop operations */
|
/* stop operations */
|
||||||
|
|
Loading…
Reference in New Issue