From nobody Sat Apr 18 09:10:30 2026 Received: from OS0P286CU011.outbound.protection.outlook.com (mail-japanwestazon11020096.outbound.protection.outlook.com [52.101.228.96]) (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 3E42E44BC94; Sat, 28 Feb 2026 14:55:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.228.96 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772290550; cv=fail; b=Zt+PTKg05PCkL95KgHBF5EjSKOZB8/+kOrGeEZ68CrUYMlML0AC9s58thJKURNGxXhhEC75rUTptUQIF4DiZrEhIETMl3DhswJjDfxFDf27D5aHH35b3yQt6LzSI5zv8NmcSizVTy+yLlBIZJ0N0ItMyTjuL1xvVWxiCuZK4WPg= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772290550; c=relaxed/simple; bh=PxyjFFhRjY+GohSBCAhZsm/8r3NrwoH95rhs1ARpqKs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: Content-Type:MIME-Version; b=ElFTVKv/MEHmXq2MlA3rUOjkkwzqiSruhzgda1jubjrL7atWfSNa9uqcDDVOudn8HJqIGoac3nQc9n5shnTtiiQq+iz5vX4EHqDnVeFhuNncy4nM2UlF8mIc5nws8FHEi3pvezWb/vzqT+I+y901PWwht/WfnbOkUHHhwwkOr28= 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=L3/C6WNh; arc=fail smtp.client-ip=52.101.228.96 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="L3/C6WNh" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=XMpzy9dqCjw2B5tUaxK+F1X8CwyTVr1ShvSUsLku+ZIWrbLWa8ccpLVu6zdmsd4E/N7BDKx1rpNg6Y2rIHCwjHbb37Hm1csvEjgHE7z5v3z8i2bBC4gZNfSWrcb6YeAXpZY5u9rnehDDBAHQyP31Bx5gl6BZaPqU/ATvzAIEJTsK+QFyiNYba5sRt2oINl0FNBxwncPZqtC/SZD76f+ZXcO8om7Bvz1MDqaSepMC3BBJu4PxIrJvHm0bO1Tb8gsGZ2FPB9CR5ik4I1fmcsEu13mdAjOh1/MG1nrlh3T+HmiaZVhYmZ/kTjisiUNKNYBda2AKaEO+4gPy7TgyuGrgwg== 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=3ZgfNGx+9873c1ELgPerCrX6m8iklUIZvf5Jq+l/oMU=; b=ubWM9gyQwqNfzH7jgrihMY2mOCNJUOK5EkoMja+ka36mf2L8cKuf8AvT4meVFF2DNPI5RrTUCLfeETYTigkiCtrQKKE7R70xWVbeWufsYULFmD77casH9MQjI0HiQ1l0cm5qRwrX8q2TBpWR7DwgzzIaaK2AB6bndmXguRkw/EV/w1YijnEw1HQjxDH8qSkGfYV6xJ1pKc4NJfKMgbfDGjtgQQpArI9chVS8S8sz+aCLwIy+q0WLslCHePKk5RvkH/RT+QsRcf7jSqcl+t+P/6dDihppt8TflrhuST5LGsXbwYwyNimMBwdZ9U6iPCWc8dvFZSTAUSdGMXVOTBj9yw== 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=3ZgfNGx+9873c1ELgPerCrX6m8iklUIZvf5Jq+l/oMU=; b=L3/C6WNh1IL8ommdN7+1xhdmQoLxi1yZI5h4S5DdIUy39o3ZveEFxQXKOy+X91vD5KPSZ0p7v2Z2/r48zOWCQ0yLb3arO8weYHqhfH885kfHfdegsK5K0HuiQjru46hOWbsfF5lbJ1pDVuwwZ0UAgsiz4yAB4xFAEa2Cxd4ZbXc= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp; Received: from TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:38f::10) by TYYP286MB5182.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:164::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9654.18; Sat, 28 Feb 2026 14:55:46 +0000 Received: from TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM ([fe80::2305:327c:28ec:9b32]) by TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM ([fe80::2305:327c:28ec:9b32%5]) with mapi id 15.20.9654.013; Sat, 28 Feb 2026 14:55: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 v2 1/4] net: ntb_netdev: Introduce per-queue context Date: Sat, 28 Feb 2026 23:55:35 +0900 Message-ID: <20260228145538.3955864-2-den@valinux.co.jp> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260228145538.3955864-1-den@valinux.co.jp> References: <20260228145538.3955864-1-den@valinux.co.jp> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TY4P301CA0065.JPNP301.PROD.OUTLOOK.COM (2603:1096:405:36a::14) To TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:38f::10) 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: TY7P286MB7722:EE_|TYYP286MB5182:EE_ X-MS-Office365-Filtering-Correlation-Id: 169cb54a-98e6-41a0-d692-08de76d97430 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|7416014|376014|1800799024|10070799003|366016; X-Microsoft-Antispam-Message-Info: E9sNp4jlZvTZt/pGc0/d6um3Iw3Ku8T/n0J4FmHp1+v+ntsmx5NqDE7aC8xi1FDPtUV9JFxYjmpR5AiRBQMPfBDsF4+vAVDVBPE3ADBWnDewSOibY1xEdq0wd+EIWIwJuHL1lNpS6chzTtOHiCbPxun+ZnwIVpEHxbAC4r4EHHqBvmOAk5INonlq9SWPCqljg6xqY0HOz68hmGxvoT+3ktTEUmN6kaCEfNNxIwqvo/7iW3RmvAqlbq5bv9RSMbd7U0jVQ7slHAVnA43hZi/ld/Ja/HSQCM6oylyGkvjUrpLdAz+t1kJPadt/MGfRVjXJaef6PhIQ5aZE4c//lH2aRCN2qDmIeOG6WVzcnuRK4K07Y4+sFhTvV9EjWOfKAPJjnu9VHtS2E6yIT18t4BUmJH9TRFhTX541X9UhA5KW0+qAyg3SwcG9XL2E0kc4fUUaYM4aGVyQQSj7nLWbrKSaFTvroApck5njumNEKxYaCLTPMujP2Hzeer0HrfR8jGdI8sA4DSBOA3AnbVtXt4jZkWkD3B1gcuhS8V0P5x5LGp5/U9dQk1vQnEtryJwCJLPoYh4sEZBbbXsnd+RHQtM8x9SboqwhXO8/mZcJEz/8hKcUoiw8NBuQeSunw+t5G0dDQASCA2itoX5QL5caLH1ClzPK3F3cE8xw1ouwNthxLym6hqbNv6FWUuiT0vsWbo56kyqh0OvuQlMJQtisaEuMLt2t1ORqLAPBF7fZpnRb7Lc= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(7416014)(376014)(1800799024)(10070799003)(366016);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?1UbdMq5dR1cvAbmT+Ew980lQ51zBtXX2PbYBKByrq3MNcGSlPBLj8ejxa94q?= =?us-ascii?Q?t8ZWLKlSY4CVY54e107Aqee/NNuEjwEzhD0nD8mA/yTqByUuxLCQTyi1zwKn?= =?us-ascii?Q?qKDdo76G195+eoxeyf4li3AAXHUNkMiA9OpUPvYJgoshKnDfJSc4ZEB+xvgy?= =?us-ascii?Q?CU3vblTDTaUFnUppPez7JvNz7SG1jh+M7NMo1OM0YRKCsqo4t70Khqjc8jYp?= =?us-ascii?Q?7DzVmG2h3iHVZwCcrbOF7H8F1ZpB8rzdoEthmd1Q3upPDbQSiPNiz7MGqgx1?= =?us-ascii?Q?2bzX4r/WYRBFTo6gDnEhI/lW8p2UT0SI4L46LaUl14ShxlFqZfnihbZGJ/5w?= =?us-ascii?Q?R3nQCgnItXJX09fSJ88N9NFDzlia6bVbG4YgZrqaKzYekp8va9++YWp4xeES?= =?us-ascii?Q?ObyCYXdX7//gtPks+jCGIJYleQ/qDykyMBEHYFUT2c+e5LpA+W4jTBXrzMx1?= =?us-ascii?Q?0xQDtX515r0uUhjoPbmOUsWHH0/KW43aRRr1WIEaItlzupMUxou1mwhnIWfB?= =?us-ascii?Q?ZlTjBCdWe1nqVn9dHAplZzvtKeNEep+n199QX2MJ+3oxeSU+yNHslrA+I3xN?= =?us-ascii?Q?3jHtXI3fJf+5ghRyz2x2JNth5m47GkBKKj2UPf6/rpzEyRMTGKpk/TELbWml?= =?us-ascii?Q?qMz0jD3i9+qnoTVvhEkfNVYkTsr+rLZDqxW1MryZlQJIploekZfiqP36riN7?= =?us-ascii?Q?uV9tajq5BD/MnlDgAdc5/t8T2lciDHgZzvMgKzUztuabpZJ2VDC6gJ7IKubo?= =?us-ascii?Q?Vii8IttwLIIyWpa7kHreGBb676lXFQMU6HCIzenJOAeSr5zp+k/r+91QkjVs?= =?us-ascii?Q?yv3q4Ft6F0Ka8CFcVUyhVMP7eDm3/Xc+CR5lHKqjYh9SpwB/QidxQJCCKnc+?= =?us-ascii?Q?xpNR25QFdyEze6qGuQTTPP6Wom4ZUvjRa/c0jRTvp2agUB349gb01/TSX4j5?= =?us-ascii?Q?RQK5Ur0NIZ6l2Jl+2QL5c9+N2Bm/Al/cLtXRYkmBZ8IoOZy6FShpk8L2bmFD?= =?us-ascii?Q?ManhAWmJUkevf52cSpgI6RPyK3oJn39AtdrXlGywQmDaNG/vwWGMhuf8N9tk?= =?us-ascii?Q?CoygD9MtH+3Z2+/v23XrvrI+I5Rg7iXr9fr7d1kAw2NU535RDp3kPMBy+Slh?= =?us-ascii?Q?LT0DEtSl2zFTL7O3MfM+usRQk7ZaRoQVUzV5qCNxl/GQweVa7ZAUVu8gxBXH?= =?us-ascii?Q?UtpXFJGAfKXaK1YFqC6Dcw5rEAyOJljhOR9aTXbxTIzolMyiyS1hHQUZRF7t?= =?us-ascii?Q?oE4/E7OYmQNjf4nmcyJGv7RTDtcPBxTVyxl/+wLkPVjv9iGWfbTDwZ9fwYWX?= =?us-ascii?Q?e/PQTGAmD8c4Df57SOjV9Q/aqSbtlO65lIDNyX8m25OeFc/neidtH1GSKvq/?= =?us-ascii?Q?Q57iBlPctpuwUrI248CmCJjWuGbB2ertEur4gGO0RAZsq7tOIt5iHbIuC1/7?= =?us-ascii?Q?CF9s4vqGEkLMiwkggz0uSuB4JHhQKDLZLammX6QvnNu3hzmmaEEcFfVfzXXH?= =?us-ascii?Q?OKNB5OWDlZW7gSHtxYGgj5KRL6KPVhAv+eiOrgc9d/u4f31MXSopBrjwD3mO?= =?us-ascii?Q?I4w5A+w/l5neMgjd3J5MtoYA8cr38R3yGQ9Cwh5WZQhcYDYdtKuPrnZmveE6?= =?us-ascii?Q?I6a6DBBYYjUza62cKVxIBOTcJuTKbvH09pRxLG9gWXLVCngd4eVxgxI3n1SC?= =?us-ascii?Q?Um1FvT87RzlNoLRMIjBCWCBVE0PsHOf4RbUunz4xM2qCvx1XX+du0D62bw/Z?= =?us-ascii?Q?o0XR4ld3bMUtjbLTXiin1DtuU4eQwrfcBUL5M1Pu4uKY569dYJXT?= X-OriginatorOrg: valinux.co.jp X-MS-Exchange-CrossTenant-Network-Message-Id: 169cb54a-98e6-41a0-d692-08de76d97430 X-MS-Exchange-CrossTenant-AuthSource: TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Feb 2026 14:55:46.2998 (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: X8+2SJl6yyBefX7k18jnd6Zd9TPxuNmiNBdxqF5iwXAqSepBhedZkEsSHTWe7p7C7r9lPDe5RECk74/qGd8w7w== X-MS-Exchange-Transport-CrossTenantHeadersStamped: TYYP286MB5182 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 since v1: - Allocate a fixed upper bound for netdev queues (alloc_etherdev_mq), while creating only a single ntb_transport queue pair by default. Users can later add/remove queues dynamically starting from 1. - Drop unrelated changes from this patch, for example: * remove "any_up" from ntb_netdev_event_handler() * restore the original __ntb_netdev_maybe_stop_tx(), - Store client_dev at probe time so that queue pair creation and removal can later be done via the standard ntb_transport API. drivers/net/ntb_netdev.c | 279 ++++++++++++++++++++++++++------------- 1 file changed, 190 insertions(+), 89 deletions(-) diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c index fbeae05817e9..7437b4580dff 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,15 @@ 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 =3D dev->ndev; =20 - netdev_dbg(ndev, "Event %x, Link %x\n", link_is_up, - ntb_transport_link_query(dev->qp)); + 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,7 +114,9 @@ static void ntb_netdev_event_handler(void *data, int lin= k_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 =3D dev->ndev; struct sk_buff *skb; int rc; =20 @@ -118,6 +135,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++; @@ -135,7 +153,8 @@ static void ntb_netdev_rx_handler(struct ntb_transport_= qp *qp, void *qp_data, } =20 enqueue_again: - rc =3D ntb_transport_rx_enqueue(qp, skb, skb->data, ndev->mtu + ETH_HLEN); + rc =3D ntb_transport_rx_enqueue(q->qp, skb, skb->data, + ndev->mtu + ETH_HLEN); if (rc) { dev_kfree_skb_any(skb); ndev->stats.rx_errors++; @@ -144,41 +163,41 @@ 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 =3D dev->ndev; struct sk_buff *skb; - struct ntb_netdev *dev =3D netdev_priv(ndev); =20 skb =3D data; if (!skb || !ndev) @@ -194,13 +213,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 +227,26 @@ 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); + if (unlikely(!dev->num_queues)) + goto err; =20 - rc =3D ntb_transport_tx_enqueue(dev->qp, skb, skb->data, skb->len); + if (unlikely(qid >=3D dev->num_queues)) + qid =3D 0; + + q =3D &dev->queues[qid]; + + 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 +258,102 @@ 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 ntb_netdev_queue *q =3D timer_container_of(q, t, tx_timer); + struct ntb_netdev *dev =3D q->ntdev; struct net_device *ndev =3D dev->ndev; =20 - if (ntb_transport_tx_free_entry(dev->qp) < tx_stop) { - mod_timer(&dev->tx_timer, jiffies + usecs_to_jiffies(tx_time)); + 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; + unsigned int q; + int rc =3D 0, i, len; =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 +362,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 +468,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 +476,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 +485,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 kcalloc(NTB_NETDEV_MAX_QUEUES, sizeof(*dev->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 +511,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 +560,14 @@ 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 Sat Apr 18 09:10:30 2026 Received: from OS0P286CU011.outbound.protection.outlook.com (mail-japanwestazon11020096.outbound.protection.outlook.com [52.101.228.96]) (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 0816644CAC6; Sat, 28 Feb 2026 14:55:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.228.96 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772290552; cv=fail; b=ioXxFTY7RlA5iEYWcqksbqT2O9wHVbzBsrpcw18ISoussv2xffNajL+W347Wk8jI53U3WA6TjqnWSyPa07eEk/lljXbD83ehX8llUewAUQr1dy0KjwtTFDWKSOOELrDVxkZSpWJWc/lXAv9cLingPxlvyX/Yzpn8rUJYtOiRoEs= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772290552; c=relaxed/simple; bh=YYkz/57aajK5A/fZjhk73b9JxyWQyo7bpOJ9DkuJaAo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: Content-Type:MIME-Version; b=K3fkDUq6yETQnFGimZlM8fASh86W08047LwQrN/EBBDamYWUmepwxyHA2OjReUUNA+WtlGKytfaTHEHyEYAg8rExFKfiqPczfkSq82+TOGF8HL3CMQ+M1csj+oZbxjRfde3shs5nEqHS8j+hP0Vo7+m0qEtLkVy6BNwLju+jHLs= 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=EuxSPmti; arc=fail smtp.client-ip=52.101.228.96 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="EuxSPmti" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=tpmqkMWya0jOURJU4kSa2B76551JD8qNXCLOdK2B1HJqM115gah2bupZZg9P0761S9eG7WZagx+AU0K6uM3dxsppVQ/UQaiR0XBMKmdwqwdySZPtcoEVi4Ur50SXMyW6wtFiENWQd6HfStl2edKF8b+0Ip+HTLyGfCSavgYx/sMbrkXj5O3ukyBEy2r6m/xhHPP95GDGy6HFN8xEkc/qArdz5LDqd9ZU60EYn9AsU5RSTQxzkN3UcKT9/fDMPb0kYfLXRkv9xTLsXtkH4TrMe/XHk+6i895mHXMOtBfQxhMZmF89MOToI1a8vQVKgKaUcBE/GADt0IfqJKrgoaaJ1w== 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=J5xkKyMWyjlAVwKnUGB+fgOGvC+OHlHB7MhJ+HQFSU8=; b=KXBmKZOCdo74GCPOP25qRbyCbzljga/SD6NITbq5d540REbpb7FhffL+VkCo2qMtmYPOIN+tLt7veaMaiOmzAnDUWTwqAZTg7T53WSH22wDKuSG0PNGsb+ebj2Tf9ZE9VZqw7uBzZlWTLRfspU7QoQIl64KiZrhhGVITKZmOqNf5CtENfVoQk2fRwO5XC4IbgkIMrW+NHYfcm6NhUlmNMrLpwGoTRgqMZ9MBwaSSqGZBOQLZGe3pVoM1HJZkKPYVbmgCCQHw2fZgTyMYngMMy0bIeGNR6ncviNkxFNdv5lw3gNeiUrwhgvEnPX0XLMNgZ2dH9QVqo7xcaH1//I9oSg== 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=J5xkKyMWyjlAVwKnUGB+fgOGvC+OHlHB7MhJ+HQFSU8=; b=EuxSPmtic02GTXHRdoCy705AVnFYwN2/rkWKarQdCPzkqxEQ7YnIV1o2APGn6z055TlDfL7ozMQPjlIFw8gjgSfPQ7DcfaZZ171KqtUvKLnE9LmnnN8DAYEyFsW9wGtsW/uZ9sj5Wp/axFKR+EnK937rtrQjS1FD5Pa8mp4eGBk= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp; Received: from TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:38f::10) by TYYP286MB5182.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:164::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9654.18; Sat, 28 Feb 2026 14:55:47 +0000 Received: from TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM ([fe80::2305:327c:28ec:9b32]) by TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM ([fe80::2305:327c:28ec:9b32%5]) with mapi id 15.20.9654.013; Sat, 28 Feb 2026 14:55: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 v2 2/4] net: ntb_netdev: Gate subqueue stop/wake by transport link Date: Sat, 28 Feb 2026 23:55:36 +0900 Message-ID: <20260228145538.3955864-3-den@valinux.co.jp> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260228145538.3955864-1-den@valinux.co.jp> References: <20260228145538.3955864-1-den@valinux.co.jp> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TY4P301CA0089.JPNP301.PROD.OUTLOOK.COM (2603:1096:405:37a::10) To TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:38f::10) 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: TY7P286MB7722:EE_|TYYP286MB5182:EE_ X-MS-Office365-Filtering-Correlation-Id: 909edf0d-c865-43f6-1d8f-08de76d974c4 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|7416014|376014|1800799024|10070799003|366016; X-Microsoft-Antispam-Message-Info: ELVAtFL0sE6Jt0DlZ//uhZZImRXuY9d5a6PHyRDX5F+eIAOUHYnpOazPpmhEW+5ga17VTyqIz+Jm93ki6BaxWvnLCoV9uFwIaKpPsvs3WmhuVnUthnEggiy6UIvgIN5Edraa+Hlgr2iOAlAB3HTzlwIaQBalbz8s3BNUYHBAXZ55RQ91to7FW5sNBWwHBcxXt+s+EQILyjCFTtFIrsVqzuMDqRPTbR30QpvkvoneKeupVQDFA9hP7q/IoH7MLhR6m6rJka6izymWXor9pWcADtrWIv+bIkMgFDe61b/RxHpD+kHk8/JEVYiBsAZNSOf49WrBnQSocwayhKHJ7JKBzCI0/webK72GYRmrTnZYltELCwtJ/YfmyFkjSX7v14U8+E5d+kmaynbOKkD6H95J44EtwfRcO/JvStS+D8z0Gk+jGMhC4TR6mNvmx6VkCW4Nq+2o2sNKZmepuyU3KRuZxA81gzEsUo1pOw/m2iUZUtXFDtB0vsxFvtau9ovsC0mPbphE5JlYXmy3xa3Bgivx/aBmkVF14S/saMV9a8gxvND0sF2uz6kGNq+62dVN2bk6Lc47WmKOpggjfMzB3lG/HmSbUUJnyz7OYtYYNtSugW7SBpcvvVfrvx/9KYvu6niiC72jGOAOHRJtyPUeRg6N+ZiXaeOgjfg3TEKn8PPSQkZCfKQY1oX4UPPtzBsJgws0WJEcCm+3ZVuW5oohYddrBU4uFLCVPaqltSO9lZl1IMU= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(7416014)(376014)(1800799024)(10070799003)(366016);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?Ddv6HNxGdu8CwXf4ovUMA0av8zOsO/Ik3K8D2lnZue0NGWGdyrzMLaMHiKdB?= =?us-ascii?Q?EWfSxE5WMD8Uhx7rg2nfUZbaiHUrK9T6d4yZVYxIHPevj0S2m/2Zgd8Vk3Fi?= =?us-ascii?Q?I44nMwQMRUWneE8lk8tHHdqGiE1ivVcNvdLFGnYl6oeqOjvETKXoXS7RG9OU?= =?us-ascii?Q?MaVTY1QpXcT0EdTCUYsKvO6NCzpSWYD6/vX/+KBDLQpnFPAwrMdnBREio+Lp?= =?us-ascii?Q?SuJBu0sXqJIMzIbTzYdHC3OJtC6T23SaoFykA7CtP5rIsZcJ9vo11MrJkTZp?= =?us-ascii?Q?ejsmsyPOniWAbxYUYV6/M6H7cuGtr8qNc9i0tpW88vmbeKlFxQPfoxZktAkf?= =?us-ascii?Q?WkyBTV2iAbmN/cECiPDucdbiXxEZb5zF4qHJpRkLdTEGTM3KxrvjmeM2Zvb+?= =?us-ascii?Q?GwLpibOyxkqM+TpWEOKAQkvsZ0A28fpqPHf7hMtMU1BEtVQUqQvuKs4TOuBg?= =?us-ascii?Q?ZDFCL/egv6gHmvNkYoeLnlspoWjIv2JoJhxuDzQ882V8MBcazOnRosLQce/j?= =?us-ascii?Q?hwpScyF8SXBIiS4ReopCcErrxrGYh3CUdNNY5ieMkgkKq6IrjxqongUJ8cB2?= =?us-ascii?Q?/Q2iR7cR0eHjE0ngjTwPqoker4m0rPWHTyhVVC0kDsUFNbehabnKY4R7PLb2?= =?us-ascii?Q?316rZ82OxaBxPtU4QMgwBQ7G3M7DPixqmEIR21Y0Fq/A5rnWxgdUyzdsjkbm?= =?us-ascii?Q?Pd1XkQwZFVaFkKHJVTzJh2l7NshjQcFVtPgDCDCqheCaTSKPuXlCuoA0G+p4?= =?us-ascii?Q?lKGHuTO6vOHzGdQ/fkM1ug1Csklxx5k4YMsMzHrSKg7D6ujdnVRGzBm4QKfa?= =?us-ascii?Q?iLXFcnoRAdSgwjM2a/fPrD2s4bwQa8h3EfckT+WKJKowZWU79xF+vLBLiyLh?= =?us-ascii?Q?A2QxkQyeQ4wTn5FGMAVZvHqRgMuk0rJXq94kZnZJIIN5ILEhKGXsjcJThZm1?= =?us-ascii?Q?eC3Fx72zBzgi7sXoepYOcmzuCyHsYS9/3d+5XZzmRLiZJ8w79az+KlJzGnsO?= =?us-ascii?Q?tHsvusyXz2pHQJeWLi+LceNtFOOkkr9TCwE73sFjUulicdUoAW/zw1qIo0u/?= =?us-ascii?Q?FFB3Bg9FboXZU6tq680VrMhHk16QcB/C6Lrj1T5vD3mMXm3wlA53IwYRIWOD?= =?us-ascii?Q?Y3Wp3lcE42PuSKh8TsoDeLQYoSpouW35NY1ZYuHaXGq6gsdvJ+i8eRX2aUXT?= =?us-ascii?Q?brycStQaYnPGAZWOYQP16MczkQw1u5VqXfxhVDTt7wjYePtCy4/dJDGB+2EK?= =?us-ascii?Q?wXcctSa7y50coUxWRJ8S8fPm2JH8Eb2PV1V60uHZ24CMekIiPqRXjqLeVKP1?= =?us-ascii?Q?D60VxLTmKl4rVxfcDqJJzbflJVndxfNLP2YCk7xwo/TyvzkGzpt23VAoIBek?= =?us-ascii?Q?k9gP89DYSJme21oC7orJ2ZRHxCOc5w2CBTPHCUe/kmcegWtD+g0vVOGH6GM6?= =?us-ascii?Q?kr8ZJzLp8wRfJ4vvLBcD9rhkrhBlP7H4TZ2FrgvmuLfqRyMH26cBKO38Z02r?= =?us-ascii?Q?JjU6UBQa+zyV3aue4kA7Kg6+T0trLIyAjFvP6b1w0HBz1U6mVB6lotmtx9kx?= =?us-ascii?Q?wDZU20MAm5b65KRaZbFKGEpd/kgLLW8YA15m5zemrh3/ORvRyDwkNVDJPpJ2?= =?us-ascii?Q?tlhIqClY9zTKJ55jr9cdhXqeDjZmczTd4aG64wbC+7xYef+YdIvIc297NUbX?= =?us-ascii?Q?VGoKKR3/gUDS9ODIAYl1zcG+D1oTUskxNUJ+jPUFbL1mMSMd7BDN2m05uTL2?= =?us-ascii?Q?g/zNQNH+2tQYU9eenBmDEt4ml7SPoELa9+0F3YQpv5tgCWmCUH3J?= X-OriginatorOrg: valinux.co.jp X-MS-Exchange-CrossTenant-Network-Message-Id: 909edf0d-c865-43f6-1d8f-08de76d974c4 X-MS-Exchange-CrossTenant-AuthSource: TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Feb 2026 14:55:47.2667 (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: usFJ0w0cqxtPFLf8MYG/XjKeGWHcf08SNP8ZeX8xbRBdVFhsbipDd0aLbD+2Ur3UVcqV0OmqutH8vuz2oHhmZQ== X-MS-Exchange-Transport-CrossTenantHeadersStamped: TYYP286MB5182 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 --- 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 7437b4580dff..19a3383d86f8 100644 --- a/drivers/net/ntb_netdev.c +++ b/drivers/net/ntb_netdev.c @@ -99,16 +99,30 @@ 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 =3D dev->ndev; + bool any_up =3D false; + unsigned int i; =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, @@ -177,7 +191,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 @@ -218,7 +235,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); } } @@ -269,7 +287,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); } } @@ -305,12 +326,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: @@ -331,6 +351,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 Sat Apr 18 09:10:30 2026 Received: from OS0P286CU011.outbound.protection.outlook.com (mail-japanwestazon11020096.outbound.protection.outlook.com [52.101.228.96]) (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 27FF844BC89; Sat, 28 Feb 2026 14:55:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.228.96 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772290555; cv=fail; b=Y6xy1MEaDmzmEXN7hPZZw2u0+jfCThjLeYfPOzsJ2wE3C1HpRxkxutE3kUiLdSAstjtrayGMw3tnlSv0BIZs4I5Hg24dL6240XOUJAePkv7hLR+BSQx1SBDiNuAQ/eFZSwBbUDRxSQQcLLUKiHOS18qFhKPlsiygfHA64knIWto= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772290555; c=relaxed/simple; bh=Rs/ureIuz5rpZWNFJATPsZPW2/ha1dch4gJGxyvGaW4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: Content-Type:MIME-Version; b=omzdbauyxAz/1QcDxUbLZdE4c+Aq67aWC9gix8jKhbF+rooxUvJPi146IobKil2jQ3PTPOoihqWPGCILZVST6S5Cs4FLyEJIMASCUTIQTtgfeFjOfpwwxkNv3/Hf41lEpD6qwk2W9SL5QMYY34lbKL/QgiYITBhlqIZwPQWYZAk= 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=e+MQ0t1D; arc=fail smtp.client-ip=52.101.228.96 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="e+MQ0t1D" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=kQMC5jsztpbyRda/tM5hHtnjQTWmM7rXXtZTbOBtbKIAYOqBye4dYKWXHla/kxMZXF+z++I54rDUL3XDAbciGauNq/ar6mgfzTDsj+Fa5K839iY4DO5CYcKPlsSO9CJ8x/+pq1ZHF1KnEReev+93gRDyVV4eetbwzq4nlbjaNlZDjN3k1cX25XsmevrDod+kJVcEMsJYblXiYU+43grAsw4RwlQ0CNva4WDgm+EB/F3NR4Ry/9iJjddszYp57ajRIJ7jtQKjWFU9vJ6uEe0ZkzSpr7SIm41sv/0t0DQFVHlVwMyoy7atr/dTUEvsaxUbbKWeOExN96W59dcf54WYmg== 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=0zZttERInpH2212CkOMsuFpRsaBRmoT7Aty5F6mfMvI=; b=Gv6Vjha+l0disY65/8aqcwaMnuuZPi3T5xeqLiifCN693O8Qj7CmvS8ENebiiKxUCKooJxDnsJhqyJLwcUG135IKAYLq3UkuX4xGKP9vP0oK9WV6rSEfc0yje7H1j00hdCkjXGcBDNEOA1l4hVyHtAJcRG0AQ1OOvYlnhBq67j5frdWcA0yDesE2jW+qGI3E7RMIuz75Te4KPjP/LbZ3dpMzOvGbYetbDJIwGgy3dcSEJ8lHQ9c43WetIvVXy1HwOsvGdLHSmgy/DivraqoPbBIiqLdCR4x/y3ufS4aRr8X8uanMjsPnoURQKJMshZcdTFOw1zSs1vTApms3irdxqw== 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=0zZttERInpH2212CkOMsuFpRsaBRmoT7Aty5F6mfMvI=; b=e+MQ0t1DP7CwM7trscsqdFo8Gf5lezkipVuuVNbzU8Sv/tsZnzxKZx4OSxe13V+BkGB6FDISQmUgmw7pLotZmOHajotvPrjBkHw0O2r+X4Zky2lNr1ok6xWwltNAO7BSyK9eFEvpiexOBI5rbOaWHlRUdMTmlK9DGlcw5GG+Orc= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp; Received: from TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:38f::10) by TYYP286MB5182.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:164::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9654.18; Sat, 28 Feb 2026 14:55:48 +0000 Received: from TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM ([fe80::2305:327c:28ec:9b32]) by TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM ([fe80::2305:327c:28ec:9b32%5]) with mapi id 15.20.9654.013; Sat, 28 Feb 2026 14:55:48 +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 v2 3/4] net: ntb_netdev: Factor out multi-queue helpers Date: Sat, 28 Feb 2026 23:55:37 +0900 Message-ID: <20260228145538.3955864-4-den@valinux.co.jp> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260228145538.3955864-1-den@valinux.co.jp> References: <20260228145538.3955864-1-den@valinux.co.jp> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TY4P286CA0076.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:36d::10) To TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:38f::10) 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: TY7P286MB7722:EE_|TYYP286MB5182:EE_ X-MS-Office365-Filtering-Correlation-Id: 067a878b-068f-49d1-b0ab-08de76d9753c X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|7416014|376014|1800799024|10070799003|366016; X-Microsoft-Antispam-Message-Info: 78Fzm17m0ys5DyReq2kApic6gok4RwiiZse25v+koA8qdPIDUIj9kWl0ji2F67HSwoE5RYRVxsV+oL4aQS352GB4+dtRHZ5ikm+0bApm422/RdBvnI+2XMEwIDpgTYiNVRzjw92pHoLrTybIQiApt8W9scMs2N4SYnbbRoS9KRiJ0XVj15kaVUPInc01x9EMthE1uzrkIKydbrjcl3lhb1qH5Byhn/aoT5ZruSYG9m0cdrRKHVBFXiD7lokdxqWvfQl/OrWYSl3T8LLXvftDX5CPUARE5Jl6aUSlb57MVuljwYmEY6kKpOjZMfPmkhJPceYgLWl4ZGnHPE6fxUlTINd0eRT4sTg3/LwC86BiWFdxTKhC8+dAQQ2458sonGZ+gzPH0u3f3bPYnH5w7lI+AlPQKxDBZ1KVWhROkYiNiW6y0sGfX/BSsPhS64STXbSh/DXLibpa5G5lOGghth2+uuIMWvYvUiU430h+LeStMhXnXsQ8zfYX5Bj/Hj8JxshDFpLg/Rq5d4owYQ1V5vWOW1xzcUWjTfmV65CulS6cK95FYxn5FKZ7ObAvv8Un3T5Kkbm3b+l2kmf96eUNYTa0SIbLzi56QjQpCBcymnB7wSRNxX2YJkRF8hw7eaHrSba0WeYYIO+s3pm7q2C6MHNf7gli7ewRBWNWBb6yt7BbH+k2UCzUTQ8ywYFYm/4AS+8UxS3qAUrQhxi1MZLmJp1zAocXHhQJNxuIPlsaIWllgSc= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(7416014)(376014)(1800799024)(10070799003)(366016);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?zUwN8Xec5bayQkNueW8hJbPAj7VZYwO270UZHQ1L8obFkZnzamE9gSaWGyGr?= =?us-ascii?Q?4yqvMwFTGuxLmAxqf4tnhdqYiVbCOUjtKUiz21v9Qevisks9lAOgiVzJvJdM?= =?us-ascii?Q?7oeZGoAS9tWGGaOBBmwapSklXSapLNcJJSt8qX8dWmYlf7Y4m+hXrORaD1ve?= =?us-ascii?Q?fJAYJ4xl4CzjIRcC21IR0ixmBDKgVExJu1BfBV3625egZFQCsAmSnLB8Pmt1?= =?us-ascii?Q?kOaHA6bQgGI5Ky6G5Cqlu2AfsPrML7uCcUPIlAmm32o7Wz4o6A4XfCs9mrtg?= =?us-ascii?Q?mJUbYEkFPeEDF2Judp9R+RoDhDHH3I7P56aHKvlvXHemPEIQIiXayXV6ywBD?= =?us-ascii?Q?rcjg00jomw1GQRoTAlm7kuiO3DvTvUx5Yj+z0kc4laXPZnhCw1Kx0Wdq96iU?= =?us-ascii?Q?7ZMfWCVxKnqDbwbglVT/YEDX+Bl1HwWpO6a9JtAO08dqYT0j6NyEtAh3Pgyn?= =?us-ascii?Q?FXN1fx4LyUyhPe5iNSDOg/bNWiNLEtoliAV6Fv7NaViU/+tkeuTjcDaWFasW?= =?us-ascii?Q?5gqXNf8S+8hkB8P7xEzNrrSGi224HpWoBOgDUJkQV1wKJkaysapzolTMVnG0?= =?us-ascii?Q?x5bTPOjzHZxVPDhK1FvlDA9EOlMCO7pwTZ8s5vOJURPLVztu7bAnwbl9XEGH?= =?us-ascii?Q?89v4/PZmBRLUr2Js+awMs1ezf6lPhDf3fain7U0u6MI4jLp3sr1wQLFznkOk?= =?us-ascii?Q?6cOo0Ow8vUQy5xVWDIm1mMc2dK2B/5guoGU+kiterMQLuu2dX+wOwQ5yKZEM?= =?us-ascii?Q?1Zed9wlX3vc4I4tLvhLbZyYpTMtilE0iASNrIEcKt9td5ym3Xuh2KcxysjDx?= =?us-ascii?Q?kUsoJPhjrBYILWaNAPtOw23NJh/JY8fwq1H04KB7FHBiM1E/L+3igzw8jBy+?= =?us-ascii?Q?/krwSH3qNfKK4acVtHFKFhqRT7AcKqP18B9tCaOlhArpYjFKEOVAPb+VYOZO?= =?us-ascii?Q?PGr+i/VtRvD+QdYNInVhE4vbvF0f0hBEYfSDiR4zBIqXtEus94qc0aSe9ysG?= =?us-ascii?Q?thw1CzTC6rfEYQWiiO5KBKldm9A/SRSVub7B0hebEioel4VgjQS0/LPT7IvQ?= =?us-ascii?Q?s7vPalnxNQuHUydUkj2a+7bARdXCFoOiyAZ3aJlHcK5sm/T/IdsrJ/L9pEL2?= =?us-ascii?Q?T87jPpuuGXdZU8fMrpKd06xru/+S3Ete4zVehdEY8I2pFpXlLpVyPJ4Q00lR?= =?us-ascii?Q?JM7qaT1W09CMYLvi25Gdpdg+OEX9CeU8nOea4chcdTMEDbjiDmmfTEC79kP9?= =?us-ascii?Q?tf1tqqdR4x09ZasDEYIZyOB58bp3u781Qvi4+XxrsdK57VA2052zflozC5ya?= =?us-ascii?Q?GYJFIaW6wdMIJyYkE8mHtgYyfFYSApDjZjhcKzvy1r+nZgJZs2SJPg9XsBzR?= =?us-ascii?Q?q4OL2zzgx8Ebiykx7g9zSBxpqc73DRrUGCsfczbl//ITV0D/V7OPnXi98kwL?= =?us-ascii?Q?+ypyS1st45RHF9m2xNApdbWv3WsmrHawapI9hsf7ucxbkEhKbJz/+x7sLnZJ?= =?us-ascii?Q?N2K/vqrlgsCATffgEXGmY/O5pM0wRh7EyaBBmcCvWcGwnKDrSYQyMgJ5mAMe?= =?us-ascii?Q?tLcqFx9EAmqlV/loBmYPWgGejaB61JwinXSq7Laau0dH5yulOvuiO8d2oh0w?= =?us-ascii?Q?joLfVp3Nf6DL9s0G/Hr2WutfavkxQ5P+Kk0Fp5WUW1BvTBiiBfj/4yVB8Rsc?= =?us-ascii?Q?P3fnq1AaNHjJXM64mXIaxd1A39pa7eI82HkDaX+5DQiMJvm/6Jw6tNspLLZO?= =?us-ascii?Q?+W3hHOy6xuK9SGRtYhwsIN12b6sMCpGdh4+bpX6KEWMAO+VkGAM1?= X-OriginatorOrg: valinux.co.jp X-MS-Exchange-CrossTenant-Network-Message-Id: 067a878b-068f-49d1-b0ab-08de76d9753c X-MS-Exchange-CrossTenant-AuthSource: TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Feb 2026 14:55:48.0588 (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: N4GoqmqfJVMz4PU3t7iCbo8fL2bJznnPUVOQvKzB8ZrtedonJf6WUpC4itK1FObIn+GTeZZMT5F0FG421kFFOw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: TYYP286MB5182 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 --- drivers/net/ntb_netdev.c | 99 ++++++++++++++++++++++++---------------- 1 file changed, 59 insertions(+), 40 deletions(-) diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c index 19a3383d86f8..6aa59316569c 100644 --- a/drivers/net/ntb_netdev.c +++ b/drivers/net/ntb_netdev.c @@ -94,24 +94,12 @@ 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 =3D dev->ndev; bool any_up =3D false; unsigned int i; =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; @@ -125,6 +113,56 @@ 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 =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) { @@ -299,28 +337,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; unsigned int q; - int rc =3D 0, i, len; + 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); } @@ -336,9 +362,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; } @@ -347,9 +371,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); @@ -358,12 +380,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 @@ -429,8 +449,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 Sat Apr 18 09:10:30 2026 Received: from TYVP286CU001.outbound.protection.outlook.com (mail-japaneastazon11021076.outbound.protection.outlook.com [52.101.125.76]) (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 77AEE44BCB9; Sat, 28 Feb 2026 14:55:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=52.101.125.76 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772290553; cv=fail; b=li/fbsktVRzvlIPTnB6uJVeQEd0ncMEVrfAjQfORgYxZHSMP6NdrBHfI9O9jXV3zUyugeuF63j7D89LOiwVhYcDiEW4HZxUYKU0HQ+P8ncb89LfD+3Ou9vu68xVuo5kJxtqH8NNM/cvsEqJ9YkLLd1tPkyP5YXEKbbRCSfdGUP4= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772290553; c=relaxed/simple; bh=zQLa9bOnoHCwDeWYTV/rY8bZ5b5dl5x4sZDEVROpOa8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: Content-Type:MIME-Version; b=njFuL304fakutloqBzbytKfy/kFr8zwRxi7Qe+9C6SoW9USwH/LvybrASf18qTonuU8RfVdPhMkRYVrEtY7KxQXK91XVhguwOJjjhe5ZXqbNBfGLfpyRoRLJoiIm/a879bozOEzHUoaIi+/VCvMiZdsm3XwnkDyWEk2Hv/8lygk= 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=Q9vSWcg7; arc=fail smtp.client-ip=52.101.125.76 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="Q9vSWcg7" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=r2D5dgi66JtKLm+Vi+COhxQnSnGzskz2WAiLzAlviw66xplj6vj0OciDj/cAoqnqDnBZgpeQGUnjRkW7LuJRAveUfmFidBUfruW/mIZ6sIvmROXOfw0mTPOmUBZur+KaX3kIZBsj3e05HGr+e3mIsrjlEtvVOQ3EhhMNA0Ad0OSh/D2QIuSIk7FejpYwXUiT0QrpCGTT5Ix3rj5w4xaN+a6heKOzpmUiCujsUSE9TTDdre46h9G32+TogKHJB+qW8YjZtO++xlAUfqGNExSNQ482Ce+6fDhtmznjdVMhpcA/PNpVPDYmX3LSmsEPfujm9g0h0/DIc+po2yPJzytvmg== 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=ZY5C4X9dZy+w/CE2+h/nTfa6h78czuprcim2Y5EaD/o=; b=GuYmAAgptXsxDKN1tIJzYcoQi+iJlgqJz4l1Q9KlkNSbZjjRoi13fyycn2cUkl9yaWVVigV/siIORhaZOGLkP8CCududBlXE+4+yGRqhllkjYHBDc8k2SeMyt5/+EGoDRtgFldwE6wq/wmhwDoR6ZoMQ9LBybL1tIq9ZVBamN0rHDiPGj9lGNMEWMkzjr193NZOxB5ZchLoqWg+n/oH+SZxixQPwXiqgrUCMCaJd72uhGFFplbR222O9sxX7q9vo0rwtS47nZg5FFjUNae4r2k0Ta5LWYOOIfISDQNWlpoCWb15BGc3gP6K3Hvc6UBDUodyQY1eXiYSm2Yan0qBf+A== 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=ZY5C4X9dZy+w/CE2+h/nTfa6h78czuprcim2Y5EaD/o=; b=Q9vSWcg7BMbtFSQNjMV6RuKUIa2mIu67VmxJkjaZzyGdwCZnedKXoQRh8v3FOxHF3wSOFtx8MCrcPdZbNKDV4deSpNt6lSU4t5g7Q+GrNGV9PmI2BrQtlLNzS/FzYG7vGDWDGisG9AH8SqV2oU+52I/+BmLSETiPE+UQSvItHSU= Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=valinux.co.jp; Received: from TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:38f::10) by OSCP286MB5596.JPNP286.PROD.OUTLOOK.COM (2603:1096:604:3c7::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9654.18; Sat, 28 Feb 2026 14:55:49 +0000 Received: from TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM ([fe80::2305:327c:28ec:9b32]) by TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM ([fe80::2305:327c:28ec:9b32%5]) with mapi id 15.20.9654.013; Sat, 28 Feb 2026 14:55:48 +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 v2 4/4] net: ntb_netdev: Support ethtool channels for multi-queue Date: Sat, 28 Feb 2026 23:55:38 +0900 Message-ID: <20260228145538.3955864-5-den@valinux.co.jp> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260228145538.3955864-1-den@valinux.co.jp> References: <20260228145538.3955864-1-den@valinux.co.jp> Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: TYCPR01CA0151.jpnprd01.prod.outlook.com (2603:1096:400:2b1::7) To TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM (2603:1096:405:38f::10) 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: TY7P286MB7722:EE_|OSCP286MB5596:EE_ X-MS-Office365-Filtering-Correlation-Id: 1ba7fdab-f3ae-44df-f484-08de76d975b6 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|366016|1800799024|10070799003|376014|7416014; X-Microsoft-Antispam-Message-Info: Fn5ddDTnRqkidJlkl3BKaPH5741wj+rPo6NBcxFVy3gOmP9XdT6zhZJZpLDmrkRLXBt3INwIzx9UrVv7PObPW72cnFF+DDNb4gdE01GTf/dINtLutxMpZkysBAXqQI/G5W3dquHuoelI16K/ClJU+rUL66aSoRGNsK04tzULT7tJnCxToKZrtKO6HSqaf/byXi0gdQxS+YXTgJaBXi2kC4yH8zRUkhvXSZbP7jVHylQdGOnIW1X4PdOCQEwywbm7YplHnTuc9Xh03Nv/OFI7OBC9d5eIiz7iV/17H+NsOkYk/ola6/Nb444LgKaCLY7N26J0mNMdaMrjX81toTBxaxJJ8Dar0tmgxgwmzPJ79dBl3wAu2wofkpJu8HDSjldMIWvQA2PUiN2oFrg4h2vL18BX6dPhNRQwfkihHqaOYDSOGSm9FMavlH7Aslw+IyLR4Yt4dfy9xQX3epL0nfPxlADAFSAyWHifSvRVum6lzQMoj7O1VP/JwGE1QIaVZf1Gy2AQune0r83h1grdADypX94oVpeEe9GGpPbTyO40hUdD9MGkY8HDOosZNwrKFRxXnzhklbXn7ECmiWdOw3ZU6wbVLh3O6kg7FwHNbFA/ucN0IkerK9EZnA1ecER5y9q8VTp4fic+WpzgGo297QDOMF17ib1O5o/vJtqaHYgFJfxnkykgbJPjD4FHenZYKv2Iu4uxRZ03RECLZg7nad12rCJVo1ln3aMp2A6VmdjALA8= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(366016)(1800799024)(10070799003)(376014)(7416014);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?gIl7jiL02EybEEkwR9Ew5ZGlM1ERFJsohz/cI5c/Dd+SjPAlAUxy5NVO9BJC?= =?us-ascii?Q?3ku1mjXLHZMmEVM3DMMRGq2NCCNul9PQ78nzPNMohfJGwSTlq/qRaq3W9J2s?= =?us-ascii?Q?nUtcSZmxPfJmtBySd0D95XYenmu7azsjqF/BVUse/bZsJ93EjM9swH3U9ixC?= =?us-ascii?Q?cTSFRXOKnZf2bZHYtkqWQp3GEBcHRrsHgR5X+tDymE2C5P2bK93zjIOryDBF?= =?us-ascii?Q?sgn6AL0KZZX2xYwUhKvtPW+qARG8StdnYFO1xbWTTpxNwMbQJ9viT65qu4l2?= =?us-ascii?Q?UcmXgnUgx9z/g9l8rLXbOspfz/31vauHdY49BPIakZwM+GSAECpYBhVEZydv?= =?us-ascii?Q?o0UpF9uqtVxq5HOPeMoQyGGl6IFS/B7m8DOMk53KLwRDSSTRonoAy707z296?= =?us-ascii?Q?W4p4zoLrl+oXCij8rlhcjIlexPiRh85JciqPMet7gH9k1DtSA+eDDicRcKP7?= =?us-ascii?Q?D1QpVw3Rg0z2+HxXdYxK5f1aiw2KllrKuC03U30B/i5uZz+pOeAYxi6VPcop?= =?us-ascii?Q?tBGOI6h8DYGbgjHZT382BZ69Jvek6xegi8dFi9Sc0RS/sPHaSZDpD0+7+7Fi?= =?us-ascii?Q?8OEjN9YD2hSayYtnnscnFXr9i0Fx3z661dB0lsWQsxGfXx+ExKUOEkhsp93a?= =?us-ascii?Q?OKlEt/EsqmsTdkIWO1K6o5CwhUv67/J4BvKibInNHX5AHPn4osmRhFvqZfje?= =?us-ascii?Q?bxbAamtnXAMRQejyPbaS+SdrzBB5IV3q1cBIIiJI+hL3hjFua3TiUkRmXeYe?= =?us-ascii?Q?HqrOuaprZ1xBs9ASFlkVPSnTlV2ro3Nzui8hPp2IYzYcZEv2iNhfsiFyPw6e?= =?us-ascii?Q?ZdaYjjHhiwzJefUQsaELa0M/NgfVUwKMUSkTmSIUllwzWT+r141bf4SECGz2?= =?us-ascii?Q?QHtcTOqrTSyi+CH386dFmTXQ1pxRPoKv9V+yeTlprZ3R8PwDb4L+FVT5JaDG?= =?us-ascii?Q?DzJkCMwlgWkvWt7ou5+3qATL5yq3PM1po1VQPnJf23BH+EmXeEG8f9EduMst?= =?us-ascii?Q?v1EnvPENs1w1zWTSk87wvVjxxRDXnwqssQpubw1QqyTMVxwxsv9TBSXCKWjx?= =?us-ascii?Q?dCdrKgSy8mV+jcUJyQMwSHBIriPIdfDTVE4WD38iDh4Eg4lVfXAlXrf/LmHI?= =?us-ascii?Q?FrYtJ7srDzQlT8rx/niWRl9ARSI/uOmpDRt5HnT/ZFbvBkQL/Z92/VzTvREb?= =?us-ascii?Q?qPmMzIZaTcFoM9oG8N5WKg/ip4vD1V9s+xv6SXApt9FINoZBNdT2QqU73bIA?= =?us-ascii?Q?J4hRlW9/NYgOMaIFjJBpd0RupypyC2HGUuJhtMRE2BgNqoJ0I7bgUaV9Nhxx?= =?us-ascii?Q?EE+4H61S3uC9vslzlBYvDgo5rBR2oGt/xzueq4zWtVBklIeg1gy8lqtaTWJk?= =?us-ascii?Q?LDjlBtsQCBtpJ3PWKsK0pRQ4L1HQonGCVx3Tlc312eW13vWVmpnSzeaBwe7U?= =?us-ascii?Q?QTj5PoQXybIPFJaII72StPo9gAeF8qTzfAEcg98r0tSSztCUSAd5rVHO1E/G?= =?us-ascii?Q?8geGxcTwH+xlPBFZVptOFPxP+duHqbmPQqKg7eBb2ZNSO1Ks48FfBHZD2fpC?= =?us-ascii?Q?cMJcY+VWAFEwBBpqo5UsyzYyZ4BLPRkwYB11OketDkAzrKkx8AXg8iuQP+4w?= =?us-ascii?Q?+afUX8Lrz2pr77ukfQaqNLLkDTdFdYKf/H5tH1pR/fzJxaDim4UrQgZR7Iy1?= =?us-ascii?Q?P7saJbmTFEO4l/6Y8jD36ai6xy2xmKqiJABlgfwGemje9vB2UmAsA/5cQCAw?= =?us-ascii?Q?RHZ/fuuora0iwsFQ3YOjDjqWugKRkpIPeFU/jIIToVAXYhK39UOS?= X-OriginatorOrg: valinux.co.jp X-MS-Exchange-CrossTenant-Network-Message-Id: 1ba7fdab-f3ae-44df-f484-08de76d975b6 X-MS-Exchange-CrossTenant-AuthSource: TY7P286MB7722.JPNP286.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 28 Feb 2026 14:55:48.8771 (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: Jm7XzqMZ71duny4CrU4gArxohhYKwo7noEGwsc3yHxPyvSHIwEWsbk0QGEbNOWhLCqoi503+MSeMMGzyyTFFBw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: OSCP286MB5596 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 --- drivers/net/ntb_netdev.c | 147 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c index 6aa59316569c..c2b1886775bf 100644 --- a/drivers/net/ntb_netdev.c +++ b/drivers/net/ntb_netdev.c @@ -113,6 +113,24 @@ static void ntb_netdev_update_carrier(struct ntb_netde= v *dev) netif_carrier_off(ndev); } =20 +static void ntb_netdev_sync_subqueues(struct ntb_netdev *dev) +{ + struct net_device *ndev =3D dev->ndev; + unsigned int q; + + if (!netif_running(ndev)) + return; + + for (q =3D 0; q < dev->num_queues; q++) { + struct ntb_netdev_queue *queue =3D &dev->queues[q]; + + if (ntb_transport_link_query(queue->qp)) + netif_wake_subqueue(ndev, queue->qid); + else + netif_stop_subqueue(ndev, queue->qid); + } +} + static void ntb_netdev_queue_rx_drain(struct ntb_netdev_queue *queue) { struct sk_buff *skb; @@ -464,6 +482,8 @@ static const struct net_device_ops ntb_netdev_ops =3D { .ndo_set_mac_address =3D eth_mac_addr, }; =20 +static const struct ntb_queue_handlers ntb_netdev_handlers; + static void ntb_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) { @@ -491,10 +511,137 @@ 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_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; + bool running =3D netif_running(ndev); + struct ntb_netdev_queue *queue; + unsigned int q, created; + int rc =3D 0; + + if (channels->rx_count || channels->tx_count || channels->other_count) + return -EINVAL; + + if (!new || new > ndev->num_tx_queues) + return -ERANGE; + + if (new =3D=3D old) + return 0; + + if (new < old) { + 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 out_restore; + + /* 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; + } + + goto out_restore; + } + + 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; + } + +out_restore: + if (running) { + ntb_netdev_sync_subqueues(dev); + ntb_netdev_update_carrier(dev); + } + return rc; +} + 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, + .get_channels =3D ntb_get_channels, + .set_channels =3D ntb_set_channels, }; =20 static const struct ntb_queue_handlers ntb_netdev_handlers =3D { --=20 2.51.0