Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/810670/?format=api
{ "id": 810670, "url": "http://patchwork.ozlabs.org/api/patches/810670/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/patch/20170906151925.15221-2-sthemmin@microsoft.com/", "project": { "id": 7, "url": "http://patchwork.ozlabs.org/api/projects/7/?format=api", "name": "Linux network development", "link_name": "netdev", "list_id": "netdev.vger.kernel.org", "list_email": "netdev@vger.kernel.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20170906151925.15221-2-sthemmin@microsoft.com>", "list_archive_url": null, "date": "2017-09-06T15:19:25", "name": "[net-next,1/1] hv_netvsc: fix deadlock on hotplug", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": true, "hash": "46f5c641e3efb9284a6a670654fc8f1db8fc44bf", "submitter": { "id": 21389, "url": "http://patchwork.ozlabs.org/api/people/21389/?format=api", "name": "Stephen Hemminger", "email": "stephen@networkplumber.org" }, "delegate": { "id": 34, "url": "http://patchwork.ozlabs.org/api/users/34/?format=api", "username": "davem", "first_name": "David", "last_name": "Miller", "email": "davem@davemloft.net" }, "mbox": "http://patchwork.ozlabs.org/project/netdev/patch/20170906151925.15221-2-sthemmin@microsoft.com/mbox/", "series": [ { "id": 1833, "url": "http://patchwork.ozlabs.org/api/series/1833/?format=api", "web_url": "http://patchwork.ozlabs.org/project/netdev/list/?series=1833", "date": "2017-09-06T15:19:24", "name": "netvsc hot plug fix", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/1833/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/810670/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/810670/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<netdev-owner@vger.kernel.org>", "X-Original-To": "patchwork-incoming@ozlabs.org", "Delivered-To": "patchwork-incoming@ozlabs.org", "Authentication-Results": [ "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=vger.kernel.org\n\t(client-ip=209.132.180.67; helo=vger.kernel.org;\n\tenvelope-from=netdev-owner@vger.kernel.org;\n\treceiver=<UNKNOWN>)", "ozlabs.org; dkim=pass (2048-bit key;\n\tunprotected) header.d=networkplumber-org.20150623.gappssmtp.com\n\theader.i=@networkplumber-org.20150623.gappssmtp.com\n\theader.b=\"wcrAhsBq\"; dkim-atps=neutral" ], "Received": [ "from vger.kernel.org (vger.kernel.org [209.132.180.67])\n\tby ozlabs.org (Postfix) with ESMTP id 3xnS1X4Kfnz9t2R\n\tfor <patchwork-incoming@ozlabs.org>;\n\tThu, 7 Sep 2017 01:19:44 +1000 (AEST)", "(majordomo@vger.kernel.org) by vger.kernel.org via listexpand\n\tid S932950AbdIFPTm (ORCPT <rfc822;patchwork-incoming@ozlabs.org>);\n\tWed, 6 Sep 2017 11:19:42 -0400", "from mail-pg0-f52.google.com ([74.125.83.52]:34838 \"EHLO\n\tmail-pg0-f52.google.com\" rhost-flags-OK-OK-OK-OK) by vger.kernel.org\n\twith ESMTP id S932657AbdIFPTg (ORCPT\n\t<rfc822;netdev@vger.kernel.org>); Wed, 6 Sep 2017 11:19:36 -0400", "by mail-pg0-f52.google.com with SMTP id 188so12513270pgb.2\n\tfor <netdev@vger.kernel.org>; Wed, 06 Sep 2017 08:19:35 -0700 (PDT)", "from xeon-e3.lan (76-14-207-240.or.wavecable.com. [76.14.207.240])\n\tby smtp.gmail.com with ESMTPSA id\n\tt81sm51179pfg.154.2017.09.06.08.19.34\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tWed, 06 Sep 2017 08:19:34 -0700 (PDT)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=networkplumber-org.20150623.gappssmtp.com; s=20150623;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=P6HtSSn07/iV99bQ0mXQZIICX6sui58LGPkqqs1hxlE=;\n\tb=wcrAhsBqu5cHFF1KWNoUjmv4r928HyLnXPxk2vPYHV7QK/hiQcasUN/ykcIltIXbIE\n\tXxs4DhGdfdUmtA4kIWL0rbrl/uS9RQMqP9uSvCnbdrugYr3e3YkhFb6eLwdG3rYO63Vl\n\tyoTZG4JIyGsxtaF3/M/SARJl4+3kyzPngM8GS2H2RQV4x8Be5iELznA8JQ7OyJQUhSSD\n\thwPQDBuQ33xXRN8C3HZW/0rnWvwe7hiYBljJQa11EmWyR4B9EsG5UNVDjU3AaAQ3x6bb\n\tpU7szqNkEsnx6+nPOj10D3uUhP3RD/ft3QIxfw9PxoDyiNvjCeHcJrv5oJqcAyXAft1o\n\tJjvA==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=P6HtSSn07/iV99bQ0mXQZIICX6sui58LGPkqqs1hxlE=;\n\tb=UDCx5NXA9GwNn+v8oKw9BsXzaJOq5z7ddfbqASOKgrL/328F+aJgXKZz5NK+WmBOZy\n\tfNsZdEHdni8ZWyvutBK5M1B7eUOETRVq+aTY3xeVDxt6c532niNndepo4sr16+yOjr3i\n\tT0iF032UoouuH65VZUihq5RAHKkiJMdTJGbJXssHYRepT2u7vEa3YV+9uIGtLeIn5nj+\n\tu1YeSwHVMiQk4Qs0bu+ulkluBHFNGl098x29wvz88WsoMqfqmxLPO8R1ULPDGcub/Clj\n\tOReVmCUqa34M7nUMj1lJPq9IVosIZ9SG5ju88WhiodEzhDZfasQD+Td51nBiPH8Y6fW2\n\tdWAA==", "X-Gm-Message-State": "AHPjjUjTVQHE81H1v6bujGx84sbOCkSgM3gXx8seW6ZVBfSb+X74IPNI\n\tx2yYISr2YWd9zaZ2", "X-Google-Smtp-Source": "ADKCNb5Li3VW5w130S1/ctTnV7VhqjZXEeEi1/w2Z85R3YfJ28cEpiAGHXplrmjcvM9tTgazbWqYqQ==", "X-Received": "by 10.84.211.35 with SMTP id b32mr8461590pli.256.1504711175445; \n\tWed, 06 Sep 2017 08:19:35 -0700 (PDT)", "From": "Stephen Hemminger <stephen@networkplumber.org>", "X-Google-Original-From": "Stephen Hemminger <sthemmin@microsoft.com>", "To": "kys@microsoft.com, haiyangz@microsoft.com, sthemmin@microsoft.com", "Cc": "devel@linuxdriverproject.org, netdev@vger.kernel.org", "Subject": "[PATCH net-next 1/1] hv_netvsc: fix deadlock on hotplug", "Date": "Wed, 6 Sep 2017 08:19:25 -0700", "Message-Id": "<20170906151925.15221-2-sthemmin@microsoft.com>", "X-Mailer": "git-send-email 2.11.0", "In-Reply-To": "<20170906151925.15221-1-sthemmin@microsoft.com>", "References": "<20170906151925.15221-1-sthemmin@microsoft.com>", "Sender": "netdev-owner@vger.kernel.org", "Precedence": "bulk", "List-ID": "<netdev.vger.kernel.org>", "X-Mailing-List": "netdev@vger.kernel.org" }, "content": "When a virtual device is added dynamically (via host console), then\nthe vmbus sends an offer message for the primary channel. The processing\nof this message for networking causes the network device to then\ninitialize the sub channels.\n\nThe problem is that setting up the sub channels needs to wait until\nthe subsequent subchannel offers have been processed. These offers\ncome in on the same ring buffer and work queue as where the primary\noffer is being processed; leading to a deadlock.\n\nThis did not happen in older kernels, because the sub channel waiting\nlogic was broken (it wasn't really waiting).\n\nThe solution is to do the sub channel setup in its own work queue\ncontext that is scheduled by the primary channel setup; and then\nhappens later.\n\nFixes: 732e49850c5e (\"netvsc: fix race on sub channel creation\")\nReported-by: Dexuan Cui <decui@microsoft.com>\nSigned-off-by: Stephen Hemminger <sthemmin@microsoft.com>\n---\nShould also go to stable, but this version does not apply cleanly\nto 4.13. Have another patch for that.\n\n drivers/net/hyperv/hyperv_net.h | 1 +\n drivers/net/hyperv/netvsc_drv.c | 8 +--\n drivers/net/hyperv/rndis_filter.c | 106 ++++++++++++++++++++++++++------------\n 3 files changed, 74 insertions(+), 41 deletions(-)", "diff": "diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h\nindex ec546da86683..d1df5050adfb 100644\n--- a/drivers/net/hyperv/hyperv_net.h\n+++ b/drivers/net/hyperv/hyperv_net.h\n@@ -172,6 +172,7 @@ struct rndis_device {\n \tstruct list_head req_list;\n \n \tstruct work_struct mcast_work;\n+\tstruct work_struct subchan_work;\n \n \tbool link_state; /* 0 - link up, 1 - link down */\n \ndiff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c\nindex 165ba4b3b423..80f45e0f81c8 100644\n--- a/drivers/net/hyperv/netvsc_drv.c\n+++ b/drivers/net/hyperv/netvsc_drv.c\n@@ -853,10 +853,7 @@ static int netvsc_set_channels(struct net_device *net,\n \trndis_filter_device_remove(dev, nvdev);\n \n \tnvdev = rndis_filter_device_add(dev, &device_info);\n-\tif (!IS_ERR(nvdev)) {\n-\t\tnetif_set_real_num_tx_queues(net, nvdev->num_chn);\n-\t\tnetif_set_real_num_rx_queues(net, nvdev->num_chn);\n-\t} else {\n+\tif (IS_ERR(nvdev)) {\n \t\tret = PTR_ERR(nvdev);\n \t\tdevice_info.num_chn = orig;\n \t\tnvdev = rndis_filter_device_add(dev, &device_info);\n@@ -1954,9 +1951,6 @@ static int netvsc_probe(struct hv_device *dev,\n \t\tNETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;\n \tnet->vlan_features = net->features;\n \n-\tnetif_set_real_num_tx_queues(net, nvdev->num_chn);\n-\tnetif_set_real_num_rx_queues(net, nvdev->num_chn);\n-\n \tnetdev_lockdep_set_classes(net);\n \n \t/* MTU range: 68 - 1500 or 65521 */\ndiff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c\nindex 69c40b8fccc3..c240125eed48 100644\n--- a/drivers/net/hyperv/rndis_filter.c\n+++ b/drivers/net/hyperv/rndis_filter.c\n@@ -33,6 +33,7 @@\n #include \"hyperv_net.h\"\n \n static void rndis_set_multicast(struct work_struct *w);\n+static void rndis_set_subchannel(struct work_struct *w);\n \n #define RNDIS_EXT_LEN PAGE_SIZE\n struct rndis_request {\n@@ -79,6 +80,7 @@ static struct rndis_device *get_rndis_device(void)\n \n \tINIT_LIST_HEAD(&device->req_list);\n \tINIT_WORK(&device->mcast_work, rndis_set_multicast);\n+\tINIT_WORK(&device->subchan_work, rndis_set_subchannel);\n \n \tdevice->state = RNDIS_DEV_UNINITIALIZED;\n \n@@ -1002,6 +1004,7 @@ static int rndis_filter_close_device(struct rndis_device *dev)\n \n \t/* Make sure rndis_set_multicast doesn't re-enable filter! */\n \tcancel_work_sync(&dev->mcast_work);\n+\tcancel_work_sync(&dev->subchan_work);\n \n \tret = rndis_filter_set_packet_filter(dev, 0);\n \tif (ret == -ENODEV)\n@@ -1054,6 +1057,71 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)\n \twake_up(&nvscdev->subchan_open);\n }\n \n+/*\n+ * Open sub-channels after completing the handling of the device probe.\n+ * This breaks overlap of processing the host message for the\n+ * new primary channel with the initialization of sub-channels.\n+ */\n+static void rndis_set_subchannel(struct work_struct *w)\n+{\n+\tstruct rndis_device *rdev\n+\t\t= container_of(w, struct rndis_device, subchan_work);\n+\tstruct net_device *net = rdev->ndev;\n+\tstruct net_device_context *ndev_ctx = netdev_priv(net);\n+\tstruct hv_device *dev = ndev_ctx->device_ctx;\n+\tstruct nvsp_message *init_packet;\n+\tstruct netvsc_device *nvdev;\n+\tint ret = -ENODEV;\n+\n+\tif (!rtnl_trylock()) {\n+\t\tschedule_work(w);\n+\t\treturn;\n+\t}\n+\n+\tnvdev = rtnl_dereference(ndev_ctx->nvdev);\n+\tif (!nvdev)\n+\t\tgoto out;\n+\n+\tinit_packet = &nvdev->channel_init_pkt;\n+\tmemset(init_packet, 0, sizeof(struct nvsp_message));\n+\tinit_packet->hdr.msg_type = NVSP_MSG5_TYPE_SUBCHANNEL;\n+\tinit_packet->msg.v5_msg.subchn_req.op = NVSP_SUBCHANNEL_ALLOCATE;\n+\tinit_packet->msg.v5_msg.subchn_req.num_subchannels =\n+\t\t\t\t\t\tnvdev->num_chn - 1;\n+\tret = vmbus_sendpacket(dev->channel, init_packet,\n+\t\t\t sizeof(struct nvsp_message),\n+\t\t\t (unsigned long)init_packet,\n+\t\t\t VM_PKT_DATA_INBAND,\n+\t\t\t VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);\n+\tif (ret)\n+\t\tgoto out;\n+\n+\twait_for_completion(&nvdev->channel_init_wait);\n+\tif (init_packet->msg.v5_msg.subchn_comp.status != NVSP_STAT_SUCCESS) {\n+\t\tnetdev_err(net, \"sub channel request failed\\n\");\n+\t\tgoto out;\n+\t}\n+\n+\tnvdev->num_chn = 1 +\n+\t\tinit_packet->msg.v5_msg.subchn_comp.num_subchannels;\n+\n+\t/* wait for all sub channels to open */\n+\twait_event(nvdev->subchan_open,\n+\t\t atomic_read(&nvdev->open_chn) == nvdev->num_chn);\n+\n+\t/* ignore failues from setting rss parameters, still have channels */\n+\trndis_filter_set_rss_param(rdev, netvsc_hash_key);\n+out:\n+\tif (ret) {\n+\t\tnvdev->max_chn = 1;\n+\t\tnvdev->num_chn = 1;\n+\t}\n+\n+\tnetif_set_real_num_tx_queues(net, nvdev->num_chn);\n+\tnetif_set_real_num_rx_queues(net, nvdev->num_chn);\n+\trtnl_unlock();\n+}\n+\n struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,\n \t\t\t\t struct netvsc_device_info *device_info)\n {\n@@ -1063,7 +1131,6 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,\n \tstruct rndis_device *rndis_device;\n \tstruct ndis_offload hwcaps;\n \tstruct ndis_offload_params offloads;\n-\tstruct nvsp_message *init_packet;\n \tstruct ndis_recv_scale_cap rsscap;\n \tu32 rsscap_size = sizeof(struct ndis_recv_scale_cap);\n \tunsigned int gso_max_size = GSO_MAX_SIZE;\n@@ -1215,9 +1282,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,\n \t\t\t\t\t\t\tnet_device->num_chn);\n \n \tatomic_set(&net_device->open_chn, 1);\n-\n-\tif (net_device->num_chn == 1)\n-\t\treturn net_device;\n+\tvmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);\n \n \tfor (i = 1; i < net_device->num_chn; i++) {\n \t\tret = netvsc_alloc_recv_comp_ring(net_device, i);\n@@ -1228,38 +1293,11 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,\n \t\t}\n \t}\n \n-\tvmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);\n-\n-\tinit_packet = &net_device->channel_init_pkt;\n-\tmemset(init_packet, 0, sizeof(struct nvsp_message));\n-\tinit_packet->hdr.msg_type = NVSP_MSG5_TYPE_SUBCHANNEL;\n-\tinit_packet->msg.v5_msg.subchn_req.op = NVSP_SUBCHANNEL_ALLOCATE;\n-\tinit_packet->msg.v5_msg.subchn_req.num_subchannels =\n-\t\t\t\t\t\tnet_device->num_chn - 1;\n-\tret = vmbus_sendpacket(dev->channel, init_packet,\n-\t\t\t sizeof(struct nvsp_message),\n-\t\t\t (unsigned long)init_packet,\n-\t\t\t VM_PKT_DATA_INBAND,\n-\t\t\t VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);\n-\tif (ret)\n-\t\tgoto out;\n-\n-\twait_for_completion(&net_device->channel_init_wait);\n-\tif (init_packet->msg.v5_msg.subchn_comp.status != NVSP_STAT_SUCCESS) {\n-\t\tret = -ENODEV;\n-\t\tgoto out;\n-\t}\n-\n-\tnet_device->num_chn = 1 +\n-\t\tinit_packet->msg.v5_msg.subchn_comp.num_subchannels;\n-\n-\t/* wait for all sub channels to open */\n-\twait_event(net_device->subchan_open,\n-\t\t atomic_read(&net_device->open_chn) == net_device->num_chn);\n+\tif (net_device->num_chn > 1)\n+\t\tschedule_work(&rndis_device->subchan_work);\n \n-\t/* ignore failues from setting rss parameters, still have channels */\n-\trndis_filter_set_rss_param(rndis_device, netvsc_hash_key);\n out:\n+\t/* if unavailable, just proceed with one queue */\n \tif (ret) {\n \t\tnet_device->max_chn = 1;\n \t\tnet_device->num_chn = 1;\n", "prefixes": [ "net-next", "1/1" ] }