diff --git a/drivers/xen/netback/common.h b/drivers/xen/netback/common.h index 51f97c0..87696ec 100644 --- a/drivers/xen/netback/common.h +++ b/drivers/xen/netback/common.h @@ -89,9 +89,9 @@ struct xen_netif { /* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */ unsigned long credit_bytes; unsigned long credit_usec; - unsigned long remaining_credit; + atomic64_t remaining_credit; struct timer_list credit_timeout; - + /* Enforce draining of the transmit queue. */ struct timer_list tx_queue_timeout; @@ -149,11 +149,13 @@ struct backend_info { enum xenbus_state frontend_state; struct xenbus_watch hotplug_status_watch; int have_hotplug_status_watch:1; - + int have_rate_watch:1; /* State relating to the netback accelerator */ void *netback_accel_priv; /* The accelerator that this backend is currently using */ struct netback_accelerator *accelerator; + /**/ + struct xenbus_watch rate_watch; }; #define NETBACK_ACCEL_VERSION 0x00010001 diff --git a/drivers/xen/netback/interface.c b/drivers/xen/netback/interface.c index b23b14d..139360b 100644 --- a/drivers/xen/netback/interface.c +++ b/drivers/xen/netback/interface.c @@ -218,7 +218,8 @@ struct xen_netif *netif_alloc(struct device *parent, domid_t domid, unsigned int netback_carrier_off(netif); - netif->credit_bytes = netif->remaining_credit = ~0UL; + atomic64_set(&netif->remaining_credit,~0UL); + netif->credit_bytes = ~0UL; netif->credit_usec = 0UL; init_timer(&netif->credit_timeout); /* Initialize 'expires' now: it's used to track the credit window. */ diff --git a/drivers/xen/netback/netback.c b/drivers/xen/netback/netback.c index ddc701f..3a7b048 100644 --- a/drivers/xen/netback/netback.c +++ b/drivers/xen/netback/netback.c @@ -733,11 +733,11 @@ static void tx_add_credit(struct xen_netif *netif) max_burst = max(max_burst, netif->credit_bytes); /* Take care that adding a new chunk of credit doesn't wrap to zero. */ - max_credit = netif->remaining_credit + netif->credit_bytes; - if (max_credit < netif->remaining_credit) + max_credit = atomic64_read(&netif->remaining_credit) + netif->credit_bytes; + if (max_credit < atomic64_read(&netif->remaining_credit)) max_credit = ULONG_MAX; /* wrapped: clamp to ULONG_MAX */ - netif->remaining_credit = min(max_credit, max_burst); + atomic64_set(&netif->remaining_credit,min(max_credit,max_burst)); } static void tx_credit_callback(unsigned long data) @@ -1147,7 +1147,7 @@ static bool tx_credit_exceeded(struct xen_netif *netif, unsigned size) } /* Still too big to send right now? Set a callback. */ - if (size > netif->remaining_credit) { + if (size > atomic64_read(&netif->remaining_credit)) { netif->credit_timeout.data = (unsigned long)netif; netif->credit_timeout.function = @@ -1195,13 +1195,13 @@ static unsigned net_tx_build_mops(void) memcpy(&txreq, RING_GET_REQUEST(&netif->tx, idx), sizeof(txreq)); /* Credit-based scheduling. */ - if (txreq.size > netif->remaining_credit && + if (txreq.size > atomic64_read(&netif->remaining_credit) && tx_credit_exceeded(netif, txreq.size)) { netif_put(netif); continue; } - netif->remaining_credit -= txreq.size; + atomic64_sub(txreq.size,&netif->remaining_credit); work_to_do--; netif->tx.req_cons = ++idx; diff --git a/drivers/xen/netback/xenbus.c b/drivers/xen/netback/xenbus.c index 70636d0..318c5a1 100644 --- a/drivers/xen/netback/xenbus.c +++ b/drivers/xen/netback/xenbus.c @@ -33,6 +33,7 @@ static int connect_rings(struct backend_info *); static void connect(struct backend_info *); static void backend_create_netif(struct backend_info *be); static void unregister_hotplug_status_watch(struct backend_info *be); +static void unregister_rate_watch(struct backend_info *be); static int netback_remove(struct xenbus_device *dev) { @@ -41,6 +42,7 @@ static int netback_remove(struct xenbus_device *dev) //netback_remove_accelerators(be, dev); unregister_hotplug_status_watch(be); + unregister_rate_watch(be); if (be->netif) { kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE); xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status"); @@ -350,6 +352,15 @@ static void unregister_hotplug_status_watch(struct backend_info *be) be->have_hotplug_status_watch = 0; } +static void unregister_rate_watch(struct backend_info *be) +{ + if (be->have_rate_watch) { + unregister_xenbus_watch(&be->rate_watch); + kfree(be->rate_watch.node); + } + be->have_rate_watch = 0; +} + static void hotplug_status_changed(struct xenbus_watch *watch, const char **vec, unsigned int vec_size) @@ -371,6 +382,19 @@ static void hotplug_status_changed(struct xenbus_watch *watch, kfree(str); } +static void rate_changed(struct xenbus_watch *watch, + const char **vec, unsigned int len) +{ + + struct backend_info *be=container_of(watch,struct backend_info, rate_watch); + + IPRINTK("rate changed\n"); + xen_net_read_rate(be->dev, &be->netif->credit_bytes, + &be->netif->credit_usec); + atomic64_set(&be->netif->remaining_credit,be->netif->credit_bytes); + xenbus_write(XBT_NIL, be->dev->nodename, "rate_status", "changed"); +} + static void connect(struct backend_info *be) { int err; @@ -388,7 +412,7 @@ static void connect(struct backend_info *be) xen_net_read_rate(dev, &be->netif->credit_bytes, &be->netif->credit_usec); - be->netif->remaining_credit = be->netif->credit_bytes; + atomic64_set(&be->netif->remaining_credit,be->netif->credit_bytes); unregister_hotplug_status_watch(be); err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, @@ -401,7 +425,16 @@ static void connect(struct backend_info *be) be->have_hotplug_status_watch = 1; } - netif_wake_queue(be->netif->dev); + unregister_rate_watch(be); + err=xenbus_watch_pathfmt(dev, &be->rate_watch, + rate_changed,"%s/%s", dev->nodename, "rate"); + + if(!err){ + be->have_rate_watch=1; + } + + netif_wake_queue(be->netif->dev); + }