Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-ntb_netdev-add-multi-queue-support'

Koichiro Den says:

====================
net: ntb_netdev: Add Multi-queue support

ntb_netdev currently hard-codes a single NTB transport queue pair, which
means the datapath effectively runs as a single-queue netdev regardless
of available CPUs / parallel flows.

The longer-term motivation here is throughput scale-out: allow
ntb_netdev to grow beyond the single-QP bottleneck and make it possible
to spread TX/RX work across multiple queue pairs as link speeds and core
counts keep increasing.

Multi-queue also unlocks the standard networking knobs on top of it. In
particular, once the device exposes multiple TX queues, qdisc/tc can
steer flows/traffic classes into different queues (via
skb->queue_mapping), enabling per-flow/per-class scheduling and QoS in a
familiar way.

Usage
=====

1. Ensure the NTB device you want to use has multiple Memory Windows.
2. modprobe ntb_transport on both sides, if it's not built-in.
3. modprobe ntb_netdev on both sides, if it's not built-in.
4. Use ethtool -L to configure the desired number of queues.
The default number of real (combined) queues is 1.

e.g. ethtool -L eth0 combined 2 # to increase
ethtool -L eth0 combined 1 # to reduce back to 1

Note:
* If the NTB device has only a single Memory Window, ethtool -L eth0
combined N (N > 1) fails with:
"netlink error: No space left on device".
* ethtool -L can be executed while the net_device is up.

Compatibility
=============

The default remains a single queue, so behavior is unchanged unless
the user explicitly increases the number of queues.

Kernel base
===========

