From patchwork Mon Feb 12 14:10:20 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mika Westerberg X-Patchwork-Id: 872092 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3zg6yC4RMfz9t2l for ; Tue, 13 Feb 2018 01:10:27 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S935009AbeBLOKY (ORCPT ); Mon, 12 Feb 2018 09:10:24 -0500 Received: from mga12.intel.com ([192.55.52.136]:42472 "EHLO mga12.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934648AbeBLOKX (ORCPT ); Mon, 12 Feb 2018 09:10:23 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 12 Feb 2018 06:10:22 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.46,501,1511856000"; d="scan'208";a="29374591" Received: from black.fi.intel.com ([10.237.72.28]) by fmsmga004.fm.intel.com with ESMTP; 12 Feb 2018 06:10:21 -0800 Received: by black.fi.intel.com (Postfix, from userid 1001) id 649DAEC; Mon, 12 Feb 2018 16:10:20 +0200 (EET) From: Mika Westerberg To: "David S . Miller" Cc: Michael Jamet , Yehezkel Bernat , Mika Westerberg , netdev@vger.kernel.org Subject: [PATCH net 2/2] net: thunderbolt: Run disconnect flow asynchronously when logout is received Date: Mon, 12 Feb 2018 17:10:20 +0300 Message-Id: <20180212141020.78136-2-mika.westerberg@linux.intel.com> X-Mailer: git-send-email 2.15.1 In-Reply-To: <20180212141020.78136-1-mika.westerberg@linux.intel.com> References: <20180212141020.78136-1-mika.westerberg@linux.intel.com> Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org The control channel calls registered callbacks when control messages such as XDomain protocol messages are received. The control channel handling is done in a worker running on system workqueue which means the networking driver can't run tear down flow which includes sending disconnect request and waiting for a reply in the same worker. Otherwise reply is never received (as the work is already running) and the operation times out. To fix this run disconnect ThunderboltIP flow asynchronously once ThunderboltIP logout message is received. Fixes: e69b6c02b4c3 ("net: Add support for networking over Thunderbolt cable") Signed-off-by: Mika Westerberg Cc: stable@vger.kernel.org --- drivers/net/thunderbolt.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/thunderbolt.c b/drivers/net/thunderbolt.c index 71cf9ab72fbc..e0d6760f3219 100644 --- a/drivers/net/thunderbolt.c +++ b/drivers/net/thunderbolt.c @@ -166,6 +166,8 @@ struct tbnet_ring { * @connected_work: Worker that finalizes the ThunderboltIP connection * setup and enables DMA paths for high speed data * transfers + * @disconnect_work: Worker that handles tearing down the ThunderboltIP + * connection * @rx_hdr: Copy of the currently processed Rx frame. Used when a * network packet consists of multiple Thunderbolt frames. * In host byte order. @@ -190,6 +192,7 @@ struct tbnet { int login_retries; struct delayed_work login_work; struct work_struct connected_work; + struct work_struct disconnect_work; struct thunderbolt_ip_frame_header rx_hdr; struct tbnet_ring rx_ring; atomic_t frame_id; @@ -445,7 +448,7 @@ static int tbnet_handle_packet(const void *buf, size_t size, void *data) case TBIP_LOGOUT: ret = tbnet_logout_response(net, route, sequence, command_id); if (!ret) - tbnet_tear_down(net, false); + queue_work(system_long_wq, &net->disconnect_work); break; default: @@ -659,6 +662,13 @@ static void tbnet_login_work(struct work_struct *work) } } +static void tbnet_disconnect_work(struct work_struct *work) +{ + struct tbnet *net = container_of(work, typeof(*net), disconnect_work); + + tbnet_tear_down(net, false); +} + static bool tbnet_check_frame(struct tbnet *net, const struct tbnet_frame *tf, const struct thunderbolt_ip_frame_header *hdr) { @@ -881,6 +891,7 @@ static int tbnet_stop(struct net_device *dev) napi_disable(&net->napi); + cancel_work_sync(&net->disconnect_work); tbnet_tear_down(net, true); tb_ring_free(net->rx_ring.ring); @@ -1195,6 +1206,7 @@ static int tbnet_probe(struct tb_service *svc, const struct tb_service_id *id) net = netdev_priv(dev); INIT_DELAYED_WORK(&net->login_work, tbnet_login_work); INIT_WORK(&net->connected_work, tbnet_connected_work); + INIT_WORK(&net->disconnect_work, tbnet_disconnect_work); mutex_init(&net->connection_lock); atomic_set(&net->command_id, 0); atomic_set(&net->frame_id, 0);