diff options
author | Wei Liu <wei.liu2@citrix.com> | 2013-05-22 02:34:45 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-05-23 21:40:37 -0400 |
commit | e1f00a69ec26e3eb9847c61c665b8fb3f0c6b477 (patch) | |
tree | 5958617283d231a3a58229e0e78a4d4623a569a5 /drivers/net/xen-netback/xenbus.c | |
parent | 8892475386e819aa50856947948c546ccc964d96 (diff) |
xen-netback: split event channels support for Xen backend driver
Netback and netfront only use one event channel to do TX / RX notification,
which may cause unnecessary wake-up of processing routines. This patch adds a
new feature called feature-split-event-channels to netback, enabling it to
handle TX and RX events separately.
Netback will use tx_irq to notify guest for TX completion, rx_irq for RX
notification.
If frontend doesn't support this feature, tx_irq equals to rx_irq.
Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/xen-netback/xenbus.c')
-rw-r--r-- | drivers/net/xen-netback/xenbus.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index d230c145660c..04bd860d16a9 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c | |||
@@ -122,6 +122,16 @@ static int netback_probe(struct xenbus_device *dev, | |||
122 | goto fail; | 122 | goto fail; |
123 | } | 123 | } |
124 | 124 | ||
125 | /* | ||
126 | * Split event channels support, this is optional so it is not | ||
127 | * put inside the above loop. | ||
128 | */ | ||
129 | err = xenbus_printf(XBT_NIL, dev->nodename, | ||
130 | "feature-split-event-channels", | ||
131 | "%u", separate_tx_rx_irq); | ||
132 | if (err) | ||
133 | pr_debug("Error writing feature-split-event-channels"); | ||
134 | |||
125 | err = xenbus_switch_state(dev, XenbusStateInitWait); | 135 | err = xenbus_switch_state(dev, XenbusStateInitWait); |
126 | if (err) | 136 | if (err) |
127 | goto fail; | 137 | goto fail; |
@@ -393,21 +403,36 @@ static int connect_rings(struct backend_info *be) | |||
393 | struct xenvif *vif = be->vif; | 403 | struct xenvif *vif = be->vif; |
394 | struct xenbus_device *dev = be->dev; | 404 | struct xenbus_device *dev = be->dev; |
395 | unsigned long tx_ring_ref, rx_ring_ref; | 405 | unsigned long tx_ring_ref, rx_ring_ref; |
396 | unsigned int evtchn, rx_copy; | 406 | unsigned int tx_evtchn, rx_evtchn, rx_copy; |
397 | int err; | 407 | int err; |
398 | int val; | 408 | int val; |
399 | 409 | ||
400 | err = xenbus_gather(XBT_NIL, dev->otherend, | 410 | err = xenbus_gather(XBT_NIL, dev->otherend, |
401 | "tx-ring-ref", "%lu", &tx_ring_ref, | 411 | "tx-ring-ref", "%lu", &tx_ring_ref, |
402 | "rx-ring-ref", "%lu", &rx_ring_ref, | 412 | "rx-ring-ref", "%lu", &rx_ring_ref, NULL); |
403 | "event-channel", "%u", &evtchn, NULL); | ||
404 | if (err) { | 413 | if (err) { |
405 | xenbus_dev_fatal(dev, err, | 414 | xenbus_dev_fatal(dev, err, |
406 | "reading %s/ring-ref and event-channel", | 415 | "reading %s/ring-ref", |
407 | dev->otherend); | 416 | dev->otherend); |
408 | return err; | 417 | return err; |
409 | } | 418 | } |
410 | 419 | ||
420 | /* Try split event channels first, then single event channel. */ | ||
421 | err = xenbus_gather(XBT_NIL, dev->otherend, | ||
422 | "event-channel-tx", "%u", &tx_evtchn, | ||
423 | "event-channel-rx", "%u", &rx_evtchn, NULL); | ||
424 | if (err < 0) { | ||
425 | err = xenbus_scanf(XBT_NIL, dev->otherend, | ||
426 | "event-channel", "%u", &tx_evtchn); | ||
427 | if (err < 0) { | ||
428 | xenbus_dev_fatal(dev, err, | ||
429 | "reading %s/event-channel(-tx/rx)", | ||
430 | dev->otherend); | ||
431 | return err; | ||
432 | } | ||
433 | rx_evtchn = tx_evtchn; | ||
434 | } | ||
435 | |||
411 | err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u", | 436 | err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u", |
412 | &rx_copy); | 437 | &rx_copy); |
413 | if (err == -ENOENT) { | 438 | if (err == -ENOENT) { |
@@ -454,11 +479,13 @@ static int connect_rings(struct backend_info *be) | |||
454 | vif->csum = !val; | 479 | vif->csum = !val; |
455 | 480 | ||
456 | /* Map the shared frame, irq etc. */ | 481 | /* Map the shared frame, irq etc. */ |
457 | err = xenvif_connect(vif, tx_ring_ref, rx_ring_ref, evtchn); | 482 | err = xenvif_connect(vif, tx_ring_ref, rx_ring_ref, |
483 | tx_evtchn, rx_evtchn); | ||
458 | if (err) { | 484 | if (err) { |
459 | xenbus_dev_fatal(dev, err, | 485 | xenbus_dev_fatal(dev, err, |
460 | "mapping shared-frames %lu/%lu port %u", | 486 | "mapping shared-frames %lu/%lu port tx %u rx %u", |
461 | tx_ring_ref, rx_ring_ref, evtchn); | 487 | tx_ring_ref, rx_ring_ref, |
488 | tx_evtchn, rx_evtchn); | ||
462 | return err; | 489 | return err; |
463 | } | 490 | } |
464 | return 0; | 491 | return 0; |