aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/xen-netback/common.h4
-rw-r--r--drivers/net/xen-netback/interface.c1
-rw-r--r--drivers/net/xen-netback/netback.c4
-rw-r--r--drivers/net/xen-netback/xenbus.c57
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
265void xenvif_tx_credit_callback(unsigned long data);
266
263struct xenvif *xenvif_alloc(struct device *parent, 267struct 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
644static void tx_credit_callback(unsigned long data) 644void 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);
41static int read_xenbus_vif_flags(struct backend_info *be); 41static int read_xenbus_vif_flags(struct backend_info *be);
42static int backend_create_xenvif(struct backend_info *be); 42static int backend_create_xenvif(struct backend_info *be);
43static void unregister_hotplug_status_watch(struct backend_info *be); 43static void unregister_hotplug_status_watch(struct backend_info *be);
44static void xen_unregister_watchers(struct xenvif *vif);
44static void set_backend_state(struct backend_info *be, 45static 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)
430static void backend_disconnect(struct backend_info *be) 432static 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
651static 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
673static 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
695static 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
648static void unregister_hotplug_status_watch(struct backend_info *be) 704static 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 */