From 7cfefb0d5570c1c2e8ecd9ada65f1430c1a75133 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Sun, 26 Feb 2012 18:15:52 -0600 Subject: [PATCH 1/4] wcte12xp-wip: Unbind self if timeout in getreg. Signed-off-by: Shaun Ruffell --- drivers/dahdi/wcte12xp/base.c | 41 +++++++++++++++++++++++++++++++++++++ drivers/dahdi/wcte12xp/wcte12xp.h | 1 + 2 files changed, 42 insertions(+) diff --git a/drivers/dahdi/wcte12xp/base.c b/drivers/dahdi/wcte12xp/base.c index e7f3dca..5771c01 100644 --- a/drivers/dahdi/wcte12xp/base.c +++ b/drivers/dahdi/wcte12xp/base.c @@ -640,12 +640,51 @@ static inline int t1_setreg(struct t1 *wc, int addr, int val) return 0; } +struct remove_work { + struct work_struct work; + struct device *dev; +}; + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) +static void remove_device(void *data) +{ + struct remove_work *rw = data; +#else +static void remove_device(struct work_struct *work) +{ + struct remove_work *rw = container_of(work, struct remove_work, work); +#endif + struct device *dev = rw->dev; + kfree(rw); + device_release_driver(dev); +} + +static void unbind_self(struct t1 *wc) +{ + struct remove_work *rw; + rw = kzalloc(sizeof(*rw), GFP_KERNEL); + if (!rw) { + WARN_ON_ONCE(1); + return; + } +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) + INIT_WORK(&rw->work, remove_device, rw); +#else + INIT_WORK(&rw->work, remove_device); +#endif + rw->dev = &wc->vb.pdev->dev; + schedule_work(&rw->work); +} + static int t1_getreg(struct t1 *wc, int addr) { struct command *cmd = NULL; unsigned long ret; unsigned long flags; + if (unlikely(test_bit(GONE, &wc->bit_flags))) + return -EIO; + might_sleep(); cmd = get_free_cmd(wc); @@ -665,11 +704,13 @@ static int t1_getreg(struct t1 *wc, int addr) spin_unlock_irqrestore(&wc->reglock, flags); free_cmd(wc, cmd); if (-ERESTARTSYS != ret) { + set_bit(GONE, &wc->bit_flags); if (printk_ratelimit()) { dev_warn(&wc->vb.pdev->dev, "Timeout in %s\n", __func__); } ret = -EIO; + unbind_self(wc); } return ret; } else { diff --git a/drivers/dahdi/wcte12xp/wcte12xp.h b/drivers/dahdi/wcte12xp/wcte12xp.h index 8ef4753..9b34e14 100644 --- a/drivers/dahdi/wcte12xp/wcte12xp.h +++ b/drivers/dahdi/wcte12xp/wcte12xp.h @@ -113,6 +113,7 @@ struct t1 { #define INITIALIZED 1 #define SHUTDOWN 2 #define READY 3 +#define GONE 4 unsigned long bit_flags; unsigned long alarmtimer; unsigned char ledstate; -- 1.7.9.2