aboutsummaryrefslogtreecommitdiffstats
path: root/net/switchdev/switchdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/switchdev/switchdev.c')
-rw-r--r--net/switchdev/switchdev.c100
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 */
39void 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}
47EXPORT_SYMBOL_GPL(switchdev_trans_item_enqueue);
48
49static 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 */
67void *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}
75EXPORT_SYMBOL_GPL(switchdev_trans_item_dequeue);
76
77static void switchdev_trans_init(struct switchdev_trans *trans)
78{
79 INIT_LIST_HEAD(&trans->item_list);
80}
81
82static 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
90static 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
98static LIST_HEAD(deferred); 26static LIST_HEAD(deferred);
99static DEFINE_SPINLOCK(deferred_lock); 27static 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}