ntb-next (latest as of 2026-03-06):
commit 7b3302c687ca ("ntb_hw_amd: Fix incorrect debug message in link
disable path")

Testing / Results
=================

Environment / command line:
- 2x R-Car S4 Spider boards
"Kernel base" (see above) + this series

TCP:
[RC] $ sudo iperf3 -s
[EP] $ sudo iperf3 -Z -c ${SERVER_IP} -l 65480 -w 512M -P 4
UDP:
[RC] $ sudo iperf3 -s
[EP] $ sudo iperf3 -ub0 -c ${SERVER_IP} -l 65480 -w 512M -P 4

Without this series:
TCP / UDP : 589 Mbps / 580 Mbps

With this series (default single queue):
TCP / UDP : 583 Mbps / 583 Mbps

With this series + `ethtool -L eth0 combined 2`:
TCP / UDP : 576 Mbps / 584 Mbps

With this series + `ethtool -L eth0 combined 2` + [1], where flows are
properly distributed across queues:
TCP / UDP : 1.13 Gbps / 1.16 Gbps (re-measured with v3)

The 575~590 Mbps variation is run-to-run variance i.e. no measurable
regression or improvement is observed with a single queue. The key
point is scaling from ~600 Mbps to ~1.20 Gbps once flows are
distributed across multiple queues.

Note: On R-Car S4 Spider, only BAR2 is usable for ntb_transport MW.
For testing, BAR2 was expanded from 1 MiB to 2 MiB and split into two
Memory Windows. A follow-up series is planned to add split BAR support
for vNTB. On platforms where multiple BARs can be used for the
datapath, this series should allow >=2 queues without additional
changes.

[1] [PATCH v2 00/10] NTB: epf: Enable per-doorbell bit handling while keeping legacy offset
https://lore.kernel.org/linux-pci/20260227084955.3184017-1-den@valinux.co.jp/
(subject was accidentally incorrect in the original posting)
====================

Link: https://patch.msgid.link/20260305155639.1885517-1-den@valinux.co.jp
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+391 -104
+391 -104
drivers/net/ntb_netdev.c
··· 53 53 #include <linux/pci.h> 54 54 #include <linux/ntb.h> 55 55 #include <linux/ntb_transport.h> 56 + #include <linux/slab.h> 56 57 57 58 #define NTB_NETDEV_VER "0.7" 58 59 ··· 71 70 /* Number of descriptors still available before stop upper layer tx */ 72 71 static unsigned int tx_stop = 5; 73 72 74 - struct ntb_netdev { 75 - struct pci_dev *pdev; 76 - struct net_device *ndev; 73 + #define NTB_NETDEV_MAX_QUEUES 64 74 + #define NTB_NETDEV_DEFAULT_QUEUES 1 75 + 76 + struct ntb_netdev; 77 + 78 + struct ntb_netdev_queue { 79 + struct ntb_netdev *ntdev; 77 80 struct ntb_transport_qp *qp; 78 81 struct timer_list tx_timer; 82 + u16 qid; 83 + }; 84 + 85 + struct ntb_netdev { 86 + struct pci_dev *pdev; 87 + struct device *client_dev; 88 + struct net_device *ndev; 89 + unsigned int num_queues; 90 + struct ntb_netdev_queue *queues; 79 91 }; 80 92 81 93 #define NTB_TX_TIMEOUT_MS 1000 82 94 #define NTB_RXQ_SIZE 100 83 95 96 + static void ntb_netdev_update_carrier(struct ntb_netdev *dev) 97 + { 98 + struct net_device *ndev; 99 + bool any_up = false; 100 + unsigned int i; 101 + 102 + ndev = dev->ndev; 103 + 104 + for (i = 0; i < dev->num_queues; i++) { 105 + if (ntb_transport_link_query(dev->queues[i].qp)) { 106 + any_up = true; 107 + break; 108 + } 109 + } 110 + 111 + if (any_up) 112 + netif_carrier_on(ndev); 113 + else 114 + netif_carrier_off(ndev); 115 + } 116 + 117 + static void ntb_netdev_queue_rx_drain(struct ntb_netdev_queue *queue) 118 + { 119 + struct sk_buff *skb; 120 + int len; 121 + 122 + while ((skb = ntb_transport_rx_remove(queue->qp, &len))) 123 + dev_kfree_skb(skb); 124 + } 125 + 126 + static int ntb_netdev_queue_rx_fill(struct net_device *ndev, 127 + struct ntb_netdev_queue *queue) 128 + { 129 + struct sk_buff *skb; 130 + int rc, i; 131 + 132 + for (i = 0; i < NTB_RXQ_SIZE; i++) { 133 + skb = netdev_alloc_skb(ndev, ndev->mtu + ETH_HLEN); 134 + if (!skb) 135 + return -ENOMEM; 136 + 137 + rc = ntb_transport_rx_enqueue(queue->qp, skb, skb->data, 138 + ndev->mtu + ETH_HLEN); 139 + if (rc) { 140 + dev_kfree_skb(skb); 141 + return rc; 142 + } 143 + } 144 + 145 + return 0; 146 + } 147 + 84 148 static void ntb_netdev_event_handler(void *data, int link_is_up) 85 149 { 86 - struct net_device *ndev = data; 87 - struct ntb_netdev *dev = netdev_priv(ndev); 150 + struct ntb_netdev_queue *q = data; 151 + struct ntb_netdev *dev = q->ntdev; 152 + struct net_device *ndev; 88 153 89 - netdev_dbg(ndev, "Event %x, Link %x\n", link_is_up, 90 - ntb_transport_link_query(dev->qp)); 154 + ndev = dev->ndev; 91 155 92 - if (link_is_up) { 93 - if (ntb_transport_link_query(dev->qp)) 94 - netif_carrier_on(ndev); 95 - } else { 96 - netif_carrier_off(ndev); 156 + netdev_dbg(ndev, "Event %x, Link %x, qp %u\n", link_is_up, 157 + ntb_transport_link_query(q->qp), q->qid); 158 + 159 + if (netif_running(ndev)) { 160 + if (link_is_up) 161 + netif_wake_subqueue(ndev, q->qid); 162 + else 163 + netif_stop_subqueue(ndev, q->qid); 97 164 } 165 + 166 + ntb_netdev_update_carrier(dev); 98 167 } 99 168 100 169 static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data, 101 170 void *data, int len) 102 171 { 103 - struct net_device *ndev = qp_data; 172 + struct ntb_netdev_queue *q = qp_data; 173 + struct ntb_netdev *dev = q->ntdev; 174 + struct net_device *ndev; 104 175 struct sk_buff *skb; 105 176 int rc; 106 177 178 + ndev = dev->ndev; 107 179 skb = data; 108 180 if (!skb) 109 181 return; ··· 192 118 skb_put(skb, len); 193 119 skb->protocol = eth_type_trans(skb, ndev); 194 120 skb->ip_summed = CHECKSUM_NONE; 121 + skb_record_rx_queue(skb, q->qid); 195 122 196 123 if (netif_rx(skb) == NET_RX_DROP) { 197 124 ndev->stats.rx_errors++; ··· 219 144 } 220 145 221 146 static int __ntb_netdev_maybe_stop_tx(struct net_device *netdev, 222 - struct ntb_transport_qp *qp, int size) 147 + struct ntb_netdev_queue *q, int size) 223 148 { 224 - struct ntb_netdev *dev = netdev_priv(netdev); 149 + netif_stop_subqueue(netdev, q->qid); 225 150 226 - netif_stop_queue(netdev); 227 151 /* Make sure to see the latest value of ntb_transport_tx_free_entry() 228 152 * since the queue was last started. 229 153 */ 230 154 smp_mb(); 231 155 232 - if (likely(ntb_transport_tx_free_entry(qp) < size)) { 233 - mod_timer(&dev->tx_timer, jiffies + usecs_to_jiffies(tx_time)); 156 + if (likely(ntb_transport_tx_free_entry(q->qp) < size)) { 157 + mod_timer(&q->tx_timer, jiffies + usecs_to_jiffies(tx_time)); 234 158 return -EBUSY; 235 159 } 236 160 237 - netif_start_queue(netdev); 161 + /* The subqueue must be kept stopped if the link is down */ 162 + if (ntb_transport_link_query(q->qp)) 163 + netif_start_subqueue(netdev, q->qid); 164 + 238 165 return 0; 239 166 } 240 167 241 168 static int ntb_netdev_maybe_stop_tx(struct net_device *ndev, 242 - struct ntb_transport_qp *qp, int size) 169 + struct ntb_netdev_queue *q, int size) 243 170 { 244 - if (netif_queue_stopped(ndev) || 245 - (ntb_transport_tx_free_entry(qp) >= size)) 171 + if (__netif_subqueue_stopped(ndev, q->qid) || 172 + (ntb_transport_tx_free_entry(q->qp) >= size)) 246 173 return 0; 247 174 248 - return __ntb_netdev_maybe_stop_tx(ndev, qp, size); 175 + return __ntb_netdev_maybe_stop_tx(ndev, q, size); 249 176 } 250 177 251 178 static void ntb_netdev_tx_handler(struct ntb_transport_qp *qp, void *qp_data, 252 179 void *data, int len) 253 180 { 254 - struct net_device *ndev = qp_data; 181 + struct ntb_netdev_queue *q = qp_data; 182 + struct ntb_netdev *dev = q->ntdev; 183 + struct net_device *ndev; 255 184 struct sk_buff *skb; 256 - struct ntb_netdev *dev = netdev_priv(ndev); 257 185 186 + ndev = dev->ndev; 258 187 skb = data; 259 188 if (!skb || !ndev) 260 189 return; ··· 273 194 274 195 dev_kfree_skb_any(skb); 275 196 276 - if (ntb_transport_tx_free_entry(dev->qp) >= tx_start) { 197 + if (ntb_transport_tx_free_entry(qp) >= tx_start) { 277 198 /* Make sure anybody stopping the queue after this sees the new 278 199 * value of ntb_transport_tx_free_entry() 279 200 */ 280 201 smp_mb(); 281 - if (netif_queue_stopped(ndev)) 282 - netif_wake_queue(ndev); 202 + if (__netif_subqueue_stopped(ndev, q->qid) && 203 + ntb_transport_link_query(q->qp)) 204 + netif_wake_subqueue(ndev, q->qid); 283 205 } 284 206 } 207 + 208 + static const struct ntb_queue_handlers ntb_netdev_handlers = { 209 + .tx_handler = ntb_netdev_tx_handler, 210 + .rx_handler = ntb_netdev_rx_handler, 211 + .event_handler = ntb_netdev_event_handler, 212 + }; 285 213 286 214 static netdev_tx_t ntb_netdev_start_xmit(struct sk_buff *skb, 287 215 struct net_device *ndev) 288 216 { 289 217 struct ntb_netdev *dev = netdev_priv(ndev); 218 + u16 qid = skb_get_queue_mapping(skb); 219 + struct ntb_netdev_queue *q; 290 220 int rc; 291 221 292 - ntb_netdev_maybe_stop_tx(ndev, dev->qp, tx_stop); 222 + q = &dev->queues[qid]; 293 223 294 - rc = ntb_transport_tx_enqueue(dev->qp, skb, skb->data, skb->len); 224 + ntb_netdev_maybe_stop_tx(ndev, q, tx_stop); 225 + 226 + rc = ntb_transport_tx_enqueue(q->qp, skb, skb->data, skb->len); 295 227 if (rc) 296 228 goto err; 297 229 298 230 /* check for next submit */ 299 - ntb_netdev_maybe_stop_tx(ndev, dev->qp, tx_stop); 231 + ntb_netdev_maybe_stop_tx(ndev, q, tx_stop); 300 232 301 233 return NETDEV_TX_OK; 302 234 ··· 319 229 320 230 static void ntb_netdev_tx_timer(struct timer_list *t) 321 231 { 322 - struct ntb_netdev *dev = timer_container_of(dev, t, tx_timer); 323 - struct net_device *ndev = dev->ndev; 232 + struct ntb_netdev_queue *q = timer_container_of(q, t, tx_timer); 233 + struct ntb_netdev *dev = q->ntdev; 234 + struct net_device *ndev; 324 235 325 - if (ntb_transport_tx_free_entry(dev->qp) < tx_stop) { 326 - mod_timer(&dev->tx_timer, jiffies + usecs_to_jiffies(tx_time)); 236 + ndev = dev->ndev; 237 + 238 + if (ntb_transport_tx_free_entry(q->qp) < tx_stop) { 239 + mod_timer(&q->tx_timer, jiffies + usecs_to_jiffies(tx_time)); 327 240 } else { 328 241 /* Make sure anybody stopping the queue after this sees the new 329 242 * value of ntb_transport_tx_free_entry() 330 243 */ 331 244 smp_mb(); 332 - if (netif_queue_stopped(ndev)) 333 - netif_wake_queue(ndev); 245 + 246 + /* The subqueue must be kept stopped if the link is down */ 247 + if (__netif_subqueue_stopped(ndev, q->qid) && 248 + ntb_transport_link_query(q->qp)) 249 + netif_wake_subqueue(ndev, q->qid); 334 250 } 335 251 } 336 252 337 253 static int ntb_netdev_open(struct net_device *ndev) 338 254 { 339 255 struct ntb_netdev *dev = netdev_priv(ndev); 340 - struct sk_buff *skb; 341 - int rc, i, len; 256 + struct ntb_netdev_queue *queue; 257 + unsigned int q; 258 + int rc = 0; 342 259 343 - /* Add some empty rx bufs */ 344 - for (i = 0; i < NTB_RXQ_SIZE; i++) { 345 - skb = netdev_alloc_skb(ndev, ndev->mtu + ETH_HLEN); 346 - if (!skb) { 347 - rc = -ENOMEM; 348 - goto err; 349 - } 260 + /* Add some empty rx bufs for each queue */ 261 + for (q = 0; q < dev->num_queues; q++) { 262 + queue = &dev->queues[q]; 350 263 351 - rc = ntb_transport_rx_enqueue(dev->qp, skb, skb->data, 352 - ndev->mtu + ETH_HLEN); 353 - if (rc) { 354 - dev_kfree_skb(skb); 264 + rc = ntb_netdev_queue_rx_fill(ndev, queue); 265 + if (rc) 355 266 goto err; 356 - } 267 + 268 + timer_setup(&queue->tx_timer, ntb_netdev_tx_timer, 0); 357 269 } 358 270 359 - timer_setup(&dev->tx_timer, ntb_netdev_tx_timer, 0); 360 - 361 271 netif_carrier_off(ndev); 362 - ntb_transport_link_up(dev->qp); 363 - netif_start_queue(ndev); 272 + netif_tx_stop_all_queues(ndev); 273 + 274 + for (q = 0; q < dev->num_queues; q++) 275 + ntb_transport_link_up(dev->queues[q].qp); 364 276 365 277 return 0; 366 278 367 279 err: 368 - while ((skb = ntb_transport_rx_remove(dev->qp, &len))) 369 - dev_kfree_skb(skb); 280 + for (q = 0; q < dev->num_queues; q++) { 281 + queue = &dev->queues[q]; 282 + ntb_netdev_queue_rx_drain(queue); 283 + } 370 284 return rc; 371 285 } 372 286 373 287 static int ntb_netdev_close(struct net_device *ndev) 374 288 { 375 289 struct ntb_netdev *dev = netdev_priv(ndev); 376 - struct sk_buff *skb; 377 - int len; 290 + struct ntb_netdev_queue *queue; 291 + unsigned int q; 378 292 379 - ntb_transport_link_down(dev->qp); 293 + netif_tx_stop_all_queues(ndev); 294 + netif_carrier_off(ndev); 380 295 381 - while ((skb = ntb_transport_rx_remove(dev->qp, &len))) 382 - dev_kfree_skb(skb); 296 + for (q = 0; q < dev->num_queues; q++) { 297 + queue = &dev->queues[q]; 383 298 384 - timer_delete_sync(&dev->tx_timer); 299 + ntb_transport_link_down(queue->qp); 300 + ntb_netdev_queue_rx_drain(queue); 301 + timer_delete_sync(&queue->tx_timer); 302 + } 385 303 386 304 return 0; 387 305 } ··· 397 299 static int ntb_netdev_change_mtu(struct net_device *ndev, int new_mtu) 398 300 { 399 301 struct ntb_netdev *dev = netdev_priv(ndev); 302 + struct ntb_netdev_queue *queue; 400 303 struct sk_buff *skb; 401 - int len, rc; 304 + unsigned int q, i; 305 + int len, rc = 0; 402 306 403 - if (new_mtu > ntb_transport_max_size(dev->qp) - ETH_HLEN) 307 + if (new_mtu > ntb_transport_max_size(dev->queues[0].qp) - ETH_HLEN) 404 308 return -EINVAL; 405 309 406 310 if (!netif_running(ndev)) { ··· 411 311 } 412 312 413 313 /* Bring down the link and dispose of posted rx entries */ 414 - ntb_transport_link_down(dev->qp); 314 + for (q = 0; q < dev->num_queues; q++) 315 + ntb_transport_link_down(dev->queues[q].qp); 415 316 416 317 if (ndev->mtu < new_mtu) { 417 - int i; 318 + for (q = 0; q < dev->num_queues; q++) { 319 + queue = &dev->queues[q]; 418 320 419 - for (i = 0; (skb = ntb_transport_rx_remove(dev->qp, &len)); i++) 420 - dev_kfree_skb(skb); 421 - 422 - for (; i; i--) { 423 - skb = netdev_alloc_skb(ndev, new_mtu + ETH_HLEN); 424 - if (!skb) { 425 - rc = -ENOMEM; 426 - goto err; 427 - } 428 - 429 - rc = ntb_transport_rx_enqueue(dev->qp, skb, skb->data, 430 - new_mtu + ETH_HLEN); 431 - if (rc) { 321 + for (i = 0; 322 + (skb = ntb_transport_rx_remove(queue->qp, &len)); 323 + i++) 432 324 dev_kfree_skb(skb); 433 - goto err; 325 + 326 + for (; i; i--) { 327 + skb = netdev_alloc_skb(ndev, 328 + new_mtu + ETH_HLEN); 329 + if (!skb) { 330 + rc = -ENOMEM; 331 + goto err; 332 + } 333 + 334 + rc = ntb_transport_rx_enqueue(queue->qp, skb, 335 + skb->data, 336 + new_mtu + 337 + ETH_HLEN); 338 + if (rc) { 339 + dev_kfree_skb(skb); 340 + goto err; 341 + } 434 342 } 435 343 } 436 344 } 437 345 438 346 WRITE_ONCE(ndev->mtu, new_mtu); 439 347 440 - ntb_transport_link_up(dev->qp); 348 + for (q = 0; q < dev->num_queues; q++) 349 + ntb_transport_link_up(dev->queues[q].qp); 441 350 442 351 return 0; 443 352 444 353 err: 445 - ntb_transport_link_down(dev->qp); 354 + for (q = 0; q < dev->num_queues; q++) { 355 + struct ntb_netdev_queue *queue = &dev->queues[q]; 446 356 447 - while ((skb = ntb_transport_rx_remove(dev->qp, &len))) 448 - dev_kfree_skb(skb); 357 + ntb_transport_link_down(queue->qp); 358 + 359 + ntb_netdev_queue_rx_drain(queue); 360 + } 449 361 450 362 netdev_err(ndev, "Error changing MTU, device inoperable\n"); 451 363 return rc; ··· 498 386 return 0; 499 387 } 500 388 389 + static void ntb_get_channels(struct net_device *ndev, 390 + struct ethtool_channels *channels) 391 + { 392 + struct ntb_netdev *dev = netdev_priv(ndev); 393 + 394 + channels->combined_count = dev->num_queues; 395 + channels->max_combined = ndev->num_tx_queues; 396 + } 397 + 398 + static int ntb_inc_channels(struct net_device *ndev, 399 + unsigned int old, unsigned int new) 400 + { 401 + struct ntb_netdev *dev = netdev_priv(ndev); 402 + bool running = netif_running(ndev); 403 + struct ntb_netdev_queue *queue; 404 + unsigned int q, created; 405 + int rc; 406 + 407 + created = old; 408 + for (q = old; q < new; q++) { 409 + queue = &dev->queues[q]; 410 + 411 + queue->ntdev = dev; 412 + queue->qid = q; 413 + queue->qp = ntb_transport_create_queue(queue, dev->client_dev, 414 + &ntb_netdev_handlers); 415 + if (!queue->qp) { 416 + rc = -ENOSPC; 417 + goto err_new; 418 + } 419 + created++; 420 + 421 + if (!running) 422 + continue; 423 + 424 + timer_setup(&queue->tx_timer, ntb_netdev_tx_timer, 0); 425 + 426 + rc = ntb_netdev_queue_rx_fill(ndev, queue); 427 + if (rc) 428 + goto err_new; 429 + 430 + /* 431 + * Carrier may already be on due to other QPs. Keep the new 432 + * subqueue stopped until we get a Link Up event for this QP. 433 + */ 434 + netif_stop_subqueue(ndev, q); 435 + } 436 + 437 + rc = netif_set_real_num_queues(ndev, new, new); 438 + if (rc) 439 + goto err_new; 440 + 441 + dev->num_queues = new; 442 + 443 + if (running) 444 + for (q = old; q < new; q++) 445 + ntb_transport_link_up(dev->queues[q].qp); 446 + 447 + return 0; 448 + 449 + err_new: 450 + if (running) { 451 + unsigned int rollback = created; 452 + 453 + while (rollback-- > old) { 454 + queue = &dev->queues[rollback]; 455 + ntb_transport_link_down(queue->qp); 456 + ntb_netdev_queue_rx_drain(queue); 457 + timer_delete_sync(&queue->tx_timer); 458 + } 459 + } 460 + while (created-- > old) { 461 + queue = &dev->queues[created]; 462 + ntb_transport_free_queue(queue->qp); 463 + queue->qp = NULL; 464 + } 465 + return rc; 466 + } 467 + 468 + static int ntb_dec_channels(struct net_device *ndev, 469 + unsigned int old, unsigned int new) 470 + { 471 + struct ntb_netdev *dev = netdev_priv(ndev); 472 + bool running = netif_running(ndev); 473 + struct ntb_netdev_queue *queue; 474 + unsigned int q; 475 + int rc; 476 + 477 + if (running) 478 + for (q = new; q < old; q++) 479 + netif_stop_subqueue(ndev, q); 480 + 481 + rc = netif_set_real_num_queues(ndev, new, new); 482 + if (rc) 483 + goto err; 484 + 485 + /* Publish new queue count before invalidating QP pointers */ 486 + dev->num_queues = new; 487 + 488 + for (q = new; q < old; q++) { 489 + queue = &dev->queues[q]; 490 + 491 + if (running) { 492 + ntb_transport_link_down(queue->qp); 493 + ntb_netdev_queue_rx_drain(queue); 494 + timer_delete_sync(&queue->tx_timer); 495 + } 496 + 497 + ntb_transport_free_queue(queue->qp); 498 + queue->qp = NULL; 499 + } 500 + 501 + /* 502 + * It might be the case that the removed queues are the only queues that 503 + * were up, so see if the global carrier needs to change. 504 + */ 505 + ntb_netdev_update_carrier(dev); 506 + return 0; 507 + 508 + err: 509 + if (running) { 510 + for (q = new; q < old; q++) 511 + netif_wake_subqueue(ndev, q); 512 + } 513 + return rc; 514 + } 515 + 516 + static int ntb_set_channels(struct net_device *ndev, 517 + struct ethtool_channels *channels) 518 + { 519 + struct ntb_netdev *dev = netdev_priv(ndev); 520 + unsigned int new = channels->combined_count; 521 + unsigned int old = dev->num_queues; 522 + 523 + if (new == old) 524 + return 0; 525 + 526 + if (new < old) 527 + return ntb_dec_channels(ndev, old, new); 528 + else 529 + return ntb_inc_channels(ndev, old, new); 530 + } 531 + 501 532 static const struct ethtool_ops ntb_ethtool_ops = { 502 533 .get_drvinfo = ntb_get_drvinfo, 503 534 .get_link = ethtool_op_get_link, 504 535 .get_link_ksettings = ntb_get_link_ksettings, 505 - }; 506 - 507 - static const struct ntb_queue_handlers ntb_netdev_handlers = { 508 - .tx_handler = ntb_netdev_tx_handler, 509 - .rx_handler = ntb_netdev_rx_handler, 510 - .event_handler = ntb_netdev_event_handler, 536 + .get_channels = ntb_get_channels, 537 + .set_channels = ntb_set_channels, 511 538 }; 512 539 513 540 static int ntb_netdev_probe(struct device *client_dev) ··· 655 404 struct net_device *ndev; 656 405 struct pci_dev *pdev; 657 406 struct ntb_netdev *dev; 407 + unsigned int q; 658 408 int rc; 659 409 660 410 ntb = dev_ntb(client_dev->parent); ··· 663 411 if (!pdev) 664 412 return -ENODEV; 665 413 666 - ndev = alloc_etherdev(sizeof(*dev)); 414 + ndev = alloc_etherdev_mq(sizeof(*dev), NTB_NETDEV_MAX_QUEUES); 667 415 if (!ndev) 668 416 return -ENOMEM; 669 417 ··· 672 420 dev = netdev_priv(ndev); 673 421 dev->ndev = ndev; 674 422 dev->pdev = pdev; 423 + dev->client_dev = client_dev; 424 + dev->num_queues = 0; 425 + 426 + dev->queues = kzalloc_objs(*dev->queues, NTB_NETDEV_MAX_QUEUES, 427 + GFP_KERNEL); 428 + if (!dev->queues) { 429 + rc = -ENOMEM; 430 + goto err_free_netdev; 431 + } 432 + 675 433 ndev->features = NETIF_F_HIGHDMA; 676 434 677 435 ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE; ··· 698 436 ndev->min_mtu = 0; 699 437 ndev->max_mtu = ETH_MAX_MTU; 700 438 701 - dev->qp = ntb_transport_create_queue(ndev, client_dev, 702 - &ntb_netdev_handlers); 703 - if (!dev->qp) { 704 - rc = -EIO; 705 - goto err; 439 + for (q = 0; q < NTB_NETDEV_DEFAULT_QUEUES; q++) { 440 + struct ntb_netdev_queue *queue = &dev->queues[q]; 441 + 442 + queue->ntdev = dev; 443 + queue->qid = q; 444 + queue->qp = ntb_transport_create_queue(queue, client_dev, 445 + &ntb_netdev_handlers); 446 + if (!queue->qp) 447 + break; 448 + 449 + dev->num_queues++; 706 450 } 707 451 708 - ndev->mtu = ntb_transport_max_size(dev->qp) - ETH_HLEN; 452 + if (!dev->num_queues) { 453 + rc = -EIO; 454 + goto err_free_queues; 455 + } 456 + 457 + rc = netif_set_real_num_queues(ndev, dev->num_queues, dev->num_queues); 458 + if (rc) 459 + goto err_free_qps; 460 + 461 + ndev->mtu = ntb_transport_max_size(dev->queues[0].qp) - ETH_HLEN; 709 462 710 463 rc = register_netdev(ndev); 711 464 if (rc) 712 - goto err1; 465 + goto err_free_qps; 713 466 714 467 dev_set_drvdata(client_dev, ndev); 715 - dev_info(&pdev->dev, "%s created\n", ndev->name); 468 + dev_info(&pdev->dev, "%s created with %u queue pairs\n", 469 + ndev->name, dev->num_queues); 716 470 return 0; 717 471 718 - err1: 719 - ntb_transport_free_queue(dev->qp); 720 - err: 472 + err_free_qps: 473 + for (q = 0; q < dev->num_queues; q++) 474 + ntb_transport_free_queue(dev->queues[q].qp); 475 + 476 + err_free_queues: 477 + kfree(dev->queues); 478 + 479 + err_free_netdev: 721 480 free_netdev(ndev); 722 481 return rc; 723 482 } ··· 747 464 { 748 465 struct net_device *ndev = dev_get_drvdata(client_dev); 749 466 struct ntb_netdev *dev = netdev_priv(ndev); 467 + unsigned int q; 750 468 751 469 unregister_netdev(ndev); 752 - ntb_transport_free_queue(dev->qp); 470 + for (q = 0; q < dev->num_queues; q++) 471 + ntb_transport_free_queue(dev->queues[q].qp); 472 + 473 + kfree(dev->queues); 753 474 free_netdev(ndev); 754 475 } 755 476