diff options
-rw-r--r-- | drivers/net/xen-netback/common.h | 4 | ||||
-rw-r--r-- | drivers/net/xen-netback/interface.c | 1 | ||||
-rw-r--r-- | drivers/net/xen-netback/netback.c | 4 | ||||
-rw-r--r-- | drivers/net/xen-netback/xenbus.c | 57 |
4 files changed, 63 insertions, 3 deletions
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 589fa256256b..8a495b318b6f 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h | |||
@@ -238,6 +238,8 @@ struct xenvif { | |||
238 | unsigned int num_queues; /* active queues, resource allocated */ | 238 | unsigned int num_queues; /* active queues, resource allocated */ |
239 | unsigned int stalled_queues; | 239 | unsigned int stalled_queues; |
240 | 240 | ||
241 | struct xenbus_watch credit_watch; | ||
242 | |||
241 | spinlock_t lock; | 243 | spinlock_t lock; |
242 | 244 | ||
243 | #ifdef CONFIG_DEBUG_FS | 245 | #ifdef CONFIG_DEBUG_FS |
@@ -260,6 +262,8 @@ static inline struct xenbus_device *xenvif_to_xenbus_device(struct xenvif *vif) | |||
260 | return to_xenbus_device(vif->dev->dev.parent); | 262 | return to_xenbus_device(vif->dev->dev.parent); |
261 | } | 263 | } |
262 | 264 | ||
265 | void xenvif_tx_credit_callback(unsigned long data); | ||
266 | |||
263 | struct xenvif *xenvif_alloc(struct device *parent, | 267 | struct xenvif *xenvif_alloc(struct device *parent, |
264 | domid_t domid, | 268 | domid_t domid, |
265 | unsigned int handle); | 269 | unsigned int handle); |
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index d2ada7cda97a..1a83e190fc15 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c | |||
@@ -463,6 +463,7 @@ int xenvif_init_queue(struct xenvif_queue *queue) | |||
463 | queue->credit_bytes = queue->remaining_credit = ~0UL; | 463 | queue->credit_bytes = queue->remaining_credit = ~0UL; |
464 | queue->credit_usec = 0UL; | 464 | queue->credit_usec = 0UL; |
465 | init_timer(&queue->credit_timeout); | 465 | init_timer(&queue->credit_timeout); |
466 | queue->credit_timeout.function = xenvif_tx_credit_callback; | ||
466 | queue->credit_window_start = get_jiffies_64(); | 467 | queue->credit_window_start = get_jiffies_64(); |
467 | 468 | ||
468 | queue->rx_queue_max = XENVIF_RX_QUEUE_BYTES; | 469 | queue->rx_queue_max = XENVIF_RX_QUEUE_BYTES; |
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index cab9f5257f57..2c25e8e1a91e 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
@@ -641,7 +641,7 @@ static void tx_add_credit(struct xenvif_queue *queue) | |||
641 | queue->remaining_credit = min(max_credit, max_burst); | 641 | queue->remaining_credit = min(max_credit, max_burst); |
642 | } | 642 | } |
643 | 643 | ||
644 | static void tx_credit_callback(unsigned long data) | 644 | void xenvif_tx_credit_callback(unsigned long data) |
645 | { | 645 | { |
646 | struct xenvif_queue *queue = (struct xenvif_queue *)data; | 646 | struct xenvif_queue *queue = (struct xenvif_queue *)data; |
647 | tx_add_credit(queue); | 647 | tx_add_credit(queue); |
@@ -1169,8 +1169,6 @@ static bool tx_credit_exceeded(struct xenvif_queue *queue, unsigned size) | |||
1169 | if (size > queue->remaining_credit) { | 1169 | if (size > queue->remaining_credit) { |
1170 | queue->credit_timeout.data = | 1170 | queue->credit_timeout.data = |
1171 | (unsigned long)queue; | 1171 | (unsigned long)queue; |
1172 | queue->credit_timeout.function = | ||
1173 | tx_credit_callback; | ||
1174 | mod_timer(&queue->credit_timeout, | 1172 | mod_timer(&queue->credit_timeout, |
1175 | next_credit); | 1173 | next_credit); |
1176 | queue->credit_window_start = next_credit; | 1174 | queue->credit_window_start = next_credit; |
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index 794204e34fba..3d8dbf5f2d39 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c | |||
@@ -41,6 +41,7 @@ static void connect(struct backend_info *be); | |||
41 | static int read_xenbus_vif_flags(struct backend_info *be); | 41 | static int read_xenbus_vif_flags(struct backend_info *be); |
42 | static int backend_create_xenvif(struct backend_info *be); | 42 | static int backend_create_xenvif(struct backend_info *be); |
43 | static void unregister_hotplug_status_watch(struct backend_info *be); | 43 | static void unregister_hotplug_status_watch(struct backend_info *be); |
44 | static void xen_unregister_watchers(struct xenvif *vif); | ||
44 | static void set_backend_state(struct backend_info *be, | 45 | static void set_backend_state(struct backend_info *be, |
45 | enum xenbus_state state); | 46 | enum xenbus_state state); |
46 | 47 | ||
@@ -232,6 +233,7 @@ static int netback_remove(struct xenbus_device *dev) | |||
232 | unregister_hotplug_status_watch(be); | 233 | unregister_hotplug_status_watch(be); |
233 | if (be->vif) { | 234 | if (be->vif) { |
234 | kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); | 235 | kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); |
236 | xen_unregister_watchers(be->vif); | ||
235 | xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); | 237 | xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); |
236 | xenvif_free(be->vif); | 238 | xenvif_free(be->vif); |
237 | be->vif = NULL; | 239 | be->vif = NULL; |
@@ -430,6 +432,7 @@ static int backend_create_xenvif(struct backend_info *be) | |||
430 | static void backend_disconnect(struct backend_info *be) | 432 | static void backend_disconnect(struct backend_info *be) |
431 | { | 433 | { |
432 | if (be->vif) { | 434 | if (be->vif) { |
435 | xen_unregister_watchers(be->vif); | ||
433 | #ifdef CONFIG_DEBUG_FS | 436 | #ifdef CONFIG_DEBUG_FS |
434 | xenvif_debugfs_delif(be->vif); | 437 | xenvif_debugfs_delif(be->vif); |
435 | #endif /* CONFIG_DEBUG_FS */ | 438 | #endif /* CONFIG_DEBUG_FS */ |
@@ -645,6 +648,59 @@ static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[]) | |||
645 | return 0; | 648 | return 0; |
646 | } | 649 | } |
647 | 650 | ||
651 | static void xen_net_rate_changed(struct xenbus_watch *watch, | ||
652 | const char **vec, unsigned int len) | ||
653 | { | ||
654 | struct xenvif *vif = container_of(watch, struct xenvif, credit_watch); | ||
655 | struct xenbus_device *dev = xenvif_to_xenbus_device(vif); | ||
656 | unsigned long credit_bytes; | ||
657 | unsigned long credit_usec; | ||
658 | unsigned int queue_index; | ||
659 | |||
660 | xen_net_read_rate(dev, &credit_bytes, &credit_usec); | ||
661 | for (queue_index = 0; queue_index < vif->num_queues; queue_index++) { | ||
662 | struct xenvif_queue *queue = &vif->queues[queue_index]; | ||
663 | |||
664 | queue->credit_bytes = credit_bytes; | ||
665 | queue->credit_usec = credit_usec; | ||
666 | if (!mod_timer_pending(&queue->credit_timeout, jiffies) && | ||
667 | queue->remaining_credit > queue->credit_bytes) { | ||
668 | queue->remaining_credit = queue->credit_bytes; | ||
669 | } | ||
670 | } | ||
671 | } | ||
672 | |||
673 | static int xen_register_watchers(struct xenbus_device *dev, struct xenvif *vif) | ||
674 | { | ||
675 | int err = 0; | ||
676 | char *node; | ||
677 | unsigned maxlen = strlen(dev->nodename) + sizeof("/rate"); | ||
678 | |||
679 | node = kmalloc(maxlen, GFP_KERNEL); | ||
680 | if (!node) | ||
681 | return -ENOMEM; | ||
682 | snprintf(node, maxlen, "%s/rate", dev->nodename); | ||
683 | vif->credit_watch.node = node; | ||
684 | vif->credit_watch.callback = xen_net_rate_changed; | ||
685 | err = register_xenbus_watch(&vif->credit_watch); | ||
686 | if (err) { | ||
687 | pr_err("Failed to set watcher %s\n", vif->credit_watch.node); | ||
688 | kfree(node); | ||
689 | vif->credit_watch.node = NULL; | ||
690 | vif->credit_watch.callback = NULL; | ||
691 | } | ||
692 | return err; | ||
693 | } | ||
694 | |||
695 | static void xen_unregister_watchers(struct xenvif *vif) | ||
696 | { | ||
697 | if (vif->credit_watch.node) { | ||
698 | unregister_xenbus_watch(&vif->credit_watch); | ||
699 | kfree(vif->credit_watch.node); | ||
700 | vif->credit_watch.node = NULL; | ||
701 | } | ||
702 | } | ||
703 | |||
648 | static void unregister_hotplug_status_watch(struct backend_info *be) | 704 | static void unregister_hotplug_status_watch(struct backend_info *be) |
649 | { | 705 | { |
650 | if (be->have_hotplug_status_watch) { | 706 | if (be->have_hotplug_status_watch) { |
@@ -709,6 +765,7 @@ static void connect(struct backend_info *be) | |||
709 | } | 765 | } |
710 | 766 | ||
711 | xen_net_read_rate(dev, &credit_bytes, &credit_usec); | 767 | xen_net_read_rate(dev, &credit_bytes, &credit_usec); |
768 | xen_register_watchers(dev, be->vif); | ||
712 | read_xenbus_vif_flags(be); | 769 | read_xenbus_vif_flags(be); |
713 | 770 | ||
714 | /* Use the number of queues requested by the frontend */ | 771 | /* Use the number of queues requested by the frontend */ |