Skip to content

Commit

Permalink
UEAGLE: Avoid keyboard driver blocking
Browse files Browse the repository at this point in the history
Ueagle-atm driver load DSP firmware in function, which is running from
common workqueue. In some (error) circumstances loading firmware may
sleep for long periods (even 60 seconds, depending on timeout). This
block keyboard driver, which also use common workqueue. To fix problem
use custom workqueue in ueagle-atm.

Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Stanislaw Gruszka authored and Greg Kroah-Hartman committed Oct 12, 2007
1 parent 503add4 commit 04ea02f
Showing 1 changed file with 20 additions and 11 deletions.
31 changes: 20 additions & 11 deletions drivers/usb/atm/ueagle-atm.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ struct uea_softc {
union cmv_dsc cmv_dsc;

struct work_struct task;
struct workqueue_struct *work_q;
u16 pageno;
u16 ovl;

Expand Down Expand Up @@ -1830,7 +1831,7 @@ static int uea_start_reset(struct uea_softc *sc)
/* start loading DSP */
sc->pageno = 0;
sc->ovl = 0;
schedule_work(&sc->task);
queue_work(sc->work_q, &sc->task);

/* wait for modem ready CMV */
ret = wait_cmv_ack(sc);
Expand Down Expand Up @@ -2038,13 +2039,13 @@ static void uea_schedule_load_page_e1(struct uea_softc *sc, struct intr_pkt *int
{
sc->pageno = intr->e1_bSwapPageNo;
sc->ovl = intr->e1_bOvl >> 4 | intr->e1_bOvl << 4;
schedule_work(&sc->task);
queue_work(sc->work_q, &sc->task);
}

static void uea_schedule_load_page_e4(struct uea_softc *sc, struct intr_pkt *intr)
{
sc->pageno = intr->e4_bSwapPageNo;
schedule_work(&sc->task);
queue_work(sc->work_q, &sc->task);
}

/*
Expand Down Expand Up @@ -2117,21 +2118,27 @@ static int uea_boot(struct uea_softc *sc)
init_waitqueue_head(&sc->sync_q);
init_waitqueue_head(&sc->cmv_ack_wait);

sc->work_q = create_workqueue("ueagle-dsp");
if (!sc->work_q) {
uea_err(INS_TO_USBDEV(sc), "cannot allocate workqueue\n");
uea_leaves(INS_TO_USBDEV(sc));
return -ENOMEM;
}

if (UEA_CHIP_VERSION(sc) == ADI930)
load_XILINX_firmware(sc);

intr = kmalloc(size, GFP_KERNEL);
if (!intr) {
uea_err(INS_TO_USBDEV(sc),
"cannot allocate interrupt package\n");
uea_leaves(INS_TO_USBDEV(sc));
return -ENOMEM;
goto err0;
}

sc->urb_int = usb_alloc_urb(0, GFP_KERNEL);
if (!sc->urb_int) {
uea_err(INS_TO_USBDEV(sc), "cannot allocate interrupt URB\n");
goto err;
goto err1;
}

usb_fill_int_urb(sc->urb_int, sc->usb_dev,
Expand All @@ -2144,7 +2151,7 @@ static int uea_boot(struct uea_softc *sc)
if (ret < 0) {
uea_err(INS_TO_USBDEV(sc),
"urb submition failed with error %d\n", ret);
goto err;
goto err1;
}

sc->kthread = kthread_run(uea_kthread, sc, "ueagle-atm");
Expand All @@ -2158,10 +2165,12 @@ static int uea_boot(struct uea_softc *sc)

err2:
usb_kill_urb(sc->urb_int);
err:
err1:
usb_free_urb(sc->urb_int);
sc->urb_int = NULL;
kfree(intr);
err0:
destroy_workqueue(sc->work_q);
uea_leaves(INS_TO_USBDEV(sc));
return -ENOMEM;
}
Expand All @@ -2176,15 +2185,15 @@ static void uea_stop(struct uea_softc *sc)
ret = kthread_stop(sc->kthread);
uea_dbg(INS_TO_USBDEV(sc), "kthread finish with status %d\n", ret);

/* stop any pending boot process */
flush_scheduled_work();

uea_request(sc, UEA_SET_MODE, UEA_LOOPBACK_ON, 0, NULL);

usb_kill_urb(sc->urb_int);
kfree(sc->urb_int->transfer_buffer);
usb_free_urb(sc->urb_int);

/* stop any pending boot process, when no one can schedule work */
destroy_workqueue(sc->work_q);

if (sc->dsp_firm)
release_firmware(sc->dsp_firm);
uea_leaves(INS_TO_USBDEV(sc));
Expand Down

0 comments on commit 04ea02f

Please sign in to comment.