From nobody Thu Apr 9 21:52:52 2026 Received: from OS0P286CU010.outbound.protection.outlook.com (mail-japanwestazon11021081.outbound.protection.outlook.com [40.107.74.81]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B7182366803; Thu, 5 Mar 2026 15:56:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.74.81 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772726210; cv=fail; b=tUscMY1DLqmlMjARo2ILeeNWwzTdRdj2zohfjySHgvXUMP8/IbQPjtu878LP4j1+R7mUBw/R0xWEF+3g/hnWHqtSBbVX1zvDNUuQdak1vGORBfp9fxcFsvYyq//b3gGS/HqL8CrBHaf/2d9BNF6ijnSOQbl7xkVOvQgGSsrilfA= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772726210; c=relaxed/simple; bh=2SwLOxCcbOcrJlfGSDcWegSZ9mGw3x0lmuxGk5ard68=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: Content-Type:MIME-Version; b=ge4KNx+bFpjlUsUx/0XrH5DhWIn6j6WSwLIOvZq9woPOf2ZvofylDoRX/FmY1TSLUFBHOg47AYgHxzqaaE/ljSp+X2SH5wp4TSLn6qv9euieUxQFdpH6mJfoqU2iNIycEfHCCp7EXf4dlq+zM6naEdZUUw/DBdpwqj4p4PTz/oc= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=valinux.co.jp; spf=pass smtp.mailfrom=valinux.co.jp; dkim=pass (1024-bit key) header.d=valinux.co.jp header.i=@valinux.co.jp header.b=VLAs4tpL; arc=fail smtp.client-ip=40.107.74.81 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=valinux.co.jp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=valinux.co.jp Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=valinux.co.jp header.i=@valinux.co.jp header.b="VLAs4tpL" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=F/8TwtZA09MphEOew+EHi964OyszY7QdCA/CKolaL8TwxhBJyEaOkbKJLRfqclBiLwbDyx69F6Ai45Z5/HMp2MlIsIJDCfMcz9kGx05Z2NlVzS5XcANED1TqpehpWMHu2qt9bJjDuOIfH75L6ipw9v9G9jPbLycCzYOVStl+Adon+ArcDdezhFfKOzWJdHThiFEimCU42GhX1RNLvZspBCCPF4pnNO/t1IWY+mRLgi7NmanpP3/MF0HB3eP3WnxWctGW454Zvq8/L53mY3ulrmK3pIo0CoNiU9U/iFCZFxiq5aylHqQhwWbGpdcxkHoG3BDd1yrRiuyufLfgXIOGtg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=o+LRddvNKZhICXhZVakAF/zDQqryIGwJHp6IE6sTRtM=; b=dxrKegGE0hKYM8jr+4uV6HKjjO+m6YIoipsNwQIz/LBBBQ7Dvd97m/4Sjrfh9lHS2OS9E1grnpasAKhsUw0hJK1dDuCdpYG2fUkXiE4RudM1FnWsvVBszGFctGS++WNCr3eo6mp7H4h2x+SSy2/9BFVPB300in3sk82Hz/YGFEsbhOheRoamXzUETXD4fCTlAjnwcP3rOjMnwwf/dA/6RDVijgL7uAfiqkxPM3GZnkmTnSU5fyOgFAbkhqtkFVV1ITGOyWJ1F8WKBSZIU8CNbFKzi30HEK7Wo5H4oIXyxmdcc4buXbwebkX9Sn157Mz0uNncBrNjDaa6PA6I+X0ERg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=valinux.co.jp; dmarc=pass action=none header.from=valinux.co.jp; dkim=pass header.d=valinux.co.jp; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=valinux.co.jp; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=o+LRddvNKZhICXhZVakAF/zDQqryIGwJHp6IE6sTRtM=; b=VLAs4tpLR3jrS4OX9mPKmsnCxterrvyByzIBIOgc0mOxm2utvyEvsbhpwU30egzVBH8kDEl5+hIQFvYDZL981Bbfmnp2S+lR9gunkyBGka0ZEHCI49b8TKGjxJDRtLH23xrHtvPlh+4wjE/SziShXvnMpFnzr6Bfep+AlqILeI0= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp; Received: from OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM (2603:1096:604:468::22) by TY3P286MB2756.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:23e::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9678.18; Thu, 5 Mar 2026 15:56:44 +0000 Received: from OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM ([fe80::b7ab:6af2:d18e:4a71]) by OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM ([fe80::b7ab:6af2:d18e:4a71%3]) with mapi id 15.20.9678.017; Thu, 5 Mar 2026 15:56:44 +0000 From: Koichiro Den To: Jon Mason , Dave Jiang , Allen Hubbe , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: ntb@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 1/4] net: ntb_netdev: Introduce per-queue context Date: Fri, 6 Mar 2026 00:56:36 +0900 Message-ID: <20260305155639.1885517-2-den@valinux.co.jp> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260305155639.1885517-1-den@valinux.co.jp> References: <20260305155639.1885517-1-den@valinux.co.jp> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TY4P301CA0091.JPNP301.PROD.OUTLOOK.COM (2603:1096:405:37a::14) To OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM (2603:1096:604:468::22) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: OSOP286MB7730:EE_|TY3P286MB2756:EE_ X-MS-Office365-Filtering-Correlation-Id: b4342f9a-7e89-4751-a75d-08de7acfcc7a X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|376014|7416014|366016|1800799024; X-Microsoft-Antispam-Message-Info: 8XFu/um0jN7N1T3BgizsRbR/pKYyQ12Y2YrHa3X6osknorgHWKyS2dK1oPH8Y8omaGxQTgKRxHqm+Pq9LQkGQKBLN0ujb3PZ0MIR5TCRUXP7O0Rlg4RYw4121ohtf/b47bm8W/s7QAfBpDpNoL1IYr0CP0O9zSk2sOBj6C3bUxJU5NDHwK85yBQecqAD4YtmzC541LRzucQowx84QTPzZvLdEzbje9Pt8F4NaL1asqqScuT3xtB+wOZ0u2xyjMoJhI82NOp+329dWgDfdAyfxvQ1TDOOmk5QM45Ozy/PAFIR+k8ItOmS9fwsXcJcv/xSb3ppZ/vcqRclVSz4NKJlxR5U1rAeUvKcHP5+fDiBDWMRdj6jax/TOpREkgFnkELwAoBZGx4/sLQtwpMQXnkhJoIuaEnYJjlWHZEagpY52q+XzWd6y6a4x254HWY5v31890ECgMwQIYWqqTaiI6P75PkLUAXSxK/4imREKNaCD95Jc62kQlwxWQK1/RvQwo4ZL7VRnapea+b/RWP7WR6gdcNTNc7rcCs08Ub19OnfbmLzOTDVjdKC9NezCNwNi0tiGq3d56VzHZCJhvgP0b6wyBSaUNND2bcKBfM0cKFGzOgc6pl93V57EM92AOjlg7TEF3p/qdIfLm+CQ183IvKpP/N0WvxejSSPGh3prHHp1LXxTkrT2krbHCp/p5KYq9xwqSLvI4GFXwNGVUnQZ4FJlK7J+yuEY16a5D3uJ0DiAHs= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(376014)(7416014)(366016)(1800799024);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?ASBpR1VF0QszoF6XGJvk06dzp15qCxoQkTqTUrHGkA+SrxztMzzyqL9qLTsX?= =?us-ascii?Q?LbB7Y/7PZ0MoUGUd8btNvXjEW6+1oHE9ZkGLaq3/eXRk/2+7yKRch7b5N/EQ?= =?us-ascii?Q?WWZbYOKtJlfyN4CYmPcRa0k6dwLvAYtWPND1Oov8MTLVnRBvEJr8VpsKfFKj?= =?us-ascii?Q?a+jpeKQmtKFC1M1F7Tz+urlMjdmSt3YmbCB6ODY6lgAzxfEKzQ+jBtCRqG3q?= =?us-ascii?Q?UoQl5wOoNyQAlb3/nXnHX3mpjNbhElwLRd7e6R0pqDr9s7zmZ4jYrZv1U3MR?= =?us-ascii?Q?NfzQTnXs9hciXN/Nihk2K5b2KLy1d+zNCpMRiUcLf9s4dPT3ZFHSXR3pN33h?= =?us-ascii?Q?8jI9yZvIqbAh2ppPqRR0Xev6TVa+2gt1HPkGDHWixAd+CJzYxPClZ2MwH+kd?= =?us-ascii?Q?VwCcFKy/cpJBsjx8vk0AOOHuIfoIOsr8zhbXYXWoyFHloT1PoZd93PJEa4Tm?= =?us-ascii?Q?zoYiCwPZKaDfUsJAzwSB+J8iX/3gMBL13RPhHvP1/G/NuaNUiczV1WBM+tmr?= =?us-ascii?Q?Cgz/GhLsstSWqTYWbsXgt9QvqNbLgUz2z5esbzlZyzD/2nwGG6Btq8wIO1Vj?= =?us-ascii?Q?wbKjsvHim7vdOTM2Jq8aQvFgU1BrBd8SsJr5Rn3qiTd/SITPz8jkqkivGlAT?= =?us-ascii?Q?O9X5TiX0ymEpcVdLf0mx+lNzzsehXHno5DK54+Aod8Qo4Nr+4K3xtuI1tSgb?= =?us-ascii?Q?HQUbN/UtHNzrM6h9Aa5HxKAaMVdTzlYZjk7up0gY+cDmq4w+ZJoJaqnN0f1K?= =?us-ascii?Q?cGe1VVticAhzSvRtiA49hgdefByCQc23PPAs0dyoh+fMcGSoJS7YqEnhHsVJ?= =?us-ascii?Q?vTj4iSnGNPmz8jXnoN4F/asvDuahhcfBD4Y2rAoxGQ8Uq9AJ+HMoiweEovEX?= =?us-ascii?Q?M7m9kCcKKqX8omIraKyMcUc941Pkwe5dp2Q7bhCKIOeQXJS55deIpGwDwq/h?= =?us-ascii?Q?VFxImh1dffPwzEwsPddqCmvF3+99ntuFFgM/UqHijdWMrO3DxmTKoSeCHSW3?= =?us-ascii?Q?eOnhzBtcMSCPuwE6MDwCoX4m4iEOtwTMWQZxEiDdqu2+KXte/YEp47zkicDC?= =?us-ascii?Q?DlU+pEkGhm+R60KLeQ6xBDb+UgOTMQtwgTCGrs0R7NSpO6q2DreZrQhY2jyL?= =?us-ascii?Q?U18WbWT59ViRwqQhq1+danPd8hKkTEiocvtzWdsRUULRJLwwYFHtTFlS3hB6?= =?us-ascii?Q?fdHqEdTn5n22j90Tylxho118CK2UjPlTTum9MU+WB8gDLHeEGonqWdjhP5qX?= =?us-ascii?Q?uThk/PE0gmuuEZU/n+qn9fNa93xWx2kFcYpj7DSDAf76Jh90EUMTvszw9LR/?= =?us-ascii?Q?Ws4L41TW14CHrs36osPd/wBu4SqhxTko4UBCdjPTIdBpT5B/x8MbImu7aG+T?= =?us-ascii?Q?qsC+w49RWOCi1NW5J8IYhl+xlERV2ZqT9KIJSyEZobB+121zt1aJwJpbhlXZ?= =?us-ascii?Q?ucRc9Ewo53eUH41OzSy92Fq+EN78NCNn9hZ09P5g7QCU6PUueJ5gr1DNxr9v?= =?us-ascii?Q?/+ZvV5c26gvs09zx4cj6oWHOC4h06ItkDSn/cNQQouNDl4D0zF7BFe0USHwi?= =?us-ascii?Q?LoeBoaDkD5CRg05KF9DlYPgx39foEE+36RP4nR3QNOqNU6rUOsUjjj3cbqpD?= =?us-ascii?Q?10u7rn3oFXf2hgPvd3YVmCb3/nCkxEcnkGaTW7hUvEYW2nmBX+q4obrTnRcY?= =?us-ascii?Q?gfzZDsSEimksjKO6vNjEtBhfYK54/LjwXSqAYdiSO2IwPgbuAKkGuk1uITiQ?= =?us-ascii?Q?4mVWUub7Ed67c8cZi+/Yx1EhAiHsKWk5+lhiLFNdCtBe/kmaAF8V?= X-OriginatorOrg: valinux.co.jp X-MS-Exchange-CrossTenant-Network-Message-Id: b4342f9a-7e89-4751-a75d-08de7acfcc7a X-MS-Exchange-CrossTenant-AuthSource: OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Mar 2026 15:56:44.1229 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 7a57bee8-f73d-4c5f-a4f7-d72c91c8c111 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: p0iZUMx9GrKdxIYfofFRcLR5xqhHspXOBoxNp9tz6IESjuXBDc73GHgau0xNarkWTdidrygB+XpGynPWXqQRmA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: TY3P286MB2756 Content-Type: text/plain; charset="utf-8" Prepare ntb_netdev for multi-queue operation by moving queue-pair state out of struct ntb_netdev. Introduce struct ntb_netdev_queue to carry the ntb_transport_qp pointer, the per-QP TX timer and queue id. Pass this object as the callback context and convert the RX/TX handlers and link event path accordingly. The probe path allocates a fixed upper bound for netdev queues while instantiating only a single ntb_transport queue pair, preserving the previous behavior. Also store client_dev for future queue pair creation/removal via the ntb_transport API. Signed-off-by: Koichiro Den --- Changes in v3: - Drop redundant defensive checks in start_xmit(). - Use kzalloc_objs() for the queue array. - Use the local qp argument where applicable. - Make variable declarations follow reverse Christmas tree style. - Remove double blank line. drivers/net/ntb_netdev.c | 277 ++++++++++++++++++++++++++------------- 1 file changed, 188 insertions(+), 89 deletions(-) diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c index fbeae05817e9..4b65e938d549 100644 --- a/drivers/net/ntb_netdev.c +++ b/drivers/net/ntb_netdev.c @@ -53,6 +53,7 @@ #include #include #include +#include =20 #define NTB_NETDEV_VER "0.7" =20 @@ -70,11 +71,24 @@ static unsigned int tx_start =3D 10; /* Number of descriptors still available before stop upper layer tx */ static unsigned int tx_stop =3D 5; =20 -struct ntb_netdev { - struct pci_dev *pdev; - struct net_device *ndev; +#define NTB_NETDEV_MAX_QUEUES 64 +#define NTB_NETDEV_DEFAULT_QUEUES 1 + +struct ntb_netdev; + +struct ntb_netdev_queue { + struct ntb_netdev *ntdev; struct ntb_transport_qp *qp; struct timer_list tx_timer; + u16 qid; +}; + +struct ntb_netdev { + struct pci_dev *pdev; + struct device *client_dev; + struct net_device *ndev; + unsigned int num_queues; + struct ntb_netdev_queue *queues; }; =20 #define NTB_TX_TIMEOUT_MS 1000 @@ -82,14 +96,17 @@ struct ntb_netdev { =20 static void ntb_netdev_event_handler(void *data, int link_is_up) { - struct net_device *ndev =3D data; - struct ntb_netdev *dev =3D netdev_priv(ndev); + struct ntb_netdev_queue *q =3D data; + struct ntb_netdev *dev =3D q->ntdev; + struct net_device *ndev; =20 - netdev_dbg(ndev, "Event %x, Link %x\n", link_is_up, - ntb_transport_link_query(dev->qp)); + ndev =3D dev->ndev; + + netdev_dbg(ndev, "Event %x, Link %x, qp %u\n", link_is_up, + ntb_transport_link_query(q->qp), q->qid); =20 if (link_is_up) { - if (ntb_transport_link_query(dev->qp)) + if (ntb_transport_link_query(q->qp)) netif_carrier_on(ndev); } else { netif_carrier_off(ndev); @@ -99,10 +116,13 @@ static void ntb_netdev_event_handler(void *data, int l= ink_is_up) static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_da= ta, void *data, int len) { - struct net_device *ndev =3D qp_data; + struct ntb_netdev_queue *q =3D qp_data; + struct ntb_netdev *dev =3D q->ntdev; + struct net_device *ndev; struct sk_buff *skb; int rc; =20 + ndev =3D dev->ndev; skb =3D data; if (!skb) return; @@ -118,6 +138,7 @@ static void ntb_netdev_rx_handler(struct ntb_transport_= qp *qp, void *qp_data, skb_put(skb, len); skb->protocol =3D eth_type_trans(skb, ndev); skb->ip_summed =3D CHECKSUM_NONE; + skb_record_rx_queue(skb, q->qid); =20 if (netif_rx(skb) =3D=3D NET_RX_DROP) { ndev->stats.rx_errors++; @@ -144,42 +165,43 @@ static void ntb_netdev_rx_handler(struct ntb_transpor= t_qp *qp, void *qp_data, } =20 static int __ntb_netdev_maybe_stop_tx(struct net_device *netdev, - struct ntb_transport_qp *qp, int size) + struct ntb_netdev_queue *q, int size) { - struct ntb_netdev *dev =3D netdev_priv(netdev); + netif_stop_subqueue(netdev, q->qid); =20 - netif_stop_queue(netdev); /* Make sure to see the latest value of ntb_transport_tx_free_entry() * since the queue was last started. */ smp_mb(); =20 - if (likely(ntb_transport_tx_free_entry(qp) < size)) { - mod_timer(&dev->tx_timer, jiffies + usecs_to_jiffies(tx_time)); + if (likely(ntb_transport_tx_free_entry(q->qp) < size)) { + mod_timer(&q->tx_timer, jiffies + usecs_to_jiffies(tx_time)); return -EBUSY; } =20 - netif_start_queue(netdev); + netif_start_subqueue(netdev, q->qid); return 0; } =20 static int ntb_netdev_maybe_stop_tx(struct net_device *ndev, - struct ntb_transport_qp *qp, int size) + struct ntb_netdev_queue *q, int size) { - if (netif_queue_stopped(ndev) || - (ntb_transport_tx_free_entry(qp) >=3D size)) + if (__netif_subqueue_stopped(ndev, q->qid) || + (ntb_transport_tx_free_entry(q->qp) >=3D size)) return 0; =20 - return __ntb_netdev_maybe_stop_tx(ndev, qp, size); + return __ntb_netdev_maybe_stop_tx(ndev, q, size); } =20 static void ntb_netdev_tx_handler(struct ntb_transport_qp *qp, void *qp_da= ta, void *data, int len) { - struct net_device *ndev =3D qp_data; + struct ntb_netdev_queue *q =3D qp_data; + struct ntb_netdev *dev =3D q->ntdev; + struct net_device *ndev; struct sk_buff *skb; - struct ntb_netdev *dev =3D netdev_priv(ndev); =20 + ndev =3D dev->ndev; skb =3D data; if (!skb || !ndev) return; @@ -194,13 +216,13 @@ static void ntb_netdev_tx_handler(struct ntb_transpor= t_qp *qp, void *qp_data, =20 dev_kfree_skb_any(skb); =20 - if (ntb_transport_tx_free_entry(dev->qp) >=3D tx_start) { + if (ntb_transport_tx_free_entry(qp) >=3D tx_start) { /* Make sure anybody stopping the queue after this sees the new * value of ntb_transport_tx_free_entry() */ smp_mb(); - if (netif_queue_stopped(ndev)) - netif_wake_queue(ndev); + if (__netif_subqueue_stopped(ndev, q->qid)) + netif_wake_subqueue(ndev, q->qid); } } =20 @@ -208,16 +230,20 @@ static netdev_tx_t ntb_netdev_start_xmit(struct sk_bu= ff *skb, struct net_device *ndev) { struct ntb_netdev *dev =3D netdev_priv(ndev); + u16 qid =3D skb_get_queue_mapping(skb); + struct ntb_netdev_queue *q; int rc; =20 - ntb_netdev_maybe_stop_tx(ndev, dev->qp, tx_stop); + q =3D &dev->queues[qid]; =20 - rc =3D ntb_transport_tx_enqueue(dev->qp, skb, skb->data, skb->len); + ntb_netdev_maybe_stop_tx(ndev, q, tx_stop); + + rc =3D ntb_transport_tx_enqueue(q->qp, skb, skb->data, skb->len); if (rc) goto err; =20 /* check for next submit */ - ntb_netdev_maybe_stop_tx(ndev, dev->qp, tx_stop); + ntb_netdev_maybe_stop_tx(ndev, q, tx_stop); =20 return NETDEV_TX_OK; =20 @@ -229,80 +255,104 @@ static netdev_tx_t ntb_netdev_start_xmit(struct sk_b= uff *skb, =20 static void ntb_netdev_tx_timer(struct timer_list *t) { - struct ntb_netdev *dev =3D timer_container_of(dev, t, tx_timer); - struct net_device *ndev =3D dev->ndev; + struct ntb_netdev_queue *q =3D timer_container_of(q, t, tx_timer); + struct ntb_netdev *dev =3D q->ntdev; + struct net_device *ndev; =20 - if (ntb_transport_tx_free_entry(dev->qp) < tx_stop) { - mod_timer(&dev->tx_timer, jiffies + usecs_to_jiffies(tx_time)); + ndev =3D dev->ndev; + + if (ntb_transport_tx_free_entry(q->qp) < tx_stop) { + mod_timer(&q->tx_timer, jiffies + usecs_to_jiffies(tx_time)); } else { /* Make sure anybody stopping the queue after this sees the new * value of ntb_transport_tx_free_entry() */ smp_mb(); - if (netif_queue_stopped(ndev)) - netif_wake_queue(ndev); + if (__netif_subqueue_stopped(ndev, q->qid)) + netif_wake_subqueue(ndev, q->qid); } } =20 static int ntb_netdev_open(struct net_device *ndev) { struct ntb_netdev *dev =3D netdev_priv(ndev); + struct ntb_netdev_queue *queue; struct sk_buff *skb; - int rc, i, len; + int rc =3D 0, i, len; + unsigned int q; =20 - /* Add some empty rx bufs */ - for (i =3D 0; i < NTB_RXQ_SIZE; i++) { - skb =3D netdev_alloc_skb(ndev, ndev->mtu + ETH_HLEN); - if (!skb) { - rc =3D -ENOMEM; - goto err; - } + /* Add some empty rx bufs for each queue */ + for (q =3D 0; q < dev->num_queues; q++) { + queue =3D &dev->queues[q]; + + for (i =3D 0; i < NTB_RXQ_SIZE; i++) { + skb =3D netdev_alloc_skb(ndev, ndev->mtu + ETH_HLEN); + if (!skb) { + rc =3D -ENOMEM; + goto err; + } =20 - rc =3D ntb_transport_rx_enqueue(dev->qp, skb, skb->data, - ndev->mtu + ETH_HLEN); - if (rc) { - dev_kfree_skb(skb); - goto err; + rc =3D ntb_transport_rx_enqueue(queue->qp, skb, skb->data, + ndev->mtu + ETH_HLEN); + if (rc) { + dev_kfree_skb(skb); + goto err; + } } + + timer_setup(&queue->tx_timer, ntb_netdev_tx_timer, 0); } =20 - timer_setup(&dev->tx_timer, ntb_netdev_tx_timer, 0); - netif_carrier_off(ndev); - ntb_transport_link_up(dev->qp); + + for (q =3D 0; q < dev->num_queues; q++) + ntb_transport_link_up(dev->queues[q].qp); + netif_start_queue(ndev); =20 return 0; =20 err: - while ((skb =3D ntb_transport_rx_remove(dev->qp, &len))) - dev_kfree_skb(skb); + for (q =3D 0; q < dev->num_queues; q++) { + queue =3D &dev->queues[q]; + + while ((skb =3D ntb_transport_rx_remove(queue->qp, &len))) + dev_kfree_skb(skb); + } return rc; } =20 static int ntb_netdev_close(struct net_device *ndev) { struct ntb_netdev *dev =3D netdev_priv(ndev); + struct ntb_netdev_queue *queue; struct sk_buff *skb; + unsigned int q; int len; =20 - ntb_transport_link_down(dev->qp); =20 - while ((skb =3D ntb_transport_rx_remove(dev->qp, &len))) - dev_kfree_skb(skb); + for (q =3D 0; q < dev->num_queues; q++) { + queue =3D &dev->queues[q]; =20 - timer_delete_sync(&dev->tx_timer); + ntb_transport_link_down(queue->qp); =20 + while ((skb =3D ntb_transport_rx_remove(queue->qp, &len))) + dev_kfree_skb(skb); + + timer_delete_sync(&queue->tx_timer); + } return 0; } =20 static int ntb_netdev_change_mtu(struct net_device *ndev, int new_mtu) { struct ntb_netdev *dev =3D netdev_priv(ndev); + struct ntb_netdev_queue *queue; struct sk_buff *skb; - int len, rc; + unsigned int q, i; + int len, rc =3D 0; =20 - if (new_mtu > ntb_transport_max_size(dev->qp) - ETH_HLEN) + if (new_mtu > ntb_transport_max_size(dev->queues[0].qp) - ETH_HLEN) return -EINVAL; =20 if (!netif_running(ndev)) { @@ -311,41 +361,54 @@ static int ntb_netdev_change_mtu(struct net_device *n= dev, int new_mtu) } =20 /* Bring down the link and dispose of posted rx entries */ - ntb_transport_link_down(dev->qp); + for (q =3D 0; q < dev->num_queues; q++) + ntb_transport_link_down(dev->queues[q].qp); =20 if (ndev->mtu < new_mtu) { - int i; + for (q =3D 0; q < dev->num_queues; q++) { + queue =3D &dev->queues[q]; =20 - for (i =3D 0; (skb =3D ntb_transport_rx_remove(dev->qp, &len)); i++) - dev_kfree_skb(skb); - - for (; i; i--) { - skb =3D netdev_alloc_skb(ndev, new_mtu + ETH_HLEN); - if (!skb) { - rc =3D -ENOMEM; - goto err; - } - - rc =3D ntb_transport_rx_enqueue(dev->qp, skb, skb->data, - new_mtu + ETH_HLEN); - if (rc) { + for (i =3D 0; + (skb =3D ntb_transport_rx_remove(queue->qp, &len)); + i++) dev_kfree_skb(skb); - goto err; + + for (; i; i--) { + skb =3D netdev_alloc_skb(ndev, + new_mtu + ETH_HLEN); + if (!skb) { + rc =3D -ENOMEM; + goto err; + } + + rc =3D ntb_transport_rx_enqueue(queue->qp, skb, + skb->data, + new_mtu + + ETH_HLEN); + if (rc) { + dev_kfree_skb(skb); + goto err; + } } } } =20 WRITE_ONCE(ndev->mtu, new_mtu); =20 - ntb_transport_link_up(dev->qp); + for (q =3D 0; q < dev->num_queues; q++) + ntb_transport_link_up(dev->queues[q].qp); =20 return 0; =20 err: - ntb_transport_link_down(dev->qp); + for (q =3D 0; q < dev->num_queues; q++) { + struct ntb_netdev_queue *queue =3D &dev->queues[q]; =20 - while ((skb =3D ntb_transport_rx_remove(dev->qp, &len))) - dev_kfree_skb(skb); + ntb_transport_link_down(queue->qp); + + while ((skb =3D ntb_transport_rx_remove(queue->qp, &len))) + dev_kfree_skb(skb); + } =20 netdev_err(ndev, "Error changing MTU, device inoperable\n"); return rc; @@ -404,6 +467,7 @@ static int ntb_netdev_probe(struct device *client_dev) struct net_device *ndev; struct pci_dev *pdev; struct ntb_netdev *dev; + unsigned int q; int rc; =20 ntb =3D dev_ntb(client_dev->parent); @@ -411,7 +475,7 @@ static int ntb_netdev_probe(struct device *client_dev) if (!pdev) return -ENODEV; =20 - ndev =3D alloc_etherdev(sizeof(*dev)); + ndev =3D alloc_etherdev_mq(sizeof(*dev), NTB_NETDEV_MAX_QUEUES); if (!ndev) return -ENOMEM; =20 @@ -420,6 +484,16 @@ static int ntb_netdev_probe(struct device *client_dev) dev =3D netdev_priv(ndev); dev->ndev =3D ndev; dev->pdev =3D pdev; + dev->client_dev =3D client_dev; + dev->num_queues =3D 0; + + dev->queues =3D kzalloc_objs(*dev->queues, NTB_NETDEV_MAX_QUEUES, + GFP_KERNEL); + if (!dev->queues) { + rc =3D -ENOMEM; + goto err_free_netdev; + } + ndev->features =3D NETIF_F_HIGHDMA; =20 ndev->priv_flags |=3D IFF_LIVE_ADDR_CHANGE; @@ -436,26 +510,47 @@ static int ntb_netdev_probe(struct device *client_dev) ndev->min_mtu =3D 0; ndev->max_mtu =3D ETH_MAX_MTU; =20 - dev->qp =3D ntb_transport_create_queue(ndev, client_dev, - &ntb_netdev_handlers); - if (!dev->qp) { + for (q =3D 0; q < NTB_NETDEV_DEFAULT_QUEUES; q++) { + struct ntb_netdev_queue *queue =3D &dev->queues[q]; + + queue->ntdev =3D dev; + queue->qid =3D q; + queue->qp =3D ntb_transport_create_queue(queue, client_dev, + &ntb_netdev_handlers); + if (!queue->qp) + break; + + dev->num_queues++; + } + + if (!dev->num_queues) { rc =3D -EIO; - goto err; + goto err_free_queues; } =20 - ndev->mtu =3D ntb_transport_max_size(dev->qp) - ETH_HLEN; + rc =3D netif_set_real_num_queues(ndev, dev->num_queues, dev->num_queues); + if (rc) + goto err_free_qps; + + ndev->mtu =3D ntb_transport_max_size(dev->queues[0].qp) - ETH_HLEN; =20 rc =3D register_netdev(ndev); if (rc) - goto err1; + goto err_free_qps; =20 dev_set_drvdata(client_dev, ndev); - dev_info(&pdev->dev, "%s created\n", ndev->name); + dev_info(&pdev->dev, "%s created with %u queue pairs\n", + ndev->name, dev->num_queues); return 0; =20 -err1: - ntb_transport_free_queue(dev->qp); -err: +err_free_qps: + for (q =3D 0; q < dev->num_queues; q++) + ntb_transport_free_queue(dev->queues[q].qp); + +err_free_queues: + kfree(dev->queues); + +err_free_netdev: free_netdev(ndev); return rc; } @@ -464,9 +559,13 @@ static void ntb_netdev_remove(struct device *client_de= v) { struct net_device *ndev =3D dev_get_drvdata(client_dev); struct ntb_netdev *dev =3D netdev_priv(ndev); + unsigned int q; =20 unregister_netdev(ndev); - ntb_transport_free_queue(dev->qp); + for (q =3D 0; q < dev->num_queues; q++) + ntb_transport_free_queue(dev->queues[q].qp); + + kfree(dev->queues); free_netdev(ndev); } =20 --=20 2.51.0 From nobody Thu Apr 9 21:52:52 2026 Received: from OS0P286CU010.outbound.protection.outlook.com (mail-japanwestazon11021081.outbound.protection.outlook.com [40.107.74.81]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 31C753CC9E1; Thu, 5 Mar 2026 15:56:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.74.81 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772726213; cv=fail; b=Y191zLulA0pmqMDoLKotofv9TrMmcKFV3t8dUTpSHLag0IngtGACrfIadeMnMrXE8Zr8lnOpDM3woDSi2HVxFqw671AP7GJOldXCfDbddfA8NfpOp/IRYqiHR2rS34YKYREoPv9hG15kTp1ouhWEaVpBdF3j0fb1r4QzT6fGknY= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772726213; c=relaxed/simple; bh=krrV6ZYfVKk45vHdtQPRvBLAbouZ59ifnsi8MdZoZ6g=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: Content-Type:MIME-Version; b=Oh/pLqqTg6TD1dHaeNWEQzvRSyUNaJjaDm3hUPre6cUQFoSs630XFt6CCd+mls46NYOLhkBkdBW3JT8OEvBAxkCtlxCN0Fw4+R/RfGDIAR42Qx0CGx08BSAxjzMd0EDiZU+UpEqzp5tXSTXZ3XG4oA7vKUQ5IF5Wh5RQ1f1Hn5I= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=valinux.co.jp; spf=pass smtp.mailfrom=valinux.co.jp; dkim=pass (1024-bit key) header.d=valinux.co.jp header.i=@valinux.co.jp header.b=HU8DrQef; arc=fail smtp.client-ip=40.107.74.81 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=valinux.co.jp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=valinux.co.jp Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=valinux.co.jp header.i=@valinux.co.jp header.b="HU8DrQef" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=nN0yZgNOson9h4+2/NWiolLLUS0/1kDq/FV1fRViEED5UeLjxjZ+02NRcafuAxUVmPkffPQAW9DQkfwfaqY0fcdewWDDvDv1o+8HAh52HEofOuAtOFt/8tqtm/i8xInql4r9cUNkct4krajzybvNXLi7eSOhe24j9kkNAqDm6RaqHTiiG8INElso/3NYRGrmoo4S42eB4nETcI42QzzxzjzxjrwEJ3/8gfh5QbiFVkRydj1Yg7oCHw/3qHikLq/ly0QfCxZpkDeBhOFj42dX8UecE6ZsAKklb06Vye1bGHoMSAaAWhHxevpDOfJluBQXI2QTqKAhqfVjxMYjRBSk7A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=m0FAvOE7qZ9togXTMdRH0hDHKJIQFkfDNABzoGVYCwY=; b=m0ANyHquXw0ZT2YWfhLyzL3y4bOldA9qM04Uyp0+o6MoH3epLI7Pips9y2XwKI1rAfIyTQoUsOh8Oo7+DYcgakzQFolNk9jUBg8nmUXOzS8DuFXJjtML9YuLnMZ+XktuP/q7QXlYa487vwfp5cAV5Q9liP2uvx4cZSPfSWBG2TsHx1/3FvkDfrduocoyIRuVdJwVk1MISD7HURz/GoCvqUgQk/gQqKO9WnYM0dgktFcftTktfn59mKJGzYBdpr/lmaM1O8YGlq7BHvKpTupIsqmRdWY7vJNROudBbt1NF0uHgyyvsAizaj6usFWBs5zkBypZIY2Ug2U0rnzgE3zcig== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=valinux.co.jp; dmarc=pass action=none header.from=valinux.co.jp; dkim=pass header.d=valinux.co.jp; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=valinux.co.jp; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=m0FAvOE7qZ9togXTMdRH0hDHKJIQFkfDNABzoGVYCwY=; b=HU8DrQefFy3/MEynJ6bZcFiXDiQmzlJBcVHuRKWfPDC6Gkb1NiYdJsPYqzDFb5ADY3e3WgP+cvdNxUCtIGrmmUBLfW7xJ+QtDNuwRI9Ely2xnGApF+HEP9sLzKJvgnIMkuG5XCNB/ggMXZfhaU46gI+1vc9vkZU1SEr3ytIuNVI= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp; Received: from OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM (2603:1096:604:468::22) by TY3P286MB2756.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:23e::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9678.18; Thu, 5 Mar 2026 15:56:45 +0000 Received: from OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM ([fe80::b7ab:6af2:d18e:4a71]) by OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM ([fe80::b7ab:6af2:d18e:4a71%3]) with mapi id 15.20.9678.017; Thu, 5 Mar 2026 15:56:45 +0000 From: Koichiro Den To: Jon Mason , Dave Jiang , Allen Hubbe , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: ntb@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 2/4] net: ntb_netdev: Gate subqueue stop/wake by transport link Date: Fri, 6 Mar 2026 00:56:37 +0900 Message-ID: <20260305155639.1885517-3-den@valinux.co.jp> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260305155639.1885517-1-den@valinux.co.jp> References: <20260305155639.1885517-1-den@valinux.co.jp> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYXPR01CA0043.jpnprd01.prod.outlook.com (2603:1096:403:a::13) To OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM (2603:1096:604:468::22) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: OSOP286MB7730:EE_|TY3P286MB2756:EE_ X-MS-Office365-Filtering-Correlation-Id: b2ae41c1-d177-4d00-09ae-08de7acfcd56 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|376014|7416014|366016|1800799024; X-Microsoft-Antispam-Message-Info: XUM0/Op1YYdkdNOHNWf3j/qknEccK/rJXz5WCj7q62b1rk16iYUwwqgtjBrATMCU6kmdyHxIBRjcWiVuZgjWFT85O5aTQdKARSbj3JqBYoK9uhTYlrvvZUMBrCkV7HqyYMXJW/ipl5+o52IurAZxyLudtAr9ggQs0lLNdZZS6TiWeecNx1NY5Bfz/1q6Evb2s2fWKK37xrgTcxly0odmQRCAsQwcrSux2aW5FGejmbzS349LujazBvHk2W78mv7Yr6ceUDvCBWqpB/jDCvfEppLWG82WvN23uV8e3H7OXLgg/52HU1qsh2CsrvgpTNKib+Fv5M224MbuJMd/sOnwWAybKre99Y1SmHexYP3EA+mIL3nDbkxue5Jt3NY4cllUfA1etpMcgdeDZH7LuNNQoxzAThXUwiNlWCfmh9u7Btf42zzwTzqf7stdSbkX9Q2MyRT4rie+bgep1P3Q8xS5EMz5oudVne51ixyHVbLpDFtIKF+DWcm1GBlauuzn/BfFdkLX6cZhR4gNQNXhZ64Mjo4bjpnXkDcgZkwQTYuq8RWz0rxGCkRgN93/IA1x3+aNRKOYSsLhze83dYSQQO8Q9p94S/gTq69zYPwLvqD9bUH/MNZxEKZ6XHTR0CLejEeRHKP3not/sU4aMyssCLKDi43ZVz9GErQkI5QLFlItg8USsvhhVdjBJ+IftM30+CCfR5GKI+PpGZfdBnj77vVCpH6fAMAM2q4zHJg5/7C4Qr0= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(376014)(7416014)(366016)(1800799024);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?t0qc5ZguckjDrLO2u7DwGtlBn/s7rIVDkQbrTHufoHBTuhfx/V2OYSfmdaep?= =?us-ascii?Q?UY9y5gwCEwF8ZDbeEuD7mH9jNy2uS9bOP7fky+f9iROSfTQ7V3i5oPhjbLTU?= =?us-ascii?Q?oM0HUbEDChrQyBA7zmGTBhppKWo+FPJTPj9y1R/YtSNsOG42E9/KBNvqrGlm?= =?us-ascii?Q?G+33wCkzPwHqLw4dsqNEiTCkvs/DEGnqZ1MsS0iAXvTPWzVM0tbyJ9GdsmCE?= =?us-ascii?Q?pT95VEbyY1uZQ4reho1BtSGUOpUmSp8MiRkOKqJBv9Bt+RVfnusPwV6xAS3P?= =?us-ascii?Q?uL4Y+vyvqIRvDbyZMebxNFMQxoNNW1ljdx2aHjnHnkUt8JV8uUGxL0mxMCO/?= =?us-ascii?Q?jTZOwfmCdNasDjm4fRzQcwv0Y7ZO+xJsrQaTCzfBypu6zbW6Hq35Mb3DeiXx?= =?us-ascii?Q?ZTPz2J07ZbZIlJVxpwSrgo2HGd7TDYc6iS5v1VGnc7iWFXjYubzKp7VQcZ9I?= =?us-ascii?Q?1qWFd/PHgnHfs1tfdRUtTysqso+3YhWGLqdQ4pd/4F/jjvC6bc11S6ZxN0qP?= =?us-ascii?Q?lD1GOZeqcOFLx9yeeYEE45S3zJOf2Jk7m2DgoWkHO6mm+N3aIktA6rKwgnPb?= =?us-ascii?Q?ed/gyIU9wuXMf1BuKDUBi9fCswSYNTvi+vdra8tBO2XL9D9nJzAGGpki9Uw5?= =?us-ascii?Q?toGd2uKefaKrSsxccq1YW0sOXEpB8uFD4uNTq1LApq7ZDEIcyZuq5qn87vnZ?= =?us-ascii?Q?JYy6iFnLdJeRjJOe6wEoB5lq5/HpjrM8Q0VooGc47RQTOlspchFuAHfS4yeV?= =?us-ascii?Q?ao0+H4kcwIJBAFufRrdzHs1r6HRJND1aYwJxZqVh5htEZ+Rud8t1gPHOP2vU?= =?us-ascii?Q?NCa3iH4bNCSxJ1+XziUimvZg8nwy7UrMqoQ6eZaybiUsGOkC/qAx7B3IjPlq?= =?us-ascii?Q?BDZ+CjKxr9HG9NllYgIJEdbRqFsOw8w+pOzEo90UxpSs/Ca4YvjGg3Hu2jFM?= =?us-ascii?Q?jZGqKauqUw9H7S1kV6+VBg1erghPOGC9L8HhsPjhUbPUzlTMhEJIkbh4FtVq?= =?us-ascii?Q?h3+nTC/qKTTWqDvz2eZcrAsRojBDtYwszTOkz0JFULBAbGycUmb1Vr8JDiWr?= =?us-ascii?Q?5WCXYg230TxYXFkh2yLKlP19zJJsrFFaMaxpvkW/I1MEL128YivAKNTDz/w6?= =?us-ascii?Q?5fCMxBnKNt0FCmvtQ+FqXOTkCZTZDWHrhHjIJ7HvVKZxJhPwUkJGDdnypor1?= =?us-ascii?Q?3ng6dF7amC9mvUwCmPOr28LvhOF6aAdDq6rqM+UD9M/7KVd/NWBsKvvfronk?= =?us-ascii?Q?6ikt+Dt9R7gMiwUWQKYPcX15danSAdsz3zK89yzMWwF7SbbiWW5A2KQJqiwV?= =?us-ascii?Q?+RE+5w8HMGDaHgk61kgGgkPwfl0jSUdWR2oMGKbgHPxC8KXcHSbTArsyPgtY?= =?us-ascii?Q?rrZp+BdiwaI24Rg8JhqmbsI9D0DAzDNiBr955+j5MXjkGgfZ0NJbWkFQy8TL?= =?us-ascii?Q?NztAwYk0QjQWBKpZUwS7AlGsbMTuzEDxfj31ttjLOAMrMsmfwAZm6HR6Dxqy?= =?us-ascii?Q?qNVkhh0vMDGuIgt30Ot5CWAsiEG3DaHYpwSOAY2eCp1OgbYVypEzKH+0EVw1?= =?us-ascii?Q?C7aibmrwYjSQ5IaBRB4ww3tznoagJTaQ30KZIy7FlHRqJhIs3SzvESuwpw7A?= =?us-ascii?Q?g/7UPlHbL7EIg+4LHFLgI+Etb51Dv1BMF6bO/oRA9z2xQPxuyX4tlAUoAkJn?= =?us-ascii?Q?08bxNu/WHeYpxzWchqn0XXJ+TbV94oGsr3VCAoKvd635gdSG/fB0+qYSpp2r?= =?us-ascii?Q?yXaTmb2zab6v+KdvuXQIS5M+UXJ5tZaH6frSovmJ7+sAdFdRL7GK?= X-OriginatorOrg: valinux.co.jp X-MS-Exchange-CrossTenant-Network-Message-Id: b2ae41c1-d177-4d00-09ae-08de7acfcd56 X-MS-Exchange-CrossTenant-AuthSource: OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Mar 2026 15:56:45.5417 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 7a57bee8-f73d-4c5f-a4f7-d72c91c8c111 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: ndwwOaybYinGPc2a/V7MxCGMwCuFk9C281K1AEugzn40JVnEAH2pVSEM5bWU6r3oQLEYZ+92+U8MAGBfUmTsTw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: TY3P286MB2756 Content-Type: text/plain; charset="utf-8" When ntb_netdev is extended to multiple ntb_transport queue pairs, the netdev carrier can be up as long as at least one QP link is up. In that setup, a given QP may be link-down while the carrier remains on. Make the link event handler start/stop the corresponding netdev TX subqueue and drive carrier state based on whether any QP link is up. Also guard subqueue wake/start points in the TX completion and timer paths so a subqueue is not restarted while its QP link is down. Stop all queues in ndo_open() and let the link event handler wake each subqueue once ntb_transport link negotiation succeeds. Signed-off-by: Koichiro Den --- Changes in v3: - Adjusted context due to changes in Patch 1. - No functional changes intended. drivers/net/ntb_netdev.c | 42 ++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c index 4b65e938d549..e4c1422d1d7a 100644 --- a/drivers/net/ntb_netdev.c +++ b/drivers/net/ntb_netdev.c @@ -99,18 +99,32 @@ static void ntb_netdev_event_handler(void *data, int li= nk_is_up) struct ntb_netdev_queue *q =3D data; struct ntb_netdev *dev =3D q->ntdev; struct net_device *ndev; + bool any_up =3D false; + unsigned int i; =20 ndev =3D dev->ndev; =20 netdev_dbg(ndev, "Event %x, Link %x, qp %u\n", link_is_up, ntb_transport_link_query(q->qp), q->qid); =20 - if (link_is_up) { - if (ntb_transport_link_query(q->qp)) - netif_carrier_on(ndev); - } else { + if (netif_running(ndev)) { + if (link_is_up) + netif_wake_subqueue(ndev, q->qid); + else + netif_stop_subqueue(ndev, q->qid); + } + + for (i =3D 0; i < dev->num_queues; i++) { + if (ntb_transport_link_query(dev->queues[i].qp)) { + any_up =3D true; + break; + } + } + + if (any_up) + netif_carrier_on(ndev); + else netif_carrier_off(ndev); - } } =20 static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_da= ta, @@ -179,7 +193,10 @@ static int __ntb_netdev_maybe_stop_tx(struct net_devic= e *netdev, return -EBUSY; } =20 - netif_start_subqueue(netdev, q->qid); + /* The subqueue must be kept stopped if the link is down */ + if (ntb_transport_link_query(q->qp)) + netif_start_subqueue(netdev, q->qid); + return 0; } =20 @@ -221,7 +238,8 @@ static void ntb_netdev_tx_handler(struct ntb_transport_= qp *qp, void *qp_data, * value of ntb_transport_tx_free_entry() */ smp_mb(); - if (__netif_subqueue_stopped(ndev, q->qid)) + if (__netif_subqueue_stopped(ndev, q->qid) && + ntb_transport_link_query(q->qp)) netif_wake_subqueue(ndev, q->qid); } } @@ -268,7 +286,10 @@ static void ntb_netdev_tx_timer(struct timer_list *t) * value of ntb_transport_tx_free_entry() */ smp_mb(); - if (__netif_subqueue_stopped(ndev, q->qid)) + + /* The subqueue must be kept stopped if the link is down */ + if (__netif_subqueue_stopped(ndev, q->qid) && + ntb_transport_link_query(q->qp)) netif_wake_subqueue(ndev, q->qid); } } @@ -304,12 +325,11 @@ static int ntb_netdev_open(struct net_device *ndev) } =20 netif_carrier_off(ndev); + netif_tx_stop_all_queues(ndev); =20 for (q =3D 0; q < dev->num_queues; q++) ntb_transport_link_up(dev->queues[q].qp); =20 - netif_start_queue(ndev); - return 0; =20 err: @@ -330,6 +350,8 @@ static int ntb_netdev_close(struct net_device *ndev) unsigned int q; int len; =20 + netif_tx_stop_all_queues(ndev); + netif_carrier_off(ndev); =20 for (q =3D 0; q < dev->num_queues; q++) { queue =3D &dev->queues[q]; --=20 2.51.0 From nobody Thu Apr 9 21:52:52 2026 Received: from OS0P286CU010.outbound.protection.outlook.com (mail-japanwestazon11021081.outbound.protection.outlook.com [40.107.74.81]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C45383CD8AB; Thu, 5 Mar 2026 15:56:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.74.81 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772726215; cv=fail; b=THsSpXq+khi4ZMxosNuYfhglsYvMpD54OQVEGbspWgaKV3sl7+6ldPjP0zaVoNsv/EhREkpQ3dXLjz5QC7l4ymz3Tjvr8/ZcfA8ujVVAj93I6+fNmWN6hCXydOd2CcweGpM5ZzJMzdSKpzMXnceZjE4xnQ9l7EH0DP2dLVI8/k8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772726215; c=relaxed/simple; bh=SzGLouDnynt7GQYgGra97hkbKoh1+Z3tgMqKLm6KNfY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: Content-Type:MIME-Version; b=NBTO3s5lrjDStgHn4QPAUAk8FMbfzodmWhqyfUJWVz34nn9tvEfGse9YmjtWBt2u5bBtTkdOV2VBsIVeS9ZK268MDmHfmSgKxrM0EPPPYpzKf7Qk6AB9EztQAYSpJwzJSKVOUmbne0Bsffm8jSih4TCGioGpMqTbpFXBequbk3E= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=valinux.co.jp; spf=pass smtp.mailfrom=valinux.co.jp; dkim=pass (1024-bit key) header.d=valinux.co.jp header.i=@valinux.co.jp header.b=eDbhtOTD; arc=fail smtp.client-ip=40.107.74.81 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=valinux.co.jp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=valinux.co.jp Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=valinux.co.jp header.i=@valinux.co.jp header.b="eDbhtOTD" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=cckTvWJhq1ZgqrCW8YsmLYumSIF94knTK3xyXetetHtxMJjhNJu782v2DCoQLo2MCpPgyZ68cAZdHLmdOtSc+vF3PK/+vrUjslJEkitjxSgK4NeOMdqtIdFWkXUWg5m9Agne/kqKHeSRwWpplIKd88R3hD5oauP6vQ0+Hk9oyHjWQe0aG7BedP93WFNeb/ozAmm902txFgYS0m3mMX5JVW8tzgDDXvXYyw/W+iLEJXa035S4oiwoJrzTgKBEudgdm2bGL97O2n0mE4H1HoZ4kGRMW3/sn6UhlzbQr3djYPl9use0YcKnfQowdtL7ucJhJ6v33r3xWsPBIQtv4GNJrA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=r7vfPwUFrIPhhveeO6qXJKoySSUaTrEedhg6Gtj4evo=; b=Nb+x0x5qusDTQkhlaN+qt4CBXJlRP2RLTzE/kzEki/MBeAXc/FAA3oZJyaBsWnRu1n5IUVj65lhl+orgXM2by1DgjE8I0Rt9wkibMO840YDv66r9BvaERUQ2qrNNxxADWl8gpkz2B3hH7LSeEDhAfhJY6HdfcXAMaTe8Yg+VfsCfs4nxhy6plFA1N9xPDFuCRa8FJIDdcBhkwx8Q8490w5sgjgyE14Ar77iIC1GZ1j3v52slGTyTbD9bMS5OZgfcUyJFEt8hWTmWEpzTp93LehY0UX9Zzfyd7V91vMnN75ZeDj93aVuOy1DPg/7hga4tU8dezktilzZOW1u2k4hdWQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=valinux.co.jp; dmarc=pass action=none header.from=valinux.co.jp; dkim=pass header.d=valinux.co.jp; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=valinux.co.jp; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=r7vfPwUFrIPhhveeO6qXJKoySSUaTrEedhg6Gtj4evo=; b=eDbhtOTDg5MnGcReRpCsnPEaJL50UJlrQMuHXU4uOWXYJTrqNKOkEV49GSkxmho7AjaJu5nQkKC6In6V2pb4ISvUvIrn45ufPyq3ewR7T6IZ2HQ7JtKpEw3gcY3Md2zgzd+KSjsR/G7IuH6XeidQQiITjYq0k5zvizDqKNJPW08= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp; Received: from OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM (2603:1096:604:468::22) by TY3P286MB2756.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:23e::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9678.18; Thu, 5 Mar 2026 15:56:46 +0000 Received: from OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM ([fe80::b7ab:6af2:d18e:4a71]) by OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM ([fe80::b7ab:6af2:d18e:4a71%3]) with mapi id 15.20.9678.017; Thu, 5 Mar 2026 15:56:46 +0000 From: Koichiro Den To: Jon Mason , Dave Jiang , Allen Hubbe , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: ntb@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 3/4] net: ntb_netdev: Factor out multi-queue helpers Date: Fri, 6 Mar 2026 00:56:38 +0900 Message-ID: <20260305155639.1885517-4-den@valinux.co.jp> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260305155639.1885517-1-den@valinux.co.jp> References: <20260305155639.1885517-1-den@valinux.co.jp> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TY4P301CA0082.JPNP301.PROD.OUTLOOK.COM (2603:1096:405:36f::14) To OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM (2603:1096:604:468::22) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: OSOP286MB7730:EE_|TY3P286MB2756:EE_ X-MS-Office365-Filtering-Correlation-Id: 4efc5edb-a68b-4954-b651-08de7acfcdf1 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|376014|7416014|366016|1800799024; X-Microsoft-Antispam-Message-Info: J5VljWpiePYi3HA0U4le0Gl4+/6mlsu8okSoN/U/lSr/y8IoqciWrfIcIhopB9CBpM9zA6+CCdEDLfgoc5yM9xhfI+MSiINW7YcrO0LHD7vhyYXSNVHIVoERJ4Kc7vAtTnwfju9Ep/Frw6MTJLRQ3/jN3fjML7YrKlSbQPoMfMT13zr5GWQeIYcixb8z+6ZM/H1j1clj+DjmqNtQyl96tUQ2srDamAi2bE08hjnxIKgb7HVHSsYQb+fCD9Fuzveu8KkEn6yI2QXgYWALqupMAtVkLqm28y59m2Mv7kfpDwlnNP5lEuNVh1smyJ2Uh8YRaKxyC8AfgUg6kSLyRXGAxPXwZ7da/V7NwOtnk+9ro2xx/WInFHahe2Xk7xfVxoTd4vpyBosUdqqPMD8ZoDymGOToqPHCUUS/rEGIcLxWKEMoTNkUoOUBvMO+d7fo1X4tCd1OQS6AmjJO6wTOwDIvgCoiV/Jds/zJ6PZwebElOzwuWbInpcHOJOcaRRSERaG9FCl0xZzISAyQ4NUdty2TwnOg33QdMk5sIHIpBxxOgOftSnKd9Rs+9uYUomEPsmUr/ewKxIU2tLQW37aloopNy+WzSvI5MXaJh5OEZOQA9gEWT6YBMfC0HbendttRvL2EfrUg68OCuTB94UReuInR8RZ6D3lwAOHVpPjfPnj8v3rIFNp0kkSOkSHduuYFyF5LPqv5JzxtOkWgyNekZylk5zina/PAT5tdSTEWNoAKHu0= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(376014)(7416014)(366016)(1800799024);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?1F06TuW1CwXOh7pZsehThKknRi+GLMdm6kDdmgWKk324v+uy1mEvbYwZ6UIB?= =?us-ascii?Q?I3hhct5ULqfAad8lVrsmHolFXBF/E4lBseSjMQzOlUszfwymfkY9DBFITVlV?= =?us-ascii?Q?PdP/o8P+s8UHXaOCfcmW2OAM9IKQGHPHNhU5I1/uZ1tU9oeimV3lYf8h2eCU?= =?us-ascii?Q?uMzxc6EFnMZCBwhX3sIDlK4GkY7pLujXZZJTQdSq7ItK1oiRN6TUslFzG07E?= =?us-ascii?Q?7STHvNtWOLHbKtCPzztdSUgeC6JBVvLFmKRA8vNLbhDiw/61+2uie7faTsib?= =?us-ascii?Q?/fwZ0JvYfCkYK+iKz/AquHy++Lhx0+Tzt+sYkzo7/++xW6Dym3BISjAdHhSE?= =?us-ascii?Q?3495itr9AIYOmT8CdX265iP9Ogp5m7TIjA16iOAGwzlluAhpVHAvvAWLMqC+?= =?us-ascii?Q?jdd7m82nOSbBrGFXS+m4sDQjNNw+eIK+rx9cC/+meufbEPtOEaDTJRtjXbEx?= =?us-ascii?Q?yDduleQrgkiPNH8XZ3q/r8OFEn+D2OVK020seQWuJj1LP6RANf+CaOW7LJW8?= =?us-ascii?Q?l9mEXPBD0DCYABNBQEKCkgGQSB/EfgjYZYS5ANFr18bV0gPz9ovCNWp0v+V6?= =?us-ascii?Q?tgtN0wvkJLPjzemhoIXh2AOV5ydeoIxZuIm4Ddc953Y3EtMYQWJVrNZAdZLS?= =?us-ascii?Q?6s6it7qxJde1m23nyx1rj5dk+fKlkQnE8VWnu+jWQEZo3KOX5yvyNhovX3Oa?= =?us-ascii?Q?SNLqZnL4iAiiZby79iStaEoS0ov4XXq/CgfYKIDjRv17nqcysNtjNxxi6pcu?= =?us-ascii?Q?OvJ36uvvBX+BCYhKeY7ZomocUB4Sx1d9aHXp8hgY0WtPneMO+PAGFvze8c3x?= =?us-ascii?Q?tyNBMTChpj3goRLWFtacZhV4TfrzGTyjcaRXdaIH57Fp2xfSXv6wUeLkS/zg?= =?us-ascii?Q?aMHQjiBnWka+I9r5EwPWQGmByAArIg7F01bDWEEpS4lj5UaaCzq3v7xUgrUZ?= =?us-ascii?Q?aVIM+DK3Yemvedr+1Dr9IQbyxvuJqP8UymddkO9wIiuogJHYnxGGV0wRNq14?= =?us-ascii?Q?uOyppOLS9FyFjgw9VBQ4c4f7rqSIIMMUiFPsmPgG+emuGjLjIKnXIFsKMMwH?= =?us-ascii?Q?HafHjk19JEpXeAXg/Exy1tQr47uhWvbLVd3tm+iCI+k8hHjDHuGo/nrcP5pA?= =?us-ascii?Q?tCfiIe7UmlKD0Z+Bvyi7ni1xftVaTdWb0JoIqG78JO8Kgu+yo28IyHtBW6ES?= =?us-ascii?Q?vv2w3UKK/IBtaaZbfVs2WvRxGeQ5lgMkL99c92/5g9Hn0DDO6/VARHHdsqEH?= =?us-ascii?Q?VdiRSUQO8AmxN0NTPjcC1t4AD2wIw4XzS2EAL1pDivVg/3PWTf8ZXLp8err4?= =?us-ascii?Q?nbcFhr0bbZOk5ZeGn+/1RVu7YGJg9NU3rWktuefo6VUKYzofZbtD2NOYQWlX?= =?us-ascii?Q?lSlfG5X7uyaHuuy9Qyt8EvyR0nSmoS65Vlq6SZKnyL1Sx1MaSSj9b5u4Bpdg?= =?us-ascii?Q?WMPiZQOFm49PgRMN+LfCF3dP7nwx2+2sDZnyXKWcX8iYSlQvjMk0p/sfmiXN?= =?us-ascii?Q?aNtnpd93p2f8EnKh9d+aNtm4bUqlUP4Iz/38Q7W5/9e0QwB9748sgyz6+xPI?= =?us-ascii?Q?utdcyp5jWglD/JazuHLE6LsSCYOGDRWXeOmv5XTrio0BzIlOuanOB3ylTOwS?= =?us-ascii?Q?9QHBrcnJOEYXAQrnMKxrpfK3TlFR1AIc8rlxdywKBfLMTJl58g8VYnw5tbl9?= =?us-ascii?Q?1IgzwTZ/Fgf38mcXPz94Yi8cZEj9OIThrMKl+782YH3k1Q0jtk5PKQqm3QHp?= =?us-ascii?Q?KPfn4sMYeHv9nP7Hd2LPhEDL1wEJkK3idkcqTUZ/f4vyARyqj2rb?= X-OriginatorOrg: valinux.co.jp X-MS-Exchange-CrossTenant-Network-Message-Id: 4efc5edb-a68b-4954-b651-08de7acfcdf1 X-MS-Exchange-CrossTenant-AuthSource: OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Mar 2026 15:56:46.5680 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 7a57bee8-f73d-4c5f-a4f7-d72c91c8c111 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: iZ0gRR9d2LPRrZZ9WjiQW/vham2+uaZkxAEyaEp149u2JI5DdQt3GitigdUlhOsvGWOl5QyEDE9Ko0zDujQ8zQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: TY3P286MB2756 Content-Type: text/plain; charset="utf-8" Implementing .set_channels will otherwise duplicate the same multi-queue operations at multiple call sites. Factor out the following helpers: - ntb_netdev_update_carrier(): carrier is switched on when at least one QP link is up - ntb_netdev_queue_rx_drain(): drain and free all queued RX packets for one QP - ntb_netdev_queue_rx_fill(): prefill RX ring for one QP No functional change. Signed-off-by: Koichiro Den --- Changes in v3: - Adjusted context due to changes on Patch 1. - No functional change intended. drivers/net/ntb_netdev.c | 101 +++++++++++++++++++++++---------------- 1 file changed, 61 insertions(+), 40 deletions(-) diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c index e4c1422d1d7a..ac39652b0488 100644 --- a/drivers/net/ntb_netdev.c +++ b/drivers/net/ntb_netdev.c @@ -94,26 +94,14 @@ struct ntb_netdev { #define NTB_TX_TIMEOUT_MS 1000 #define NTB_RXQ_SIZE 100 =20 -static void ntb_netdev_event_handler(void *data, int link_is_up) +static void ntb_netdev_update_carrier(struct ntb_netdev *dev) { - struct ntb_netdev_queue *q =3D data; - struct ntb_netdev *dev =3D q->ntdev; struct net_device *ndev; bool any_up =3D false; unsigned int i; =20 ndev =3D dev->ndev; =20 - netdev_dbg(ndev, "Event %x, Link %x, qp %u\n", link_is_up, - ntb_transport_link_query(q->qp), q->qid); - - if (netif_running(ndev)) { - if (link_is_up) - netif_wake_subqueue(ndev, q->qid); - else - netif_stop_subqueue(ndev, q->qid); - } - for (i =3D 0; i < dev->num_queues; i++) { if (ntb_transport_link_query(dev->queues[i].qp)) { any_up =3D true; @@ -127,6 +115,58 @@ static void ntb_netdev_event_handler(void *data, int l= ink_is_up) netif_carrier_off(ndev); } =20 +static void ntb_netdev_queue_rx_drain(struct ntb_netdev_queue *queue) +{ + struct sk_buff *skb; + int len; + + while ((skb =3D ntb_transport_rx_remove(queue->qp, &len))) + dev_kfree_skb(skb); +} + +static int ntb_netdev_queue_rx_fill(struct net_device *ndev, + struct ntb_netdev_queue *queue) +{ + struct sk_buff *skb; + int rc, i; + + for (i =3D 0; i < NTB_RXQ_SIZE; i++) { + skb =3D netdev_alloc_skb(ndev, ndev->mtu + ETH_HLEN); + if (!skb) + return -ENOMEM; + + rc =3D ntb_transport_rx_enqueue(queue->qp, skb, skb->data, + ndev->mtu + ETH_HLEN); + if (rc) { + dev_kfree_skb(skb); + return rc; + } + } + + return 0; +} + +static void ntb_netdev_event_handler(void *data, int link_is_up) +{ + struct ntb_netdev_queue *q =3D data; + struct ntb_netdev *dev =3D q->ntdev; + struct net_device *ndev; + + ndev =3D dev->ndev; + + netdev_dbg(ndev, "Event %x, Link %x, qp %u\n", link_is_up, + ntb_transport_link_query(q->qp), q->qid); + + if (netif_running(ndev)) { + if (link_is_up) + netif_wake_subqueue(ndev, q->qid); + else + netif_stop_subqueue(ndev, q->qid); + } + + ntb_netdev_update_carrier(dev); +} + static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_da= ta, void *data, int len) { @@ -298,28 +338,16 @@ static int ntb_netdev_open(struct net_device *ndev) { struct ntb_netdev *dev =3D netdev_priv(ndev); struct ntb_netdev_queue *queue; - struct sk_buff *skb; - int rc =3D 0, i, len; unsigned int q; + int rc =3D 0; =20 /* Add some empty rx bufs for each queue */ for (q =3D 0; q < dev->num_queues; q++) { queue =3D &dev->queues[q]; =20 - for (i =3D 0; i < NTB_RXQ_SIZE; i++) { - skb =3D netdev_alloc_skb(ndev, ndev->mtu + ETH_HLEN); - if (!skb) { - rc =3D -ENOMEM; - goto err; - } - - rc =3D ntb_transport_rx_enqueue(queue->qp, skb, skb->data, - ndev->mtu + ETH_HLEN); - if (rc) { - dev_kfree_skb(skb); - goto err; - } - } + rc =3D ntb_netdev_queue_rx_fill(ndev, queue); + if (rc) + goto err; =20 timer_setup(&queue->tx_timer, ntb_netdev_tx_timer, 0); } @@ -335,9 +363,7 @@ static int ntb_netdev_open(struct net_device *ndev) err: for (q =3D 0; q < dev->num_queues; q++) { queue =3D &dev->queues[q]; - - while ((skb =3D ntb_transport_rx_remove(queue->qp, &len))) - dev_kfree_skb(skb); + ntb_netdev_queue_rx_drain(queue); } return rc; } @@ -346,9 +372,7 @@ static int ntb_netdev_close(struct net_device *ndev) { struct ntb_netdev *dev =3D netdev_priv(ndev); struct ntb_netdev_queue *queue; - struct sk_buff *skb; unsigned int q; - int len; =20 netif_tx_stop_all_queues(ndev); netif_carrier_off(ndev); @@ -357,12 +381,10 @@ static int ntb_netdev_close(struct net_device *ndev) queue =3D &dev->queues[q]; =20 ntb_transport_link_down(queue->qp); - - while ((skb =3D ntb_transport_rx_remove(queue->qp, &len))) - dev_kfree_skb(skb); - + ntb_netdev_queue_rx_drain(queue); timer_delete_sync(&queue->tx_timer); } + return 0; } =20 @@ -428,8 +450,7 @@ static int ntb_netdev_change_mtu(struct net_device *nde= v, int new_mtu) =20 ntb_transport_link_down(queue->qp); =20 - while ((skb =3D ntb_transport_rx_remove(queue->qp, &len))) - dev_kfree_skb(skb); + ntb_netdev_queue_rx_drain(queue); } =20 netdev_err(ndev, "Error changing MTU, device inoperable\n"); --=20 2.51.0 From nobody Thu Apr 9 21:52:52 2026 Received: from OS0P286CU010.outbound.protection.outlook.com (mail-japanwestazon11021081.outbound.protection.outlook.com [40.107.74.81]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D92D73CE494; Thu, 5 Mar 2026 15:56:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.74.81 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772726219; cv=fail; b=fVtGqcnFj2yu4cQnvRLCc85xTgDnapHsAwCtXUcbx2NZeV93IwYXRBWdJuFJv5RetIt6K/UxM+BDoK/B9XVmHksLXCdhFIDeSH6+EcskbkoeZ8Rt8ekfEU1ETlhuvfr8NBBkOGTTW83PuA3QymR2f4XHMqV0KCJ0sxtVB5ccE04= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772726219; c=relaxed/simple; bh=9Swe8eXaL3wGyj1PPfuNXv0bx06Y0EF2oZtO4jeDuAc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: Content-Type:MIME-Version; b=SesB7THiy5dn1Smqb20J2rvfcefo7qp+kS2Va1vKjGE2GbKVsSP1S6Jmwsy2xFyJy059D00dkFHUMopp3qrA/0fRyspG9N4Lc/qc7akwmQxazx2zpcig3mBN4UqepAL9bs0mPmHRNJtReN2hnttE7SLSAjW2HNnSjXQfIzzCIWM= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=valinux.co.jp; spf=pass smtp.mailfrom=valinux.co.jp; dkim=pass (1024-bit key) header.d=valinux.co.jp header.i=@valinux.co.jp header.b=EEKA56ER; arc=fail smtp.client-ip=40.107.74.81 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=valinux.co.jp Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=valinux.co.jp Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=valinux.co.jp header.i=@valinux.co.jp header.b="EEKA56ER" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=KzlqSbiEkFFZiG8e0oj70mSqxUleQQN2VxuV6sfFbwiAEKQ3hLY1ZuqdU/xarmNYimGZX3ON147dg0zjKEcp+k5rsndg0zO5qKTF46sCm1LrZ0k0swolk1fdBlL3q/t1wsVXQ9UyKRL2NCa7V/DEGSbqROndw9zbsYmqEEXocefZsAVQfFjWO2k92hweVdrbXL2mPYSGzauF1SqpupO6YLitv4xH0iHVT8rj37ej5HlLmBGaxo1fNFtnbqAm3LkVXAKCGoGV0g3pGH7aZSMv5t0hLA93JMkDqYHnTjTGBx+mue20nmS2cDne9VqP+ijyssDUWyEix708vfJzZlkZaw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=T+CgcqvbhMN/UfDLBLi7OyLlVkE3LBPFmQWBwhYA4yY=; b=GztUTPZ3yh4SoafYks0LmsGg6UW8FmPBhFTKAYiR9DqqYWWld5YzhJOONoZk1sdqHuWWmyLX+GEQLiPMTuKssIFfnfa3lFLcfBB5qNF6wSigmGWwl5v7vpuJC4TUNReDARwxRYDtmUhmz/XgUbBkfnaP8IrLXh8jscvb4k+AqnJIKBq4TX2UOuneVX+B5wBbCHIfkrstKf8iBDn0Ms5cu2y6cR4nKXXGl3Sg13rNp2GrcpPUE6FzFuhWoFZ7y9Ot1P5us0aPSZ8wNVwMy7cPO+7De+RifJ65zkJ5B33rg13ZBYo5TZN6eY06AVlV6u1pO6px5wLtcdB5B5YHmeHXEQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=valinux.co.jp; dmarc=pass action=none header.from=valinux.co.jp; dkim=pass header.d=valinux.co.jp; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=valinux.co.jp; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=T+CgcqvbhMN/UfDLBLi7OyLlVkE3LBPFmQWBwhYA4yY=; b=EEKA56ER1auRjSOVtZbnaQBpKrpItF68WXmfP23buPEIfYXGxixSWpoDEhBarjR9nIN55zJRrFP0xz27/ik+SdQhQ3Fk5l/U6dy5y7Mkb+leiFETqVWFk3GFXXr6bRiRmN7W7s44gsbYiUOYy96pDi2k4MLlm5PrPkbqbW5nS2w= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp; Received: from OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM (2603:1096:604:468::22) by TY3P286MB2756.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:23e::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9678.18; Thu, 5 Mar 2026 15:56:47 +0000 Received: from OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM ([fe80::b7ab:6af2:d18e:4a71]) by OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM ([fe80::b7ab:6af2:d18e:4a71%3]) with mapi id 15.20.9678.017; Thu, 5 Mar 2026 15:56:47 +0000 From: Koichiro Den To: Jon Mason , Dave Jiang , Allen Hubbe , Andrew Lunn , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: ntb@lists.linux.dev, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v3 4/4] net: ntb_netdev: Support ethtool channels for multi-queue Date: Fri, 6 Mar 2026 00:56:39 +0900 Message-ID: <20260305155639.1885517-5-den@valinux.co.jp> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260305155639.1885517-1-den@valinux.co.jp> References: <20260305155639.1885517-1-den@valinux.co.jp> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCP286CA0162.JPNP286.PROD.OUTLOOK.COM (2603:1096:400:383::17) To OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM (2603:1096:604:468::22) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: OSOP286MB7730:EE_|TY3P286MB2756:EE_ X-MS-Office365-Filtering-Correlation-Id: a2b719f4-909a-42b8-8e85-08de7acfce7e X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|10070799003|376014|7416014|366016|1800799024; X-Microsoft-Antispam-Message-Info: U/BETqv3/T4w/rgrXYrymH+X/y4mqZHN1BKpOHmjwjOhzhyXIFOJOIVHD8EpEI7gvsXyUjOYeHF20d/M1trw1jHoT1zxjHZrSrCs3xfOMJ79+ffNtvSm6AVtj6bOx/bRoxD+U8NDCGpPQjD7ukTtm+4hIepCBXKWzF1ZDeaPAjh8nDryD78KJq/MwIKj9f7qerjhZzxpbuZyvXbLBKVox+iIuf7JuFyCompiQ7MI5sRtr/1RRBs1QPMwHUTJm3317BUE/R80zqXDohq4kmfRuCTJ7wOq4kmrXzZS73nCk1t6ljt+He55+S54nKhn/Ipcuh3Z38B8fbG+M+BeasJsbTNI0BlYMmgROpEUuWGTnkb83hjn0HVQo5bnB8kWfWUdtjeLdV5WsNkQs+zYVVV8KtzC52mr5PLasb0Ez23Q9IAQk6zWNlHhW33N2lnZQSp/gwQucQPagoWLxPYu/YrFu2mGSxT8F/UGTPjYufEONFCXdmmu3BoLTb2w4P4bNqa/lT9rU5CD0ds7KN1wyKboPpDPDwmEkHx6R7/d7Or4q1jQ05AaWBFskS2URfLOlEEOPMuCijMPu6FKmsj8+zbcu+/rEHaFYCJHhh/QrjhyebtvzyZd7M6TvsoliFnfwblYY02aJNoqfGyjoTNZKdoMq1jzN1EhuFSa2vPX0rDa2RRJ9fmhfIxdZzxjfFFHMKUSBz4Oqfl5vFmWkQRdpt5b0kUrg8UXDVX5KfLcZNp2+gY= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(10070799003)(376014)(7416014)(366016)(1800799024);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?YwFoj5StAOsvMPJWFvlfgGHj8HqVjVGFe6Su+eFtQBqDas3gL2/ce0tW/2mx?= =?us-ascii?Q?bTMORdurnZezNjv6pWvLFlhhduRe5KB6w6c+sLSm568e/IB7ocMr7Xu3Q40f?= =?us-ascii?Q?VEjuXE72jeZDlGak4Sfzm4ZXz+V4VQlqQ5oP7bTG4fAYra/yrRs9BT45NR03?= =?us-ascii?Q?05l5bsUEd5GMXEzbnohn59vSZXKtDbRdeSaHgCtlPjOV2aBhw34SVHBRLIHK?= =?us-ascii?Q?I3OrVfw8pjOHZWx3nsmBnFvP+p2kXeC/OYnxPFUALHFLtbOsIWmTebHRzaiJ?= =?us-ascii?Q?I+Xl03bmDPjBM8KsicvEowyJM2g9Gt8Zd9giZUDZCFlqXDUujv1Gqbp1JzFV?= =?us-ascii?Q?L+QA8WsKs7lqmq9UAqfrz1dQKipNZokxooJ/LeqIrXsJvtD00zGylHCCFWZu?= =?us-ascii?Q?ZcQgrQ0qNAPAuoxl4fWLAkYxpfyl9iwYZBo743AC9kocxEAKXt8SMJynxxiT?= =?us-ascii?Q?FWvcWtMu2vcR8YM1a7zrzVp/yV8R1IoSjOdFxxazT1YMH/2hrYpBpK1TiZzS?= =?us-ascii?Q?Ug5kWdJIQz3jmiOPA8pydXg/Q18cUKyS0axeb1IDbq18U5ppSE5s7UwIBrTT?= =?us-ascii?Q?fyecgHSd2tt3V/DaeSl55K0LI//CsSAXWUQKLTw58axr72dOTHHhaLnyvxt1?= =?us-ascii?Q?Csok6Sr8kRiBUnoYB5tV1HKN5YO/ptAZ6A+sm4liQwQ5j9S95eD81TCv4gkE?= =?us-ascii?Q?qPyiRPfUBYQwDgq2HDMmMHjIvXjQuQwdiabDKJZihrzZwyuD2SjAIUvaSddE?= =?us-ascii?Q?MbULTIchmYJKiw1Vr2zpCIcN14Qe+SaqHOR7BOtBmP3hqRPegQehj4VEeoPK?= =?us-ascii?Q?imd0rCXbnn63RdHxHp6bqs2NYO5JH+h1sQkYDzxWFu1XnZDv5Zlu6ilyH6vC?= =?us-ascii?Q?eeldGl6VBanz3JfK3qyzeXjlP0h2ZDYByqq1KTBjbOppD5vW9cfqfZMmD+DA?= =?us-ascii?Q?jMYGs1KkybjGiMikBBliQyn3+Mtlr6EFeqnuf4wvAE5gAPfBjqjekabd2+Zh?= =?us-ascii?Q?BXcIc9WpK3zIROJZJwkU7VE+HQ7ZwvfTKmUFFqLQKiWatqDLDLenw45rL6KK?= =?us-ascii?Q?8qaAOu1FsgKyDvmRF/0d+CSgQOMGztAnuTPz9yVJvSMDv34OqD7FbSirCaPd?= =?us-ascii?Q?/J4LS7xJja6RD3Ze8452qf6DT3LNoDNsY9+pQWRLh4Wf+qlxRb/1BMhuBy7J?= =?us-ascii?Q?mJ9vp1zM5YLSkxH6xy9gF1EEC2HI3NzCu1UAKfA/aOnl13j+QGcef7YZjEWX?= =?us-ascii?Q?4DDChy2EWQ7PO+sZ4yXzvOKRer9ZOJX1YsvPIl59rPbR1835/Bjkgn2Sek/Z?= =?us-ascii?Q?BSjk36qUQL7/EFjDonkCfrGIq2rmY8sL5/mrYuGtuRf3SptV3GDkCrArUVR4?= =?us-ascii?Q?iGjTAKRFOqVVCUckmnKytPsIwbjhj9QOZhOfgkJO756/ymzanC5ATt1dPB3H?= =?us-ascii?Q?xHBVa3ecVpP4cGeKua9riVeAMzOscXGGS2Qs5eLGz1jdsqhgE6I6yAgzsxQA?= =?us-ascii?Q?ud1PA3pVFX7ggthKA+VOt6qa5te1wOAGCj9fkesUFpxCscQKc2MphxolLolK?= =?us-ascii?Q?f6XDXklLNO4qyZNZhvK4lUVE3JWxlE+LmOcQeQZZWHj+Zq86SnPn4wwD0cjv?= =?us-ascii?Q?N8sBPpxXYLWuDJNAyqtbDrWAYMU9IUF3Fvjj7Ztczh0HaU757ZfPI/ukry9U?= =?us-ascii?Q?P3YKLd3hZ2aWzR/ABF5XptV4eMVK7nz8xgVHSL6IS/1VIxF9W2w2F0zIqDEo?= =?us-ascii?Q?zaW1bWdz9doigb4u48GU5sQF70OEmlfyeGw/BrKS9IGQMAmldjwE?= X-OriginatorOrg: valinux.co.jp X-MS-Exchange-CrossTenant-Network-Message-Id: a2b719f4-909a-42b8-8e85-08de7acfce7e X-MS-Exchange-CrossTenant-AuthSource: OSOP286MB7730.JPNP286.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Mar 2026 15:56:47.4841 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 7a57bee8-f73d-4c5f-a4f7-d72c91c8c111 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: nbYc4BPfr7kJqmXdc4cIT8zB799yEKdKQXWgQ0B1ZwFj7B5KZZ5VBdiq4rn0lwmJ1HGz9F6Aa1c2ivzTcBtMaA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: TY3P286MB2756 Content-Type: text/plain; charset="utf-8" Support dynamic queue pair addition/removal via ethtool channels. Use the combined channel count to control the number of netdev TX/RX queues, each corresponding to a ntb_transport queue pair. When the number of queues is reduced, tear down and free the removed ntb_transport queue pairs (not just deactivate them) so other ntb_transport clients can reuse the freed resources. When the number of queues is increased, create additional queue pairs up to NTB_NETDEV_MAX_QUEUES (=3D64). The effective limit is determined by the underlying ntb_transport implementation and NTB hardware resources (the number of MWs), so set_channels may return -ENOSPC if no more QPs can be allocated. Keep the default at one queue pair to preserve the previous behavior. Signed-off-by: Koichiro Den --- Changes in v3: - Remove redundant checks already handled by ethtool core. - Split ntb_set_channels() into helper functions. - Drop ntb_netdev_sync_subqueues(), which did more than necessary in some call sites. Adjust the original call sites to perform only the required operations. drivers/net/ntb_netdev.c | 157 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 151 insertions(+), 6 deletions(-) diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c index ac39652b0488..6397d898c991 100644 --- a/drivers/net/ntb_netdev.c +++ b/drivers/net/ntb_netdev.c @@ -284,6 +284,12 @@ static void ntb_netdev_tx_handler(struct ntb_transport= _qp *qp, void *qp_data, } } =20 +static const struct ntb_queue_handlers ntb_netdev_handlers =3D { + .tx_handler =3D ntb_netdev_tx_handler, + .rx_handler =3D ntb_netdev_rx_handler, + .event_handler =3D ntb_netdev_event_handler, +}; + static netdev_tx_t ntb_netdev_start_xmit(struct sk_buff *skb, struct net_device *ndev) { @@ -492,16 +498,155 @@ static int ntb_get_link_ksettings(struct net_device = *dev, return 0; } =20 +static void ntb_get_channels(struct net_device *ndev, + struct ethtool_channels *channels) +{ + struct ntb_netdev *dev =3D netdev_priv(ndev); + + channels->combined_count =3D dev->num_queues; + channels->max_combined =3D ndev->num_tx_queues; +} + +static int ntb_inc_channels(struct net_device *ndev, + unsigned int old, unsigned int new) +{ + struct ntb_netdev *dev =3D netdev_priv(ndev); + bool running =3D netif_running(ndev); + struct ntb_netdev_queue *queue; + unsigned int q, created; + int rc; + + created =3D old; + for (q =3D old; q < new; q++) { + queue =3D &dev->queues[q]; + + queue->ntdev =3D dev; + queue->qid =3D q; + queue->qp =3D ntb_transport_create_queue(queue, dev->client_dev, + &ntb_netdev_handlers); + if (!queue->qp) { + rc =3D -ENOSPC; + goto err_new; + } + created++; + + if (!running) + continue; + + timer_setup(&queue->tx_timer, ntb_netdev_tx_timer, 0); + + rc =3D ntb_netdev_queue_rx_fill(ndev, queue); + if (rc) + goto err_new; + + /* + * Carrier may already be on due to other QPs. Keep the new + * subqueue stopped until we get a Link Up event for this QP. + */ + netif_stop_subqueue(ndev, q); + } + + rc =3D netif_set_real_num_queues(ndev, new, new); + if (rc) + goto err_new; + + dev->num_queues =3D new; + + if (running) + for (q =3D old; q < new; q++) + ntb_transport_link_up(dev->queues[q].qp); + + return 0; + +err_new: + if (running) { + unsigned int rollback =3D created; + + while (rollback-- > old) { + queue =3D &dev->queues[rollback]; + ntb_transport_link_down(queue->qp); + ntb_netdev_queue_rx_drain(queue); + timer_delete_sync(&queue->tx_timer); + } + } + while (created-- > old) { + queue =3D &dev->queues[created]; + ntb_transport_free_queue(queue->qp); + queue->qp =3D NULL; + } + return rc; +} + +static int ntb_dec_channels(struct net_device *ndev, + unsigned int old, unsigned int new) +{ + struct ntb_netdev *dev =3D netdev_priv(ndev); + bool running =3D netif_running(ndev); + struct ntb_netdev_queue *queue; + unsigned int q; + int rc; + + if (running) + for (q =3D new; q < old; q++) + netif_stop_subqueue(ndev, q); + + rc =3D netif_set_real_num_queues(ndev, new, new); + if (rc) + goto err; + + /* Publish new queue count before invalidating QP pointers */ + dev->num_queues =3D new; + + for (q =3D new; q < old; q++) { + queue =3D &dev->queues[q]; + + if (running) { + ntb_transport_link_down(queue->qp); + ntb_netdev_queue_rx_drain(queue); + timer_delete_sync(&queue->tx_timer); + } + + ntb_transport_free_queue(queue->qp); + queue->qp =3D NULL; + } + + /* + * It might be the case that the removed queues are the only queues that + * were up, so see if the global carrier needs to change. + */ + ntb_netdev_update_carrier(dev); + return 0; + +err: + if (running) { + for (q =3D new; q < old; q++) + netif_wake_subqueue(ndev, q); + } + return rc; +} + +static int ntb_set_channels(struct net_device *ndev, + struct ethtool_channels *channels) +{ + struct ntb_netdev *dev =3D netdev_priv(ndev); + unsigned int new =3D channels->combined_count; + unsigned int old =3D dev->num_queues; + + if (new =3D=3D old) + return 0; + + if (new < old) + return ntb_dec_channels(ndev, old, new); + else + return ntb_inc_channels(ndev, old, new); +} + static const struct ethtool_ops ntb_ethtool_ops =3D { .get_drvinfo =3D ntb_get_drvinfo, .get_link =3D ethtool_op_get_link, .get_link_ksettings =3D ntb_get_link_ksettings, -}; - -static const struct ntb_queue_handlers ntb_netdev_handlers =3D { - .tx_handler =3D ntb_netdev_tx_handler, - .rx_handler =3D ntb_netdev_rx_handler, - .event_handler =3D ntb_netdev_event_handler, + .get_channels =3D ntb_get_channels, + .set_channels =3D ntb_set_channels, }; =20 static int ntb_netdev_probe(struct device *client_dev) --=20 2.51.0