aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/xen-netback/xenbus.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/xen-netback/xenbus.c')
-rw-r--r--drivers/net/xen-netback/xenbus.c95
1 files changed, 71 insertions, 24 deletions
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 7a206cffb062..358602f55afa 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -19,6 +19,8 @@
19*/ 19*/
20 20
21#include "common.h" 21#include "common.h"
22#include <linux/vmalloc.h>
23#include <linux/rtnetlink.h>
22 24
23struct backend_info { 25struct backend_info {
24 struct xenbus_device *dev; 26 struct xenbus_device *dev;
@@ -34,8 +36,9 @@ struct backend_info {
34 u8 have_hotplug_status_watch:1; 36 u8 have_hotplug_status_watch:1;
35}; 37};
36 38
37static int connect_rings(struct backend_info *); 39static int connect_rings(struct backend_info *be, struct xenvif_queue *queue);
38static void connect(struct backend_info *); 40static void connect(struct backend_info *be);
41static int read_xenbus_vif_flags(struct backend_info *be);
39static void backend_create_xenvif(struct backend_info *be); 42static void backend_create_xenvif(struct backend_info *be);
40static void unregister_hotplug_status_watch(struct backend_info *be); 43static void unregister_hotplug_status_watch(struct backend_info *be);
41static void set_backend_state(struct backend_info *be, 44static void set_backend_state(struct backend_info *be,
@@ -485,10 +488,10 @@ static void connect(struct backend_info *be)
485{ 488{
486 int err; 489 int err;
487 struct xenbus_device *dev = be->dev; 490 struct xenbus_device *dev = be->dev;
488 491 unsigned long credit_bytes, credit_usec;
489 err = connect_rings(be); 492 unsigned int queue_index;
490 if (err) 493 unsigned int requested_num_queues = 1;
491 return; 494 struct xenvif_queue *queue;
492 495
493 err = xen_net_read_mac(dev, be->vif->fe_dev_addr); 496 err = xen_net_read_mac(dev, be->vif->fe_dev_addr);
494 if (err) { 497 if (err) {
@@ -496,9 +499,34 @@ static void connect(struct backend_info *be)
496 return; 499 return;
497 } 500 }
498 501
499 xen_net_read_rate(dev, &be->vif->credit_bytes, 502 xen_net_read_rate(dev, &credit_bytes, &credit_usec);
500 &be->vif->credit_usec); 503 read_xenbus_vif_flags(be);
501 be->vif->remaining_credit = be->vif->credit_bytes; 504
505 be->vif->queues = vzalloc(requested_num_queues *
506 sizeof(struct xenvif_queue));
507 rtnl_lock();
508 netif_set_real_num_tx_queues(be->vif->dev, requested_num_queues);
509 rtnl_unlock();
510
511 for (queue_index = 0; queue_index < requested_num_queues; ++queue_index) {
512 queue = &be->vif->queues[queue_index];
513 queue->vif = be->vif;
514 queue->id = queue_index;
515 snprintf(queue->name, sizeof(queue->name), "%s-q%u",
516 be->vif->dev->name, queue->id);
517
518 err = xenvif_init_queue(queue);
519 if (err)
520 goto err;
521
522 queue->remaining_credit = credit_bytes;
523
524 err = connect_rings(be, queue);
525 if (err)
526 goto err;
527 }
528
529 xenvif_carrier_on(be->vif);
502 530
503 unregister_hotplug_status_watch(be); 531 unregister_hotplug_status_watch(be);
504 err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, 532 err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
@@ -507,18 +535,26 @@ static void connect(struct backend_info *be)
507 if (!err) 535 if (!err)
508 be->have_hotplug_status_watch = 1; 536 be->have_hotplug_status_watch = 1;
509 537
510 netif_wake_queue(be->vif->dev); 538 netif_tx_wake_all_queues(be->vif->dev);
539
540 return;
541
542err:
543 vfree(be->vif->queues);
544 be->vif->queues = NULL;
545 rtnl_lock();
546 netif_set_real_num_tx_queues(be->vif->dev, 0);
547 rtnl_unlock();
548 return;
511} 549}
512 550
513 551
514static int connect_rings(struct backend_info *be) 552static int connect_rings(struct backend_info *be, struct xenvif_queue *queue)
515{ 553{
516 struct xenvif *vif = be->vif;
517 struct xenbus_device *dev = be->dev; 554 struct xenbus_device *dev = be->dev;
518 unsigned long tx_ring_ref, rx_ring_ref; 555 unsigned long tx_ring_ref, rx_ring_ref;
519 unsigned int tx_evtchn, rx_evtchn, rx_copy; 556 unsigned int tx_evtchn, rx_evtchn;
520 int err; 557 int err;
521 int val;
522 558
523 err = xenbus_gather(XBT_NIL, dev->otherend, 559 err = xenbus_gather(XBT_NIL, dev->otherend,
524 "tx-ring-ref", "%lu", &tx_ring_ref, 560 "tx-ring-ref", "%lu", &tx_ring_ref,
@@ -546,6 +582,27 @@ static int connect_rings(struct backend_info *be)
546 rx_evtchn = tx_evtchn; 582 rx_evtchn = tx_evtchn;
547 } 583 }
548 584
585 /* Map the shared frame, irq etc. */
586 err = xenvif_connect(queue, tx_ring_ref, rx_ring_ref,
587 tx_evtchn, rx_evtchn);
588 if (err) {
589 xenbus_dev_fatal(dev, err,
590 "mapping shared-frames %lu/%lu port tx %u rx %u",
591 tx_ring_ref, rx_ring_ref,
592 tx_evtchn, rx_evtchn);
593 return err;
594 }
595
596 return 0;
597}
598
599static int read_xenbus_vif_flags(struct backend_info *be)
600{
601 struct xenvif *vif = be->vif;
602 struct xenbus_device *dev = be->dev;
603 unsigned int rx_copy;
604 int err, val;
605
549 err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u", 606 err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u",
550 &rx_copy); 607 &rx_copy);
551 if (err == -ENOENT) { 608 if (err == -ENOENT) {
@@ -621,16 +678,6 @@ static int connect_rings(struct backend_info *be)
621 val = 0; 678 val = 0;
622 vif->ipv6_csum = !!val; 679 vif->ipv6_csum = !!val;
623 680
624 /* Map the shared frame, irq etc. */
625 err = xenvif_connect(vif, tx_ring_ref, rx_ring_ref,
626 tx_evtchn, rx_evtchn);
627 if (err) {
628 xenbus_dev_fatal(dev, err,
629 "mapping shared-frames %lu/%lu port tx %u rx %u",
630 tx_ring_ref, rx_ring_ref,
631 tx_evtchn, rx_evtchn);
632 return err;
633 }
634 return 0; 681 return 0;
635} 682}
636 683