From 69f5df491e0becb75d2d795add7481a35218d657 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 24 Sep 2015 10:02:40 +0200 Subject: switchdev: rename "trans" to "trans_ph". This is temporary, name "trans" will be used for something else and "trans_ph" will eventually disappear. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/switchdev/switchdev.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'net/switchdev/switchdev.c') diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index fda38f830a10..df5a5446ff4c 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -163,7 +163,7 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) * but should not commit the attr. */ - attr->trans = SWITCHDEV_TRANS_PREPARE; + attr->trans_ph = SWITCHDEV_TRANS_PREPARE; err = __switchdev_port_attr_set(dev, attr); if (err) { /* Prepare phase failed: abort the transaction. Any @@ -172,7 +172,7 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) */ if (err != -EOPNOTSUPP) { - attr->trans = SWITCHDEV_TRANS_ABORT; + attr->trans_ph = SWITCHDEV_TRANS_ABORT; __switchdev_port_attr_set(dev, attr); } @@ -184,7 +184,7 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) * because the driver said everythings was OK in phase I. */ - attr->trans = SWITCHDEV_TRANS_COMMIT; + attr->trans_ph = SWITCHDEV_TRANS_COMMIT; err = __switchdev_port_attr_set(dev, attr); WARN(err, "%s: Commit of attribute (id=%d) failed.\n", dev->name, attr->id); @@ -243,7 +243,7 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) * but should not commit the obj. */ - obj->trans = SWITCHDEV_TRANS_PREPARE; + obj->trans_ph = SWITCHDEV_TRANS_PREPARE; err = __switchdev_port_obj_add(dev, obj); if (err) { /* Prepare phase failed: abort the transaction. Any @@ -252,7 +252,7 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) */ if (err != -EOPNOTSUPP) { - obj->trans = SWITCHDEV_TRANS_ABORT; + obj->trans_ph = SWITCHDEV_TRANS_ABORT; __switchdev_port_obj_add(dev, obj); } @@ -264,7 +264,7 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) * because the driver said everythings was OK in phase I. */ - obj->trans = SWITCHDEV_TRANS_COMMIT; + obj->trans_ph = SWITCHDEV_TRANS_COMMIT; err = __switchdev_port_obj_add(dev, obj); WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id); -- cgit From 7ea6eb3f56f45cf4babae8b9a7421868e5005f17 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 24 Sep 2015 10:02:41 +0200 Subject: switchdev: introduce transaction item queue for attr_set and obj_add Now, the memory allocation in prepare/commit state is done separatelly in each driver (rocker). Introduce the similar mechanism in generic switchdev code, in form of queue. That can be used not only for memory allocations, but also for different items. Abort item destruction is handled as well. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/switchdev/switchdev.c | 111 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 98 insertions(+), 13 deletions(-) (limited to 'net/switchdev/switchdev.c') diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index df5a5446ff4c..35e2967ffa18 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -1,6 +1,6 @@ /* * net/switchdev/switchdev.c - Switch device API - * Copyright (c) 2014 Jiri Pirko + * Copyright (c) 2014-2015 Jiri Pirko * Copyright (c) 2014-2015 Scott Feldman * * This program is free software; you can redistribute it and/or modify @@ -16,9 +16,82 @@ #include #include #include +#include #include #include +/** + * switchdev_trans_item_enqueue - Enqueue data item to transaction queue + * + * @trans: transaction + * @data: pointer to data being queued + * @destructor: data destructor + * @tritem: transaction item being queued + * + * Enqeueue data item to transaction queue. tritem is typically placed in + * cointainter pointed at by data pointer. Destructor is called on + * transaction abort and after successful commit phase in case + * the caller did not dequeue the item before. + */ +void switchdev_trans_item_enqueue(struct switchdev_trans *trans, + void *data, void (*destructor)(void const *), + struct switchdev_trans_item *tritem) +{ + tritem->data = data; + tritem->destructor = destructor; + list_add_tail(&tritem->list, &trans->item_list); +} +EXPORT_SYMBOL_GPL(switchdev_trans_item_enqueue); + +static struct switchdev_trans_item * +__switchdev_trans_item_dequeue(struct switchdev_trans *trans) +{ + struct switchdev_trans_item *tritem; + + if (list_empty(&trans->item_list)) + return NULL; + tritem = list_first_entry(&trans->item_list, + struct switchdev_trans_item, list); + list_del(&tritem->list); + return tritem; +} + +/** + * switchdev_trans_item_dequeue - Dequeue data item from transaction queue + * + * @trans: transaction + */ +void *switchdev_trans_item_dequeue(struct switchdev_trans *trans) +{ + struct switchdev_trans_item *tritem; + + tritem = __switchdev_trans_item_dequeue(trans); + BUG_ON(!tritem); + return tritem->data; +} +EXPORT_SYMBOL_GPL(switchdev_trans_item_dequeue); + +static void switchdev_trans_init(struct switchdev_trans *trans) +{ + INIT_LIST_HEAD(&trans->item_list); +} + +static void switchdev_trans_items_destroy(struct switchdev_trans *trans) +{ + struct switchdev_trans_item *tritem; + + while ((tritem = __switchdev_trans_item_dequeue(trans))) + tritem->destructor(tritem->data); +} + +static void switchdev_trans_items_warn_destroy(struct net_device *dev, + struct switchdev_trans *trans) +{ + WARN(!list_empty(&trans->item_list), "%s: transaction item queue is not empty.\n", + dev->name); + switchdev_trans_items_destroy(trans); +} + /** * switchdev_port_attr_get - Get port attribute * @@ -62,7 +135,8 @@ int switchdev_port_attr_get(struct net_device *dev, struct switchdev_attr *attr) EXPORT_SYMBOL_GPL(switchdev_port_attr_get); static int __switchdev_port_attr_set(struct net_device *dev, - struct switchdev_attr *attr) + struct switchdev_attr *attr, + struct switchdev_trans *trans) { const struct switchdev_ops *ops = dev->switchdev_ops; struct net_device *lower_dev; @@ -70,7 +144,7 @@ static int __switchdev_port_attr_set(struct net_device *dev, int err = -EOPNOTSUPP; if (ops && ops->switchdev_port_attr_set) - return ops->switchdev_port_attr_set(dev, attr); + return ops->switchdev_port_attr_set(dev, attr, trans); if (attr->flags & SWITCHDEV_F_NO_RECURSE) return err; @@ -81,7 +155,7 @@ static int __switchdev_port_attr_set(struct net_device *dev, */ netdev_for_each_lower_dev(dev, lower_dev, iter) { - err = __switchdev_port_attr_set(lower_dev, attr); + err = __switchdev_port_attr_set(lower_dev, attr, trans); if (err) break; } @@ -144,6 +218,7 @@ static int switchdev_port_attr_set_defer(struct net_device *dev, */ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) { + struct switchdev_trans trans; int err; if (!rtnl_is_locked()) { @@ -156,6 +231,8 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) return switchdev_port_attr_set_defer(dev, attr); } + switchdev_trans_init(&trans); + /* Phase I: prepare for attr set. Driver/device should fail * here if there are going to be issues in the commit phase, * such as lack of resources or support. The driver/device @@ -164,7 +241,7 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) */ attr->trans_ph = SWITCHDEV_TRANS_PREPARE; - err = __switchdev_port_attr_set(dev, attr); + err = __switchdev_port_attr_set(dev, attr, &trans); if (err) { /* Prepare phase failed: abort the transaction. Any * resources reserved in the prepare phase are @@ -173,7 +250,8 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) if (err != -EOPNOTSUPP) { attr->trans_ph = SWITCHDEV_TRANS_ABORT; - __switchdev_port_attr_set(dev, attr); + __switchdev_port_attr_set(dev, attr, &trans); + switchdev_trans_items_destroy(&trans); } return err; @@ -185,16 +263,18 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) */ attr->trans_ph = SWITCHDEV_TRANS_COMMIT; - err = __switchdev_port_attr_set(dev, attr); + err = __switchdev_port_attr_set(dev, attr, &trans); WARN(err, "%s: Commit of attribute (id=%d) failed.\n", dev->name, attr->id); + switchdev_trans_items_warn_destroy(dev, &trans); return err; } EXPORT_SYMBOL_GPL(switchdev_port_attr_set); static int __switchdev_port_obj_add(struct net_device *dev, - struct switchdev_obj *obj) + struct switchdev_obj *obj, + struct switchdev_trans *trans) { const struct switchdev_ops *ops = dev->switchdev_ops; struct net_device *lower_dev; @@ -202,7 +282,7 @@ static int __switchdev_port_obj_add(struct net_device *dev, int err = -EOPNOTSUPP; if (ops && ops->switchdev_port_obj_add) - return ops->switchdev_port_obj_add(dev, obj); + return ops->switchdev_port_obj_add(dev, obj, trans); /* Switch device port(s) may be stacked under * bond/team/vlan dev, so recurse down to add object on @@ -210,7 +290,7 @@ static int __switchdev_port_obj_add(struct net_device *dev, */ netdev_for_each_lower_dev(dev, lower_dev, iter) { - err = __switchdev_port_obj_add(lower_dev, obj); + err = __switchdev_port_obj_add(lower_dev, obj, trans); if (err) break; } @@ -232,10 +312,13 @@ static int __switchdev_port_obj_add(struct net_device *dev, */ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) { + struct switchdev_trans trans; int err; ASSERT_RTNL(); + switchdev_trans_init(&trans); + /* Phase I: prepare for obj add. Driver/device should fail * here if there are going to be issues in the commit phase, * such as lack of resources or support. The driver/device @@ -244,7 +327,7 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) */ obj->trans_ph = SWITCHDEV_TRANS_PREPARE; - err = __switchdev_port_obj_add(dev, obj); + err = __switchdev_port_obj_add(dev, obj, &trans); if (err) { /* Prepare phase failed: abort the transaction. Any * resources reserved in the prepare phase are @@ -253,7 +336,8 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) if (err != -EOPNOTSUPP) { obj->trans_ph = SWITCHDEV_TRANS_ABORT; - __switchdev_port_obj_add(dev, obj); + __switchdev_port_obj_add(dev, obj, &trans); + switchdev_trans_items_destroy(&trans); } return err; @@ -265,8 +349,9 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) */ obj->trans_ph = SWITCHDEV_TRANS_COMMIT; - err = __switchdev_port_obj_add(dev, obj); + err = __switchdev_port_obj_add(dev, obj, &trans); WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id); + switchdev_trans_items_warn_destroy(dev, &trans); return err; } -- cgit From f8db83486e316ff50f97961a82b614985645508e Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 24 Sep 2015 10:02:42 +0200 Subject: switchdev: move transaction phase enum under transaction structure Before it disappears completely, move transaction phase enum under transaction structure and make attr/obj structures a bit cleaner. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/switchdev/switchdev.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'net/switchdev/switchdev.c') diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 35e2967ffa18..d1c7d51620b1 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -240,7 +240,7 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) * but should not commit the attr. */ - attr->trans_ph = SWITCHDEV_TRANS_PREPARE; + trans.ph = SWITCHDEV_TRANS_PREPARE; err = __switchdev_port_attr_set(dev, attr, &trans); if (err) { /* Prepare phase failed: abort the transaction. Any @@ -249,7 +249,7 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) */ if (err != -EOPNOTSUPP) { - attr->trans_ph = SWITCHDEV_TRANS_ABORT; + trans.ph = SWITCHDEV_TRANS_ABORT; __switchdev_port_attr_set(dev, attr, &trans); switchdev_trans_items_destroy(&trans); } @@ -262,7 +262,7 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) * because the driver said everythings was OK in phase I. */ - attr->trans_ph = SWITCHDEV_TRANS_COMMIT; + trans.ph = SWITCHDEV_TRANS_COMMIT; err = __switchdev_port_attr_set(dev, attr, &trans); WARN(err, "%s: Commit of attribute (id=%d) failed.\n", dev->name, attr->id); @@ -326,7 +326,7 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) * but should not commit the obj. */ - obj->trans_ph = SWITCHDEV_TRANS_PREPARE; + trans.ph = SWITCHDEV_TRANS_PREPARE; err = __switchdev_port_obj_add(dev, obj, &trans); if (err) { /* Prepare phase failed: abort the transaction. Any @@ -335,7 +335,7 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) */ if (err != -EOPNOTSUPP) { - obj->trans_ph = SWITCHDEV_TRANS_ABORT; + trans.ph = SWITCHDEV_TRANS_ABORT; __switchdev_port_obj_add(dev, obj, &trans); switchdev_trans_items_destroy(&trans); } @@ -348,7 +348,7 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) * because the driver said everythings was OK in phase I. */ - obj->trans_ph = SWITCHDEV_TRANS_COMMIT; + trans.ph = SWITCHDEV_TRANS_COMMIT; err = __switchdev_port_obj_add(dev, obj, &trans); WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id); switchdev_trans_items_warn_destroy(dev, &trans); -- cgit From 9f6467cf229a0e8a7580401b07de2a76e4c8618d Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 24 Sep 2015 10:02:47 +0200 Subject: switchdev: remove "ABORT" transaction phase No longer used by drivers, as transaction queue with item destructors takes care of abort phase internally in switchdev code. So kill it. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/switchdev/switchdev.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'net/switchdev/switchdev.c') diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index d1c7d51620b1..1adeedade0fb 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -248,11 +248,8 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) * released. */ - if (err != -EOPNOTSUPP) { - trans.ph = SWITCHDEV_TRANS_ABORT; - __switchdev_port_attr_set(dev, attr, &trans); + if (err != -EOPNOTSUPP) switchdev_trans_items_destroy(&trans); - } return err; } @@ -334,11 +331,8 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) * released. */ - if (err != -EOPNOTSUPP) { - trans.ph = SWITCHDEV_TRANS_ABORT; - __switchdev_port_obj_add(dev, obj, &trans); + if (err != -EOPNOTSUPP) switchdev_trans_items_destroy(&trans); - } return err; } -- cgit From f623ab7f51b1bfb523c9cd492747392abf3c4421 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 24 Sep 2015 10:02:49 +0200 Subject: switchdev: reduce transaction phase enum down to a boolean Now, since we have only 2 values for transaction phase, just use bool. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- net/switchdev/switchdev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net/switchdev/switchdev.c') diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 1adeedade0fb..00ee547ba45b 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -240,7 +240,7 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) * but should not commit the attr. */ - trans.ph = SWITCHDEV_TRANS_PREPARE; + trans.ph_prepare = true; err = __switchdev_port_attr_set(dev, attr, &trans); if (err) { /* Prepare phase failed: abort the transaction. Any @@ -259,7 +259,7 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr) * because the driver said everythings was OK in phase I. */ - trans.ph = SWITCHDEV_TRANS_COMMIT; + trans.ph_prepare = false; err = __switchdev_port_attr_set(dev, attr, &trans); WARN(err, "%s: Commit of attribute (id=%d) failed.\n", dev->name, attr->id); @@ -323,7 +323,7 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) * but should not commit the obj. */ - trans.ph = SWITCHDEV_TRANS_PREPARE; + trans.ph_prepare = true; err = __switchdev_port_obj_add(dev, obj, &trans); if (err) { /* Prepare phase failed: abort the transaction. Any @@ -342,7 +342,7 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj) * because the driver said everythings was OK in phase I. */ - trans.ph = SWITCHDEV_TRANS_COMMIT; + trans.ph_prepare = false; err = __switchdev_port_obj_add(dev, obj, &trans); WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id); switchdev_trans_items_warn_destroy(dev, &trans); -- cgit