* compatible (i.e. if the accelerator should be used by the
* backend)
*/
-static int match_accelerator(struct backend_info *be,
+static int match_accelerator(struct xenbus_device *xendev,
+ struct backend_info *be,
struct netback_accelerator *accelerator)
{
- /*
- * This could do with being more sophisticated. For example,
- * determine which hardware is being used by each backend from
- * the bridge and network topology of the domain
- */
- return be->accelerator == NULL;
+ int rc = 0;
+ char *eth_name = xenbus_read(XBT_NIL, xendev->nodename, "accel", NULL);
+
+ if (IS_ERR(eth_name)) {
+ /* Probably means not present */
+ DPRINTK("%s: no match due to xenbus_read accel error %d\n",
+ __FUNCTION__, PTR_ERR(eth_name));
+ return 0;
+ } else {
+ if (!strcmp(eth_name, accelerator->eth_name))
+ rc = 1;
+ kfree(eth_name);
+ return rc;
+ }
}
/*
if (!strcmp("vif", xendev->devicetype)) {
struct backend_info *be = xendev->dev.driver_data;
- if (match_accelerator(be, accelerator)) {
+ if (match_accelerator(xendev, be, accelerator)) {
be->accelerator = accelerator;
atomic_inc(&be->accelerator->use_count);
be->accelerator->hooks->probe(xendev);
* Entry point for an netback accelerator plugin module. Called to
* advertise its presence, and connect to any suitable backends.
*/
-void netback_connect_accelerator(int id, const char *frontend,
+void netback_connect_accelerator(int id, const char *eth_name,
struct netback_accel_hooks *hooks)
{
struct netback_accelerator *new_accelerator =
kmalloc(sizeof(struct netback_accelerator), GFP_KERNEL);
- unsigned frontend_len, flags;
+ unsigned eth_name_len, flags;
if (!new_accelerator) {
DPRINTK("%s: failed to allocate memory for accelerator\n",
new_accelerator->id = id;
- frontend_len = strlen(frontend)+1;
- new_accelerator->frontend = kmalloc(frontend_len, GFP_KERNEL);
- if (!new_accelerator->frontend) {
- DPRINTK("%s: failed to allocate memory for frontend string\n",
+ eth_name_len = strlen(eth_name)+1;
+ new_accelerator->eth_name = kmalloc(eth_name_len, GFP_KERNEL);
+ if (!new_accelerator->eth_name) {
+ DPRINTK("%s: failed to allocate memory for eth_name string\n",
__FUNCTION__);
kfree(new_accelerator);
return;
}
- strlcpy(new_accelerator->frontend, frontend, frontend_len);
+ strlcpy(new_accelerator->eth_name, eth_name, eth_name_len);
new_accelerator->hooks = hooks;
/*
- * Disconnect an accerator plugin module that has previously been
+ * Remove the link from backend state to a particular accelerator
+ */
+static int netback_accelerator_cleanup_backend(struct device *dev, void *arg)
+{
+ struct netback_accelerator *accelerator =
+ (struct netback_accelerator *)arg;
+ struct xenbus_device *xendev = to_xenbus_device(dev);
+
+ if (!strcmp("vif", xendev->devicetype)) {
+ struct backend_info *be = xendev->dev.driver_data;
+ if (be->accelerator == accelerator)
+ be->accelerator = NULL;
+ }
+ return 0;
+}
+
+
+/*
+ * Disconnect an accelerator plugin module that has previously been
* connected.
*
* This should only be allowed when there are no remaining users -
* they should have already been removed. This is enforced through a
* usage count and BUG_ON(use!=0), but should be made more user-friendly
*/
-void netback_disconnect_accelerator(int id, const char *frontend)
+void netback_disconnect_accelerator(int id, const char *eth_name)
{
struct netback_accelerator *accelerator, *next;
unsigned flags;
spin_lock_irqsave(&accelerators_lock, flags);
list_for_each_entry_safe(accelerator, next, &accelerators_list, link) {
- if (strcmp(frontend, accelerator->frontend)) {
+ if (strcmp(eth_name, accelerator->eth_name)) {
BUG_ON(atomic_read(&accelerator->use_count) != 0);
list_del(&accelerator->link);
spin_unlock_irqrestore(&accelerators_lock, flags);
- kfree(accelerator->frontend);
+
+ xenbus_for_each_backend(accelerator,
+ netback_accelerator_cleanup_backend);
+
+ kfree(accelerator->eth_name);
kfree(accelerator);
return;
}
*/
spin_lock_irqsave(&accelerators_lock, flags);
list_for_each_entry(accelerator, &accelerators_list, link) {
- if (match_accelerator(be, accelerator)) {
+ if (match_accelerator(dev, be, accelerator)) {
be->accelerator = accelerator;
atomic_inc(&be->accelerator->use_count);
be->accelerator->hooks->probe(dev);