diff options
Diffstat (limited to 'net/switchdev/switchdev.c')
-rw-r--r-- | net/switchdev/switchdev.c | 100 |
1 files changed, 2 insertions, 98 deletions
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index d81cfcee9ad9..90ba4a1f0a6d 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c | |||
@@ -23,78 +23,6 @@ | |||
23 | #include <linux/rtnetlink.h> | 23 | #include <linux/rtnetlink.h> |
24 | #include <net/switchdev.h> | 24 | #include <net/switchdev.h> |
25 | 25 | ||
26 | /** | ||
27 | * switchdev_trans_item_enqueue - Enqueue data item to transaction queue | ||
28 | * | ||
29 | * @trans: transaction | ||
30 | * @data: pointer to data being queued | ||
31 | * @destructor: data destructor | ||
32 | * @tritem: transaction item being queued | ||
33 | * | ||
34 | * Enqeueue data item to transaction queue. tritem is typically placed in | ||
35 | * cointainter pointed at by data pointer. Destructor is called on | ||
36 | * transaction abort and after successful commit phase in case | ||
37 | * the caller did not dequeue the item before. | ||
38 | */ | ||
39 | void switchdev_trans_item_enqueue(struct switchdev_trans *trans, | ||
40 | void *data, void (*destructor)(void const *), | ||
41 | struct switchdev_trans_item *tritem) | ||
42 | { | ||
43 | tritem->data = data; | ||
44 | tritem->destructor = destructor; | ||
45 | list_add_tail(&tritem->list, &trans->item_list); | ||
46 | } | ||
47 | EXPORT_SYMBOL_GPL(switchdev_trans_item_enqueue); | ||
48 | |||
49 | static struct switchdev_trans_item * | ||
50 | __switchdev_trans_item_dequeue(struct switchdev_trans *trans) | ||
51 | { | ||
52 | struct switchdev_trans_item *tritem; | ||
53 | |||
54 | if (list_empty(&trans->item_list)) | ||
55 | return NULL; | ||
56 | tritem = list_first_entry(&trans->item_list, | ||
57 | struct switchdev_trans_item, list); | ||
58 | list_del(&tritem->list); | ||
59 | return tritem; | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * switchdev_trans_item_dequeue - Dequeue data item from transaction queue | ||
64 | * | ||
65 | * @trans: transaction | ||
66 | */ | ||
67 | void *switchdev_trans_item_dequeue(struct switchdev_trans *trans) | ||
68 | { | ||
69 | struct switchdev_trans_item *tritem; | ||
70 | |||
71 | tritem = __switchdev_trans_item_dequeue(trans); | ||
72 | BUG_ON(!tritem); | ||
73 | return tritem->data; | ||
74 | } | ||
75 | EXPORT_SYMBOL_GPL(switchdev_trans_item_dequeue); | ||
76 | |||
77 | static void switchdev_trans_init(struct switchdev_trans *trans) | ||
78 | { | ||
79 | INIT_LIST_HEAD(&trans->item_list); | ||
80 | } | ||
81 | |||
82 | static void switchdev_trans_items_destroy(struct switchdev_trans *trans) | ||
83 | { | ||
84 | struct switchdev_trans_item *tritem; | ||
85 | |||
86 | while ((tritem = __switchdev_trans_item_dequeue(trans))) | ||
87 | tritem->destructor(tritem->data); | ||
88 | } | ||
89 | |||
90 | static void switchdev_trans_items_warn_destroy(struct net_device *dev, | ||
91 | struct switchdev_trans *trans) | ||
92 | { | ||
93 | WARN(!list_empty(&trans->item_list), "%s: transaction item queue is not empty.\n", | ||
94 | dev->name); | ||
95 | switchdev_trans_items_destroy(trans); | ||
96 | } | ||
97 | |||
98 | static LIST_HEAD(deferred); | 26 | static LIST_HEAD(deferred); |
99 | static DEFINE_SPINLOCK(deferred_lock); | 27 | static DEFINE_SPINLOCK(deferred_lock); |
100 | 28 | ||
@@ -208,8 +136,6 @@ static int switchdev_port_attr_set_now(struct net_device *dev, | |||
208 | struct switchdev_trans trans; | 136 | struct switchdev_trans trans; |
209 | int err; | 137 | int err; |
210 | 138 | ||
211 | switchdev_trans_init(&trans); | ||
212 | |||
213 | /* Phase I: prepare for attr set. Driver/device should fail | 139 | /* Phase I: prepare for attr set. Driver/device should fail |
214 | * here if there are going to be issues in the commit phase, | 140 | * here if there are going to be issues in the commit phase, |
215 | * such as lack of resources or support. The driver/device | 141 | * such as lack of resources or support. The driver/device |
@@ -220,17 +146,8 @@ static int switchdev_port_attr_set_now(struct net_device *dev, | |||
220 | trans.ph_prepare = true; | 146 | trans.ph_prepare = true; |
221 | err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr, | 147 | err = switchdev_port_attr_notify(SWITCHDEV_PORT_ATTR_SET, dev, attr, |
222 | &trans); | 148 | &trans); |
223 | if (err) { | 149 | if (err) |
224 | /* Prepare phase failed: abort the transaction. Any | ||
225 | * resources reserved in the prepare phase are | ||
226 | * released. | ||
227 | */ | ||
228 | |||
229 | if (err != -EOPNOTSUPP) | ||
230 | switchdev_trans_items_destroy(&trans); | ||
231 | |||
232 | return err; | 150 | return err; |
233 | } | ||
234 | 151 | ||
235 | /* Phase II: commit attr set. This cannot fail as a fault | 152 | /* Phase II: commit attr set. This cannot fail as a fault |
236 | * of driver/device. If it does, it's a bug in the driver/device | 153 | * of driver/device. If it does, it's a bug in the driver/device |
@@ -242,7 +159,6 @@ static int switchdev_port_attr_set_now(struct net_device *dev, | |||
242 | &trans); | 159 | &trans); |
243 | WARN(err, "%s: Commit of attribute (id=%d) failed.\n", | 160 | WARN(err, "%s: Commit of attribute (id=%d) failed.\n", |
244 | dev->name, attr->id); | 161 | dev->name, attr->id); |
245 | switchdev_trans_items_warn_destroy(dev, &trans); | ||
246 | 162 | ||
247 | return err; | 163 | return err; |
248 | } | 164 | } |
@@ -341,8 +257,6 @@ static int switchdev_port_obj_add_now(struct net_device *dev, | |||
341 | 257 | ||
342 | ASSERT_RTNL(); | 258 | ASSERT_RTNL(); |
343 | 259 | ||
344 | switchdev_trans_init(&trans); | ||
345 | |||
346 | /* Phase I: prepare for obj add. Driver/device should fail | 260 | /* Phase I: prepare for obj add. Driver/device should fail |
347 | * here if there are going to be issues in the commit phase, | 261 | * here if there are going to be issues in the commit phase, |
348 | * such as lack of resources or support. The driver/device | 262 | * such as lack of resources or support. The driver/device |
@@ -353,17 +267,8 @@ static int switchdev_port_obj_add_now(struct net_device *dev, | |||
353 | trans.ph_prepare = true; | 267 | trans.ph_prepare = true; |
354 | err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, | 268 | err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, |
355 | dev, obj, &trans, extack); | 269 | dev, obj, &trans, extack); |
356 | if (err) { | 270 | if (err) |
357 | /* Prepare phase failed: abort the transaction. Any | ||
358 | * resources reserved in the prepare phase are | ||
359 | * released. | ||
360 | */ | ||
361 | |||
362 | if (err != -EOPNOTSUPP) | ||
363 | switchdev_trans_items_destroy(&trans); | ||
364 | |||
365 | return err; | 271 | return err; |
366 | } | ||
367 | 272 | ||
368 | /* Phase II: commit obj add. This cannot fail as a fault | 273 | /* Phase II: commit obj add. This cannot fail as a fault |
369 | * of driver/device. If it does, it's a bug in the driver/device | 274 | * of driver/device. If it does, it's a bug in the driver/device |
@@ -374,7 +279,6 @@ static int switchdev_port_obj_add_now(struct net_device *dev, | |||
374 | err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, | 279 | err = switchdev_port_obj_notify(SWITCHDEV_PORT_OBJ_ADD, |
375 | dev, obj, &trans, extack); | 280 | dev, obj, &trans, extack); |
376 | WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id); | 281 | WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id); |
377 | switchdev_trans_items_warn_destroy(dev, &trans); | ||
378 | 282 | ||
379 | return err; | 283 | return err; |
380 | } | 284 | } |