From patchwork Mon Jul 14 10:08:50 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Olivier Sobrie X-Patchwork-Id: 369574 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id A3EE0140076 for ; Mon, 14 Jul 2014 20:09:34 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754422AbaGNKJY (ORCPT ); Mon, 14 Jul 2014 06:09:24 -0400 Received: from mail-wi0-f176.google.com ([209.85.212.176]:59273 "EHLO mail-wi0-f176.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753800AbaGNKIy (ORCPT ); Mon, 14 Jul 2014 06:08:54 -0400 Received: by mail-wi0-f176.google.com with SMTP id bs8so2245143wib.9 for ; Mon, 14 Jul 2014 03:08:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=Eb+GKuKb9CgPAt1sB0mAMM+R8hcriPJAJkB6NsvmIgg=; b=SqSWrKIl10eQtndeOEL1PtvmPMhTx4w0jfqy2j2LbN6CjV+m/EAu9PnQ1GObQMK004 tvwKx6nl2qCEFJNQIl1F8ZyrwQMoJjfxsCMgUTclYxAzPt4c+7AdzNqzJa0HQ8hXAyW0 ItJIpGsmDvJios3EPmfkKe1ELdQ/AFXpcB1cihrdjb2SfivSJynXBkq6so7M0rNGJHLy LWrlIx7HF/wwFrqirD9hVZEigfAMeG4/0JVChm5KIBXOgSJD3/LRdWQOgIq5ECAtmICx XbXhynU1BUpSpPQFmtzzJ1c3Ulv076J0ZnBEwwiaXUH/D4v5G77ltmn/6H06jRIznKpT Bn0Q== X-Received: by 10.180.211.71 with SMTP id na7mr23039107wic.55.1405332532456; Mon, 14 Jul 2014 03:08:52 -0700 (PDT) Received: from localhost.localdomain ([213.99.42.111]) by mx.google.com with ESMTPSA id lk5sm29346410wic.18.2014.07.14.03.08.51 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 14 Jul 2014 03:08:51 -0700 (PDT) From: Olivier Sobrie To: linux-usb@vger.kernel.org, netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Olivier Sobrie , David Miller , David Laight , One Thousand Gnomes , Dan Williams , Jan Dumon Subject: [PATCH v2 2/2] hso: fix deadlock when receiving bursts of data Date: Mon, 14 Jul 2014 12:08:50 +0200 Message-Id: <1405332530-2507-2-git-send-email-olivier@sobrie.be> X-Mailer: git-send-email 2.0.0 In-Reply-To: <1405332530-2507-1-git-send-email-olivier@sobrie.be> References: <1405332530-2507-1-git-send-email-olivier@sobrie.be> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org When the module sends bursts of data, sometimes a deadlock happens in the hso driver when the tty buffer doesn't get the chance to be flushed quickly enough. Remove the endless while loop in function put_rxbuf_data() which is called by the urb completion handler. If there isn't enough room in the tty buffer, discards all the data received in the URB. Cc: David Miller Cc: David Laight Cc: One Thousand Gnomes Cc: Dan Williams Cc: Jan Dumon Signed-off-by: Olivier Sobrie Acked-by: Alan Cox --- Changes in v2: - remove the unthrottle timer added in the previous patch version - drop entire rx urb data if there is not enough space in tty buffer - remove variable curr_rx_urb_offset from hso_serial structure drivers/net/usb/hso.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 9ca2b41..a4272ed 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -258,7 +258,6 @@ struct hso_serial { * so as not to drop characters on the floor. */ int curr_rx_urb_idx; - u16 curr_rx_urb_offset; u8 rx_urb_filled[MAX_RX_URBS]; struct tasklet_struct unthrottle_tasklet; }; @@ -2001,8 +2000,7 @@ static void ctrl_callback(struct urb *urb) static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) { struct tty_struct *tty; - int write_length_remaining = 0; - int curr_write_len; + int count; /* Sanity check */ if (urb == NULL || serial == NULL) { @@ -2012,29 +2010,28 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) tty = tty_port_tty_get(&serial->port); + if (tty && test_bit(TTY_THROTTLED, &tty->flags)) { + tty_kref_put(tty); + return -1; + } + /* Push data to tty */ - write_length_remaining = urb->actual_length - - serial->curr_rx_urb_offset; D1("data to push to tty"); - while (write_length_remaining) { - if (tty && test_bit(TTY_THROTTLED, &tty->flags)) { - tty_kref_put(tty); - return -1; - } - curr_write_len = tty_insert_flip_string(&serial->port, - urb->transfer_buffer + serial->curr_rx_urb_offset, - write_length_remaining); - serial->curr_rx_urb_offset += curr_write_len; - write_length_remaining -= curr_write_len; + count = tty_buffer_request_room(&serial->port, urb->actual_length); + if (count >= urb->actual_length) { + tty_insert_flip_string(&serial->port, urb->transfer_buffer, + urb->actual_length); tty_flip_buffer_push(&serial->port); + } else { + dev_warn(&serial->parent->usb->dev, + "dropping data, %d bytes lost\n", urb->actual_length); } + tty_kref_put(tty); - if (write_length_remaining == 0) { - serial->curr_rx_urb_offset = 0; - serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; - } - return write_length_remaining; + serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; + + return 0; } @@ -2205,7 +2202,6 @@ static int hso_stop_serial_device(struct hso_device *hso_dev) } } serial->curr_rx_urb_idx = 0; - serial->curr_rx_urb_offset = 0; if (serial->tx_urb) usb_kill_urb(serial->tx_urb);