Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757200Ab0DVTjm (ORCPT ); Thu, 22 Apr 2010 15:39:42 -0400 Received: from kroah.org ([198.145.64.141]:41400 "EHLO coco.kroah.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756810Ab0DVT3f (ORCPT ); Thu, 22 Apr 2010 15:29:35 -0400 X-Mailbox-Line: From gregkh@kvm.kroah.org Thu Apr 22 12:09:21 2010 Message-Id: <20100422190921.456355044@kvm.kroah.org> User-Agent: quilt/0.48-4.4 Date: Thu, 22 Apr 2010 12:10:08 -0700 From: Greg KH To: linux-kernel@vger.kernel.org, stable@kernel.org Cc: stable-review@kernel.org, torvalds@linux-foundation.org, akpm@linux-foundation.org, alan@lxorguk.ukuu.org.uk, Oliver Neukum Subject: [157/197] USB: cdc-acm: Update to new autopm API In-Reply-To: <20100422191857.GA13268@kroah.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3848 Lines: 132 2.6.32-stable review patch. If anyone has any objections, please let us know. ------------------ From: Oliver Neukum commit 97d35f95552c9a0ee4777a7f04431a9fd1260478 upstream. Update cdc-acm to the async methods eliminating the workqueue [This fixes a reported lockup for the cdc-acm driver - gregkh] Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 43 ++++++++++++++++++++++--------------------- drivers/usb/class/cdc-acm.h | 1 - 2 files changed, 22 insertions(+), 22 deletions(-) --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -170,6 +170,7 @@ static void acm_write_done(struct acm *a { wb->use = 0; acm->transmitting--; + usb_autopm_put_interface_async(acm->control); } /* @@ -211,9 +212,12 @@ static int acm_write_start(struct acm *a } dbg("%s susp_count: %d", __func__, acm->susp_count); + usb_autopm_get_interface_async(acm->control); if (acm->susp_count) { - acm->delayed_wb = wb; - schedule_work(&acm->waker); + if (!acm->delayed_wb) + acm->delayed_wb = wb; + else + usb_autopm_put_interface_async(acm->control); spin_unlock_irqrestore(&acm->write_lock, flags); return 0; /* A white lie */ } @@ -534,23 +538,6 @@ static void acm_softint(struct work_stru tty_kref_put(tty); } -static void acm_waker(struct work_struct *waker) -{ - struct acm *acm = container_of(waker, struct acm, waker); - int rv; - - rv = usb_autopm_get_interface(acm->control); - if (rv < 0) { - dev_err(&acm->dev->dev, "Autopm failure in %s\n", __func__); - return; - } - if (acm->delayed_wb) { - acm_start_wb(acm, acm->delayed_wb); - acm->delayed_wb = NULL; - } - usb_autopm_put_interface(acm->control); -} - /* * TTY handlers */ @@ -1178,7 +1165,6 @@ made_compressed_probe: acm->urb_task.func = acm_rx_tasklet; acm->urb_task.data = (unsigned long) acm; INIT_WORK(&acm->work, acm_softint); - INIT_WORK(&acm->waker, acm_waker); init_waitqueue_head(&acm->drain_wait); spin_lock_init(&acm->throttle_lock); spin_lock_init(&acm->write_lock); @@ -1343,7 +1329,6 @@ static void stop_data_traffic(struct acm tasklet_enable(&acm->urb_task); cancel_work_sync(&acm->work); - cancel_work_sync(&acm->waker); } static void acm_disconnect(struct usb_interface *intf) @@ -1435,6 +1420,7 @@ static int acm_suspend(struct usb_interf static int acm_resume(struct usb_interface *intf) { struct acm *acm = usb_get_intfdata(intf); + struct acm_wb *wb; int rv = 0; int cnt; @@ -1449,6 +1435,21 @@ static int acm_resume(struct usb_interfa mutex_lock(&acm->mutex); if (acm->port.count) { rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); + + spin_lock_irq(&acm->write_lock); + if (acm->delayed_wb) { + wb = acm->delayed_wb; + acm->delayed_wb = NULL; + spin_unlock_irq(&acm->write_lock); + acm_start_wb(acm, acm->delayed_wb); + } else { + spin_unlock_irq(&acm->write_lock); + } + + /* + * delayed error checking because we must + * do the write path at all cost + */ if (rv < 0) goto err_out; --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h @@ -112,7 +112,6 @@ struct acm { struct mutex mutex; struct usb_cdc_line_coding line; /* bits, stop, parity */ struct work_struct work; /* work queue entry for line discipline waking up */ - struct work_struct waker; wait_queue_head_t drain_wait; /* close processing */ struct tasklet_struct urb_task; /* rx processing */ spinlock_t throttle_lock; /* synchronize throtteling and read callback */ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/