diff options
Diffstat (limited to 'drivers/net/xen-netback/xenbus.c')
-rw-r--r-- | drivers/net/xen-netback/xenbus.c | 95 |
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 | ||
23 | struct backend_info { | 25 | struct 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 | ||
37 | static int connect_rings(struct backend_info *); | 39 | static int connect_rings(struct backend_info *be, struct xenvif_queue *queue); |
38 | static void connect(struct backend_info *); | 40 | static void connect(struct backend_info *be); |
41 | static int read_xenbus_vif_flags(struct backend_info *be); | ||
39 | static void backend_create_xenvif(struct backend_info *be); | 42 | static void backend_create_xenvif(struct backend_info *be); |
40 | static void unregister_hotplug_status_watch(struct backend_info *be); | 43 | static void unregister_hotplug_status_watch(struct backend_info *be); |
41 | static void set_backend_state(struct backend_info *be, | 44 | static 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 | |||
542 | err: | ||
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 | ||
514 | static int connect_rings(struct backend_info *be) | 552 | static 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 | |||
599 | static 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 | ||