* [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
@ 2015-09-19 12:29 Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 1/6] switchdev: rename "trans" to "trans_ph" Jiri Pirko
` (8 more replies)
0 siblings, 9 replies; 23+ messages in thread
From: Jiri Pirko @ 2015-09-19 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, idosch, eladr, sfeldma, f.fainelli, linux, vivien.didelot
Jiri Pirko (6):
switchdev: rename "trans" to "trans_ph".
switchdev: introduce transaction infrastructure for attr_set and
obj_add
rocker: switch to local transaction phase enum
switchdev: move transaction phase enum under transaction structure
rocker: use switchdev transaction queue for allocated memory
switchdev: split commit and prepare phase into two callbacks
drivers/net/ethernet/rocker/rocker.c | 579 ++++++++++++++++++-----------------
include/net/switchdev.h | 39 ++-
net/dsa/slave.c | 129 +++++---
net/switchdev/switchdev.c | 153 +++++++--
4 files changed, 545 insertions(+), 355 deletions(-)
--
1.9.3
^ permalink raw reply [flat|nested] 23+ messages in thread
* [patch net-next RFC 1/6] switchdev: rename "trans" to "trans_ph".
2015-09-19 12:29 [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Jiri Pirko
@ 2015-09-19 12:29 ` Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 2/6] switchdev: introduce transaction infrastructure for attr_set and obj_add Jiri Pirko
` (7 subsequent siblings)
8 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2015-09-19 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, idosch, eladr, sfeldma, f.fainelli, linux, vivien.didelot
This is temporary, name "trans" will be used for something else and
"trans_ph" will eventually disappear.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
drivers/net/ethernet/rocker/rocker.c | 382 +++++++++++++++++------------------
include/net/switchdev.h | 6 +-
net/dsa/slave.c | 8 +-
net/switchdev/switchdev.c | 12 +-
4 files changed, 204 insertions(+), 204 deletions(-)
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index 34ac41a..b5f2ff8 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -340,7 +340,7 @@ static bool rocker_port_is_ovsed(const struct rocker_port *rocker_port)
#define ROCKER_OP_FLAG_REFRESH BIT(3)
static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
size_t size)
{
struct list_head *elem = NULL;
@@ -356,7 +356,7 @@ static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port,
* memory used in the commit phase.
*/
- switch (trans) {
+ switch (trans_ph) {
case SWITCHDEV_TRANS_PREPARE:
elem = kzalloc(size + sizeof(*elem), gfp_flags);
if (!elem)
@@ -381,20 +381,20 @@ static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port,
}
static void *rocker_port_kzalloc(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
size_t size)
{
- return __rocker_port_mem_alloc(rocker_port, trans, flags, size);
+ return __rocker_port_mem_alloc(rocker_port, trans_ph, flags, size);
}
static void *rocker_port_kcalloc(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
size_t n, size_t size)
{
- return __rocker_port_mem_alloc(rocker_port, trans, flags, n * size);
+ return __rocker_port_mem_alloc(rocker_port, trans_ph, flags, n * size);
}
-static void rocker_port_kfree(enum switchdev_trans trans, const void *mem)
+static void rocker_port_kfree(enum switchdev_trans_ph trans_ph, const void *mem)
{
struct list_head *elem;
@@ -403,7 +403,7 @@ static void rocker_port_kfree(enum switchdev_trans trans, const void *mem)
* commit phase.
*/
- if (trans == SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph == SWITCHDEV_TRANS_PREPARE)
return;
elem = (struct list_head *)mem - 1;
@@ -430,22 +430,22 @@ static void rocker_wait_init(struct rocker_wait *wait)
}
static struct rocker_wait *rocker_wait_create(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
int flags)
{
struct rocker_wait *wait;
- wait = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*wait));
+ wait = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*wait));
if (!wait)
return NULL;
rocker_wait_init(wait);
return wait;
}
-static void rocker_wait_destroy(enum switchdev_trans trans,
+static void rocker_wait_destroy(enum switchdev_trans_ph trans_ph,
struct rocker_wait *wait)
{
- rocker_port_kfree(trans, wait);
+ rocker_port_kfree(trans_ph, wait);
}
static bool rocker_wait_event_timeout(struct rocker_wait *wait,
@@ -1463,7 +1463,7 @@ static int rocker_event_link_change(const struct rocker *rocker,
}
static int rocker_port_fdb(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
const unsigned char *addr,
__be16 vlan_id, int flags);
@@ -1582,7 +1582,7 @@ typedef int (*rocker_cmd_proc_cb_t)(const struct rocker_port *rocker_port,
void *priv);
static int rocker_cmd_exec(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
rocker_cmd_prep_cb_t prepare, void *prepare_priv,
rocker_cmd_proc_cb_t process, void *process_priv)
{
@@ -1593,7 +1593,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port,
unsigned long lock_flags;
int err;
- wait = rocker_wait_create(rocker_port, trans, flags);
+ wait = rocker_wait_create(rocker_port, trans_ph, flags);
if (!wait)
return -ENOMEM;
wait->nowait = nowait;
@@ -1615,7 +1615,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port,
rocker_desc_cookie_ptr_set(desc_info, wait);
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph != SWITCHDEV_TRANS_PREPARE)
rocker_desc_head_set(rocker, &rocker->cmd_ring, desc_info);
spin_unlock_irqrestore(&rocker->cmd_ring_lock, lock_flags);
@@ -1623,7 +1623,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port,
if (nowait)
return 0;
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph != SWITCHDEV_TRANS_PREPARE)
if (!rocker_wait_event_timeout(wait, HZ / 10))
return -EIO;
@@ -1636,7 +1636,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port,
rocker_desc_gen_clear(desc_info);
out:
- rocker_wait_destroy(trans, wait);
+ rocker_wait_destroy(trans_ph, wait);
return err;
}
@@ -1915,9 +1915,9 @@ static int rocker_cmd_set_port_settings_mtu(struct rocker_port *rocker_port,
}
static int rocker_port_set_learning(struct rocker_port *rocker_port,
- enum switchdev_trans trans)
+ enum switchdev_trans_ph trans_ph)
{
- return rocker_cmd_exec(rocker_port, trans, 0,
+ return rocker_cmd_exec(rocker_port, trans_ph, 0,
rocker_cmd_set_port_learning_prep,
NULL, NULL, NULL);
}
@@ -2433,7 +2433,7 @@ rocker_flow_tbl_find(const struct rocker *rocker,
}
static int rocker_flow_tbl_add(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
struct rocker_flow_tbl_entry *match)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2449,9 +2449,9 @@ static int rocker_flow_tbl_add(struct rocker_port *rocker_port,
if (found) {
match->cookie = found->cookie;
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph != SWITCHDEV_TRANS_PREPARE)
hash_del(&found->entry);
- rocker_port_kfree(trans, found);
+ rocker_port_kfree(trans_ph, found);
found = match;
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_MOD;
} else {
@@ -2460,17 +2460,17 @@ static int rocker_flow_tbl_add(struct rocker_port *rocker_port,
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_ADD;
}
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph != SWITCHDEV_TRANS_PREPARE)
hash_add(rocker->flow_tbl, &found->entry, found->key_crc32);
spin_unlock_irqrestore(&rocker->flow_tbl_lock, lock_flags);
- return rocker_cmd_exec(rocker_port, trans, flags,
+ return rocker_cmd_exec(rocker_port, trans_ph, flags,
rocker_cmd_flow_tbl_add, found, NULL, NULL);
}
static int rocker_flow_tbl_del(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
struct rocker_flow_tbl_entry *match)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2486,43 +2486,43 @@ static int rocker_flow_tbl_del(struct rocker_port *rocker_port,
found = rocker_flow_tbl_find(rocker, match);
if (found) {
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph != SWITCHDEV_TRANS_PREPARE)
hash_del(&found->entry);
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_DEL;
}
spin_unlock_irqrestore(&rocker->flow_tbl_lock, lock_flags);
- rocker_port_kfree(trans, match);
+ rocker_port_kfree(trans_ph, match);
if (found) {
- err = rocker_cmd_exec(rocker_port, trans, flags,
+ err = rocker_cmd_exec(rocker_port, trans_ph, flags,
rocker_cmd_flow_tbl_del,
found, NULL, NULL);
- rocker_port_kfree(trans, found);
+ rocker_port_kfree(trans_ph, found);
}
return err;
}
static int rocker_flow_tbl_do(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
struct rocker_flow_tbl_entry *entry)
{
if (flags & ROCKER_OP_FLAG_REMOVE)
- return rocker_flow_tbl_del(rocker_port, trans, flags, entry);
+ return rocker_flow_tbl_del(rocker_port, trans_ph, flags, entry);
else
- return rocker_flow_tbl_add(rocker_port, trans, flags, entry);
+ return rocker_flow_tbl_add(rocker_port, trans_ph, flags, entry);
}
static int rocker_flow_tbl_ig_port(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
u32 in_pport, u32 in_pport_mask,
enum rocker_of_dpa_table_id goto_tbl)
{
struct rocker_flow_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2532,11 +2532,11 @@ static int rocker_flow_tbl_ig_port(struct rocker_port *rocker_port,
entry->key.ig_port.in_pport_mask = in_pport_mask;
entry->key.ig_port.goto_tbl = goto_tbl;
- return rocker_flow_tbl_do(rocker_port, trans, flags, entry);
+ return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry);
}
static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
u32 in_pport, __be16 vlan_id,
__be16 vlan_id_mask,
enum rocker_of_dpa_table_id goto_tbl,
@@ -2544,7 +2544,7 @@ static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port,
{
struct rocker_flow_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2558,11 +2558,11 @@ static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port,
entry->key.vlan.untagged = untagged;
entry->key.vlan.new_vlan_id = new_vlan_id;
- return rocker_flow_tbl_do(rocker_port, trans, flags, entry);
+ return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry);
}
static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
u32 in_pport, u32 in_pport_mask,
__be16 eth_type, const u8 *eth_dst,
const u8 *eth_dst_mask, __be16 vlan_id,
@@ -2571,7 +2571,7 @@ static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port,
{
struct rocker_flow_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2595,11 +2595,11 @@ static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port,
entry->key.term_mac.vlan_id_mask = vlan_id_mask;
entry->key.term_mac.copy_to_cpu = copy_to_cpu;
- return rocker_flow_tbl_do(rocker_port, trans, flags, entry);
+ return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry);
}
static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
const u8 *eth_dst, const u8 *eth_dst_mask,
__be16 vlan_id, u32 tunnel_id,
enum rocker_of_dpa_table_id goto_tbl,
@@ -2611,7 +2611,7 @@ static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port,
bool dflt = !eth_dst || (eth_dst && eth_dst_mask);
bool wild = false;
- entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2649,11 +2649,11 @@ static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port,
entry->key.bridge.group_id = group_id;
entry->key.bridge.copy_to_cpu = copy_to_cpu;
- return rocker_flow_tbl_do(rocker_port, trans, flags, entry);
+ return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry);
}
static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
__be16 eth_type, __be32 dst,
__be32 dst_mask, u32 priority,
enum rocker_of_dpa_table_id goto_tbl,
@@ -2661,7 +2661,7 @@ static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port,
{
struct rocker_flow_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2675,11 +2675,11 @@ static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port,
entry->key_len = offsetof(struct rocker_flow_tbl_key,
ucast_routing.group_id);
- return rocker_flow_tbl_do(rocker_port, trans, flags, entry);
+ return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry);
}
static int rocker_flow_tbl_acl(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
u32 in_pport, u32 in_pport_mask,
const u8 *eth_src, const u8 *eth_src_mask,
const u8 *eth_dst, const u8 *eth_dst_mask,
@@ -2691,7 +2691,7 @@ static int rocker_flow_tbl_acl(struct rocker_port *rocker_port,
u32 priority;
struct rocker_flow_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2726,7 +2726,7 @@ static int rocker_flow_tbl_acl(struct rocker_port *rocker_port,
entry->key.acl.ip_tos_mask = ip_tos_mask;
entry->key.acl.group_id = group_id;
- return rocker_flow_tbl_do(rocker_port, trans, flags, entry);
+ return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry);
}
static struct rocker_group_tbl_entry *
@@ -2744,22 +2744,22 @@ rocker_group_tbl_find(const struct rocker *rocker,
return NULL;
}
-static void rocker_group_tbl_entry_free(enum switchdev_trans trans,
+static void rocker_group_tbl_entry_free(enum switchdev_trans_ph trans_ph,
struct rocker_group_tbl_entry *entry)
{
switch (ROCKER_GROUP_TYPE_GET(entry->group_id)) {
case ROCKER_OF_DPA_GROUP_TYPE_L2_FLOOD:
case ROCKER_OF_DPA_GROUP_TYPE_L2_MCAST:
- rocker_port_kfree(trans, entry->group_ids);
+ rocker_port_kfree(trans_ph, entry->group_ids);
break;
default:
break;
}
- rocker_port_kfree(trans, entry);
+ rocker_port_kfree(trans_ph, entry);
}
static int rocker_group_tbl_add(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
struct rocker_group_tbl_entry *match)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2771,9 +2771,9 @@ static int rocker_group_tbl_add(struct rocker_port *rocker_port,
found = rocker_group_tbl_find(rocker, match);
if (found) {
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph != SWITCHDEV_TRANS_PREPARE)
hash_del(&found->entry);
- rocker_group_tbl_entry_free(trans, found);
+ rocker_group_tbl_entry_free(trans_ph, found);
found = match;
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_MOD;
} else {
@@ -2781,17 +2781,17 @@ static int rocker_group_tbl_add(struct rocker_port *rocker_port,
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_ADD;
}
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph != SWITCHDEV_TRANS_PREPARE)
hash_add(rocker->group_tbl, &found->entry, found->group_id);
spin_unlock_irqrestore(&rocker->group_tbl_lock, lock_flags);
- return rocker_cmd_exec(rocker_port, trans, flags,
+ return rocker_cmd_exec(rocker_port, trans_ph, flags,
rocker_cmd_group_tbl_add, found, NULL, NULL);
}
static int rocker_group_tbl_del(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
struct rocker_group_tbl_entry *match)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2804,95 +2804,95 @@ static int rocker_group_tbl_del(struct rocker_port *rocker_port,
found = rocker_group_tbl_find(rocker, match);
if (found) {
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph != SWITCHDEV_TRANS_PREPARE)
hash_del(&found->entry);
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_DEL;
}
spin_unlock_irqrestore(&rocker->group_tbl_lock, lock_flags);
- rocker_group_tbl_entry_free(trans, match);
+ rocker_group_tbl_entry_free(trans_ph, match);
if (found) {
- err = rocker_cmd_exec(rocker_port, trans, flags,
+ err = rocker_cmd_exec(rocker_port, trans_ph, flags,
rocker_cmd_group_tbl_del,
found, NULL, NULL);
- rocker_group_tbl_entry_free(trans, found);
+ rocker_group_tbl_entry_free(trans_ph, found);
}
return err;
}
static int rocker_group_tbl_do(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
struct rocker_group_tbl_entry *entry)
{
if (flags & ROCKER_OP_FLAG_REMOVE)
- return rocker_group_tbl_del(rocker_port, trans, flags, entry);
+ return rocker_group_tbl_del(rocker_port, trans_ph, flags, entry);
else
- return rocker_group_tbl_add(rocker_port, trans, flags, entry);
+ return rocker_group_tbl_add(rocker_port, trans_ph, flags, entry);
}
static int rocker_group_l2_interface(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
__be16 vlan_id, u32 out_pport,
int pop_vlan)
{
struct rocker_group_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
entry->group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport);
entry->l2_interface.pop_vlan = pop_vlan;
- return rocker_group_tbl_do(rocker_port, trans, flags, entry);
+ return rocker_group_tbl_do(rocker_port, trans_ph, flags, entry);
}
static int rocker_group_l2_fan_out(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
int flags, u8 group_count,
const u32 *group_ids, u32 group_id)
{
struct rocker_group_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
entry->group_id = group_id;
entry->group_count = group_count;
- entry->group_ids = rocker_port_kcalloc(rocker_port, trans, flags,
+ entry->group_ids = rocker_port_kcalloc(rocker_port, trans_ph, flags,
group_count, sizeof(u32));
if (!entry->group_ids) {
- rocker_port_kfree(trans, entry);
+ rocker_port_kfree(trans_ph, entry);
return -ENOMEM;
}
memcpy(entry->group_ids, group_ids, group_count * sizeof(u32));
- return rocker_group_tbl_do(rocker_port, trans, flags, entry);
+ return rocker_group_tbl_do(rocker_port, trans_ph, flags, entry);
}
static int rocker_group_l2_flood(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
__be16 vlan_id, u8 group_count,
const u32 *group_ids, u32 group_id)
{
- return rocker_group_l2_fan_out(rocker_port, trans, flags,
+ return rocker_group_l2_fan_out(rocker_port, trans_ph, flags,
group_count, group_ids,
group_id);
}
static int rocker_group_l3_unicast(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
u32 index, const u8 *src_mac, const u8 *dst_mac,
__be16 vlan_id, bool ttl_check, u32 pport)
{
struct rocker_group_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2905,7 +2905,7 @@ static int rocker_group_l3_unicast(struct rocker_port *rocker_port,
entry->l3_unicast.ttl_check = ttl_check;
entry->l3_unicast.group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, pport);
- return rocker_group_tbl_do(rocker_port, trans, flags, entry);
+ return rocker_group_tbl_do(rocker_port, trans_ph, flags, entry);
}
static struct rocker_neigh_tbl_entry *
@@ -2922,43 +2922,43 @@ rocker_neigh_tbl_find(const struct rocker *rocker, __be32 ip_addr)
}
static void _rocker_neigh_add(struct rocker *rocker,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
struct rocker_neigh_tbl_entry *entry)
{
- if (trans != SWITCHDEV_TRANS_COMMIT)
+ if (trans_ph != SWITCHDEV_TRANS_COMMIT)
entry->index = rocker->neigh_tbl_next_index++;
- if (trans == SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph == SWITCHDEV_TRANS_PREPARE)
return;
entry->ref_count++;
hash_add(rocker->neigh_tbl, &entry->entry,
be32_to_cpu(entry->ip_addr));
}
-static void _rocker_neigh_del(enum switchdev_trans trans,
+static void _rocker_neigh_del(enum switchdev_trans_ph trans_ph,
struct rocker_neigh_tbl_entry *entry)
{
- if (trans == SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph == SWITCHDEV_TRANS_PREPARE)
return;
if (--entry->ref_count == 0) {
hash_del(&entry->entry);
- rocker_port_kfree(trans, entry);
+ rocker_port_kfree(trans_ph, entry);
}
}
static void _rocker_neigh_update(struct rocker_neigh_tbl_entry *entry,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
const u8 *eth_dst, bool ttl_check)
{
if (eth_dst) {
ether_addr_copy(entry->eth_dst, eth_dst);
entry->ttl_check = ttl_check;
- } else if (trans != SWITCHDEV_TRANS_PREPARE) {
+ } else if (trans_ph != SWITCHDEV_TRANS_PREPARE) {
entry->ref_count++;
}
}
static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
int flags, __be32 ip_addr, const u8 *eth_dst)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2975,7 +2975,7 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port,
bool removing;
int err = 0;
- entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2992,12 +2992,12 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port,
entry->dev = rocker_port->dev;
ether_addr_copy(entry->eth_dst, eth_dst);
entry->ttl_check = true;
- _rocker_neigh_add(rocker, trans, entry);
+ _rocker_neigh_add(rocker, trans_ph, entry);
} else if (removing) {
memcpy(entry, found, sizeof(*entry));
- _rocker_neigh_del(trans, found);
+ _rocker_neigh_del(trans_ph, found);
} else if (updating) {
- _rocker_neigh_update(found, trans, eth_dst, true);
+ _rocker_neigh_update(found, trans_ph, eth_dst, true);
memcpy(entry, found, sizeof(*entry));
} else {
err = -ENOENT;
@@ -3014,7 +3014,7 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port,
* other routes' nexthops.
*/
- err = rocker_group_l3_unicast(rocker_port, trans, flags,
+ err = rocker_group_l3_unicast(rocker_port, trans_ph, flags,
entry->index,
rocker_port->dev->dev_addr,
entry->eth_dst,
@@ -3030,7 +3030,7 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port,
if (adding || removing) {
group_id = ROCKER_GROUP_L3_UNICAST(entry->index);
- err = rocker_flow_tbl_ucast4_routing(rocker_port, trans,
+ err = rocker_flow_tbl_ucast4_routing(rocker_port, trans_ph,
eth_type, ip_addr,
inet_make_mask(32),
priority, goto_tbl,
@@ -3044,13 +3044,13 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port,
err_out:
if (!adding)
- rocker_port_kfree(trans, entry);
+ rocker_port_kfree(trans_ph, entry);
return err;
}
static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port,
- enum switchdev_trans trans, __be32 ip_addr)
+ enum switchdev_trans_ph trans_ph, __be32 ip_addr)
{
struct net_device *dev = rocker_port->dev;
struct neighbour *n = __ipv4_neigh_lookup(dev, (__force u32)ip_addr);
@@ -3068,7 +3068,7 @@ static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port,
*/
if (n->nud_state & NUD_VALID)
- err = rocker_port_ipv4_neigh(rocker_port, trans, 0,
+ err = rocker_port_ipv4_neigh(rocker_port, trans_ph, 0,
ip_addr, n->ha);
else
neigh_event_send(n, NULL);
@@ -3078,7 +3078,7 @@ static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port,
}
static int rocker_port_ipv4_nh(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
__be32 ip_addr, u32 *index)
{
struct rocker *rocker = rocker_port->rocker;
@@ -3091,7 +3091,7 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port,
bool resolved = true;
int err = 0;
- entry = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -3108,13 +3108,13 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port,
if (adding) {
entry->ip_addr = ip_addr;
entry->dev = rocker_port->dev;
- _rocker_neigh_add(rocker, trans, entry);
+ _rocker_neigh_add(rocker, trans_ph, entry);
*index = entry->index;
resolved = false;
} else if (removing) {
- _rocker_neigh_del(trans, found);
+ _rocker_neigh_del(trans_ph, found);
} else if (updating) {
- _rocker_neigh_update(found, trans, NULL, false);
+ _rocker_neigh_update(found, trans_ph, NULL, false);
resolved = !is_zero_ether_addr(found->eth_dst);
} else {
err = -ENOENT;
@@ -3123,7 +3123,7 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port,
spin_unlock_irqrestore(&rocker->neigh_tbl_lock, lock_flags);
if (!adding)
- rocker_port_kfree(trans, entry);
+ rocker_port_kfree(trans_ph, entry);
if (err)
return err;
@@ -3131,13 +3131,13 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port,
/* Resolved means neigh ip_addr is resolved to neigh mac. */
if (!resolved)
- err = rocker_port_ipv4_resolve(rocker_port, trans, ip_addr);
+ err = rocker_port_ipv4_resolve(rocker_port, trans_ph, ip_addr);
return err;
}
static int rocker_port_vlan_flood_group(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
int flags, __be16 vlan_id)
{
struct rocker_port *p;
@@ -3148,7 +3148,7 @@ static int rocker_port_vlan_flood_group(struct rocker_port *rocker_port,
int err = 0;
int i;
- group_ids = rocker_port_kcalloc(rocker_port, trans, flags,
+ group_ids = rocker_port_kcalloc(rocker_port, trans_ph, flags,
rocker->port_count, sizeof(u32));
if (!group_ids)
return -ENOMEM;
@@ -3174,19 +3174,19 @@ static int rocker_port_vlan_flood_group(struct rocker_port *rocker_port,
if (group_count == 0)
goto no_ports_in_vlan;
- err = rocker_group_l2_flood(rocker_port, trans, flags, vlan_id,
+ err = rocker_group_l2_flood(rocker_port, trans_ph, flags, vlan_id,
group_count, group_ids, group_id);
if (err)
netdev_err(rocker_port->dev,
"Error (%d) port VLAN l2 flood group\n", err);
no_ports_in_vlan:
- rocker_port_kfree(trans, group_ids);
+ rocker_port_kfree(trans_ph, group_ids);
return err;
}
static int rocker_port_vlan_l2_groups(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
__be16 vlan_id, bool pop_vlan)
{
const struct rocker *rocker = rocker_port->rocker;
@@ -3204,7 +3204,7 @@ static int rocker_port_vlan_l2_groups(struct rocker_port *rocker_port,
if (rocker_port->stp_state == BR_STATE_LEARNING ||
rocker_port->stp_state == BR_STATE_FORWARDING) {
out_pport = rocker_port->pport;
- err = rocker_group_l2_interface(rocker_port, trans, flags,
+ err = rocker_group_l2_interface(rocker_port, trans_ph, flags,
vlan_id, out_pport, pop_vlan);
if (err) {
netdev_err(rocker_port->dev,
@@ -3229,7 +3229,7 @@ static int rocker_port_vlan_l2_groups(struct rocker_port *rocker_port,
return 0;
out_pport = 0;
- err = rocker_group_l2_interface(rocker_port, trans, flags,
+ err = rocker_group_l2_interface(rocker_port, trans_ph, flags,
vlan_id, out_pport, pop_vlan);
if (err) {
netdev_err(rocker_port->dev,
@@ -3292,7 +3292,7 @@ static struct rocker_ctrl {
};
static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
const struct rocker_ctrl *ctrl, __be16 vlan_id)
{
u32 in_pport = rocker_port->pport;
@@ -3308,7 +3308,7 @@ static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port,
u32 group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport);
int err;
- err = rocker_flow_tbl_acl(rocker_port, trans, flags,
+ err = rocker_flow_tbl_acl(rocker_port, trans_ph, flags,
in_pport, in_pport_mask,
eth_src, eth_src_mask,
ctrl->eth_dst, ctrl->eth_dst_mask,
@@ -3325,7 +3325,7 @@ static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port,
}
static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
const struct rocker_ctrl *ctrl,
__be16 vlan_id)
{
@@ -3338,7 +3338,7 @@ static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port,
if (!rocker_port_is_bridged(rocker_port))
return 0;
- err = rocker_flow_tbl_bridge(rocker_port, trans, flags,
+ err = rocker_flow_tbl_bridge(rocker_port, trans_ph, flags,
ctrl->eth_dst, ctrl->eth_dst_mask,
vlan_id, tunnel_id,
goto_tbl, group_id, ctrl->copy_to_cpu);
@@ -3350,7 +3350,7 @@ static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port,
}
static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
const struct rocker_ctrl *ctrl, __be16 vlan_id)
{
u32 in_pport_mask = 0xffffffff;
@@ -3360,7 +3360,7 @@ static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port,
if (ntohs(vlan_id) == 0)
vlan_id = rocker_port->internal_vlan_id;
- err = rocker_flow_tbl_term_mac(rocker_port, trans,
+ err = rocker_flow_tbl_term_mac(rocker_port, trans_ph,
rocker_port->pport, in_pport_mask,
ctrl->eth_type, ctrl->eth_dst,
ctrl->eth_dst_mask, vlan_id,
@@ -3374,25 +3374,25 @@ static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port,
}
static int rocker_port_ctrl_vlan(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
const struct rocker_ctrl *ctrl, __be16 vlan_id)
{
if (ctrl->acl)
- return rocker_port_ctrl_vlan_acl(rocker_port, trans, flags,
+ return rocker_port_ctrl_vlan_acl(rocker_port, trans_ph, flags,
ctrl, vlan_id);
if (ctrl->bridge)
- return rocker_port_ctrl_vlan_bridge(rocker_port, trans, flags,
+ return rocker_port_ctrl_vlan_bridge(rocker_port, trans_ph, flags,
ctrl, vlan_id);
if (ctrl->term)
- return rocker_port_ctrl_vlan_term(rocker_port, trans, flags,
+ return rocker_port_ctrl_vlan_term(rocker_port, trans_ph, flags,
ctrl, vlan_id);
return -EOPNOTSUPP;
}
static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
__be16 vlan_id)
{
int err = 0;
@@ -3400,7 +3400,7 @@ static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port,
for (i = 0; i < ROCKER_CTRL_MAX; i++) {
if (rocker_port->ctrls[i]) {
- err = rocker_port_ctrl_vlan(rocker_port, trans, flags,
+ err = rocker_port_ctrl_vlan(rocker_port, trans_ph, flags,
&rocker_ctrls[i], vlan_id);
if (err)
return err;
@@ -3411,7 +3411,7 @@ static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port,
}
static int rocker_port_ctrl(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
const struct rocker_ctrl *ctrl)
{
u16 vid;
@@ -3420,7 +3420,7 @@ static int rocker_port_ctrl(struct rocker_port *rocker_port,
for (vid = 1; vid < VLAN_N_VID; vid++) {
if (!test_bit(vid, rocker_port->vlan_bitmap))
continue;
- err = rocker_port_ctrl_vlan(rocker_port, trans, flags,
+ err = rocker_port_ctrl_vlan(rocker_port, trans_ph, flags,
ctrl, htons(vid));
if (err)
break;
@@ -3430,7 +3430,7 @@ static int rocker_port_ctrl(struct rocker_port *rocker_port,
}
static int rocker_port_vlan(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags, u16 vid)
+ enum switchdev_trans_ph trans_ph, int flags, u16 vid)
{
enum rocker_of_dpa_table_id goto_tbl =
ROCKER_OF_DPA_TABLE_ID_TERMINATION_MAC;
@@ -3454,7 +3454,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port,
change_bit(ntohs(internal_vlan_id), rocker_port->vlan_bitmap);
if (adding) {
- err = rocker_port_ctrl_vlan_add(rocker_port, trans, flags,
+ err = rocker_port_ctrl_vlan_add(rocker_port, trans_ph, flags,
internal_vlan_id);
if (err) {
netdev_err(rocker_port->dev,
@@ -3463,7 +3463,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port,
}
}
- err = rocker_port_vlan_l2_groups(rocker_port, trans, flags,
+ err = rocker_port_vlan_l2_groups(rocker_port, trans_ph, flags,
internal_vlan_id, untagged);
if (err) {
netdev_err(rocker_port->dev,
@@ -3471,7 +3471,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port,
goto err_out;
}
- err = rocker_port_vlan_flood_group(rocker_port, trans, flags,
+ err = rocker_port_vlan_flood_group(rocker_port, trans_ph, flags,
internal_vlan_id);
if (err) {
netdev_err(rocker_port->dev,
@@ -3479,7 +3479,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port,
goto err_out;
}
- err = rocker_flow_tbl_vlan(rocker_port, trans, flags,
+ err = rocker_flow_tbl_vlan(rocker_port, trans_ph, flags,
in_pport, vlan_id, vlan_id_mask,
goto_tbl, untagged, internal_vlan_id);
if (err)
@@ -3487,14 +3487,14 @@ static int rocker_port_vlan(struct rocker_port *rocker_port,
"Error (%d) port VLAN table\n", err);
err_out:
- if (trans == SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph == SWITCHDEV_TRANS_PREPARE)
change_bit(ntohs(internal_vlan_id), rocker_port->vlan_bitmap);
return err;
}
static int rocker_port_ig_tbl(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags)
+ enum switchdev_trans_ph trans_ph, int flags)
{
enum rocker_of_dpa_table_id goto_tbl;
u32 in_pport;
@@ -3509,7 +3509,7 @@ static int rocker_port_ig_tbl(struct rocker_port *rocker_port,
in_pport_mask = 0xffff0000;
goto_tbl = ROCKER_OF_DPA_TABLE_ID_VLAN;
- err = rocker_flow_tbl_ig_port(rocker_port, trans, flags,
+ err = rocker_flow_tbl_ig_port(rocker_port, trans_ph, flags,
in_pport, in_pport_mask,
goto_tbl);
if (err)
@@ -3522,7 +3522,7 @@ static int rocker_port_ig_tbl(struct rocker_port *rocker_port,
struct rocker_fdb_learn_work {
struct work_struct work;
struct rocker_port *rocker_port;
- enum switchdev_trans trans;
+ enum switchdev_trans_ph trans_ph;
int flags;
u8 addr[ETH_ALEN];
u16 vid;
@@ -3546,11 +3546,11 @@ static void rocker_port_fdb_learn_work(struct work_struct *work)
call_switchdev_notifiers(SWITCHDEV_FDB_ADD,
lw->rocker_port->dev, &info.info);
- rocker_port_kfree(lw->trans, work);
+ rocker_port_kfree(lw->trans_ph, work);
}
static int rocker_port_fdb_learn(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
const u8 *addr, __be16 vlan_id)
{
struct rocker_fdb_learn_work *lw;
@@ -3567,7 +3567,7 @@ static int rocker_port_fdb_learn(struct rocker_port *rocker_port,
group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport);
if (!(flags & ROCKER_OP_FLAG_REFRESH)) {
- err = rocker_flow_tbl_bridge(rocker_port, trans, flags, addr,
+ err = rocker_flow_tbl_bridge(rocker_port, trans_ph, flags, addr,
NULL, vlan_id, tunnel_id, goto_tbl,
group_id, copy_to_cpu);
if (err)
@@ -3580,20 +3580,20 @@ static int rocker_port_fdb_learn(struct rocker_port *rocker_port,
if (!rocker_port_is_bridged(rocker_port))
return 0;
- lw = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*lw));
+ lw = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*lw));
if (!lw)
return -ENOMEM;
INIT_WORK(&lw->work, rocker_port_fdb_learn_work);
lw->rocker_port = rocker_port;
- lw->trans = trans;
+ lw->trans_ph = trans_ph;
lw->flags = flags;
ether_addr_copy(lw->addr, addr);
lw->vid = rocker_port_vlan_to_vid(rocker_port, vlan_id);
- if (trans == SWITCHDEV_TRANS_PREPARE)
- rocker_port_kfree(trans, lw);
+ if (trans_ph == SWITCHDEV_TRANS_PREPARE)
+ rocker_port_kfree(trans_ph, lw);
else
schedule_work(&lw->work);
@@ -3614,7 +3614,7 @@ rocker_fdb_tbl_find(const struct rocker *rocker,
}
static int rocker_port_fdb(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
const unsigned char *addr,
__be16 vlan_id, int flags)
{
@@ -3624,7 +3624,7 @@ static int rocker_port_fdb(struct rocker_port *rocker_port,
bool removing = (flags & ROCKER_OP_FLAG_REMOVE);
unsigned long lock_flags;
- fdb = rocker_port_kzalloc(rocker_port, trans, flags, sizeof(*fdb));
+ fdb = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*fdb));
if (!fdb)
return -ENOMEM;
@@ -3639,11 +3639,11 @@ static int rocker_port_fdb(struct rocker_port *rocker_port,
found = rocker_fdb_tbl_find(rocker, fdb);
if (removing && found) {
- rocker_port_kfree(trans, fdb);
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ rocker_port_kfree(trans_ph, fdb);
+ if (trans_ph != SWITCHDEV_TRANS_PREPARE)
hash_del(&found->entry);
} else if (!removing && !found) {
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph != SWITCHDEV_TRANS_PREPARE)
hash_add(rocker->fdb_tbl, &fdb->entry, fdb->key_crc32);
}
@@ -3651,18 +3651,18 @@ static int rocker_port_fdb(struct rocker_port *rocker_port,
/* Check if adding and already exists, or removing and can't find */
if (!found != !removing) {
- rocker_port_kfree(trans, fdb);
+ rocker_port_kfree(trans_ph, fdb);
if (!found && removing)
return 0;
/* Refreshing existing to update aging timers */
flags |= ROCKER_OP_FLAG_REFRESH;
}
- return rocker_port_fdb_learn(rocker_port, trans, flags, addr, vlan_id);
+ return rocker_port_fdb_learn(rocker_port, trans_ph, flags, addr, vlan_id);
}
static int rocker_port_fdb_flush(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags)
+ enum switchdev_trans_ph trans_ph, int flags)
{
struct rocker *rocker = rocker_port->rocker;
struct rocker_fdb_tbl_entry *found;
@@ -3684,12 +3684,12 @@ static int rocker_port_fdb_flush(struct rocker_port *rocker_port,
continue;
if (!found->learned)
continue;
- err = rocker_port_fdb_learn(rocker_port, trans, flags,
+ err = rocker_port_fdb_learn(rocker_port, trans_ph, flags,
found->key.addr,
found->key.vlan_id);
if (err)
goto err_out;
- if (trans != SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph != SWITCHDEV_TRANS_PREPARE)
hash_del(&found->entry);
}
@@ -3700,7 +3700,7 @@ err_out:
}
static int rocker_port_router_mac(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
__be16 vlan_id)
{
u32 in_pport_mask = 0xffffffff;
@@ -3714,7 +3714,7 @@ static int rocker_port_router_mac(struct rocker_port *rocker_port,
vlan_id = rocker_port->internal_vlan_id;
eth_type = htons(ETH_P_IP);
- err = rocker_flow_tbl_term_mac(rocker_port, trans,
+ err = rocker_flow_tbl_term_mac(rocker_port, trans_ph,
rocker_port->pport, in_pport_mask,
eth_type, rocker_port->dev->dev_addr,
dst_mac_mask, vlan_id, vlan_id_mask,
@@ -3723,7 +3723,7 @@ static int rocker_port_router_mac(struct rocker_port *rocker_port,
return err;
eth_type = htons(ETH_P_IPV6);
- err = rocker_flow_tbl_term_mac(rocker_port, trans,
+ err = rocker_flow_tbl_term_mac(rocker_port, trans_ph,
rocker_port->pport, in_pport_mask,
eth_type, rocker_port->dev->dev_addr,
dst_mac_mask, vlan_id, vlan_id_mask,
@@ -3733,7 +3733,7 @@ static int rocker_port_router_mac(struct rocker_port *rocker_port,
}
static int rocker_port_fwding(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags)
+ enum switchdev_trans_ph trans_ph, int flags)
{
bool pop_vlan;
u32 out_pport;
@@ -3758,7 +3758,7 @@ static int rocker_port_fwding(struct rocker_port *rocker_port,
continue;
vlan_id = htons(vid);
pop_vlan = rocker_vlan_id_is_internal(vlan_id);
- err = rocker_group_l2_interface(rocker_port, trans, flags,
+ err = rocker_group_l2_interface(rocker_port, trans_ph, flags,
vlan_id, out_pport, pop_vlan);
if (err) {
netdev_err(rocker_port->dev,
@@ -3772,7 +3772,7 @@ static int rocker_port_fwding(struct rocker_port *rocker_port,
}
static int rocker_port_stp_update(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags,
+ enum switchdev_trans_ph trans_ph, int flags,
u8 state)
{
bool want[ROCKER_CTRL_MAX] = { 0, };
@@ -3781,7 +3781,7 @@ static int rocker_port_stp_update(struct rocker_port *rocker_port,
int err;
int i;
- if (trans == SWITCHDEV_TRANS_PREPARE) {
+ if (trans_ph == SWITCHDEV_TRANS_PREPARE) {
memcpy(prev_ctrls, rocker_port->ctrls, sizeof(prev_ctrls));
prev_state = rocker_port->stp_state;
}
@@ -3818,7 +3818,7 @@ static int rocker_port_stp_update(struct rocker_port *rocker_port,
if (want[i] != rocker_port->ctrls[i]) {
int ctrl_flags = flags |
(want[i] ? 0 : ROCKER_OP_FLAG_REMOVE);
- err = rocker_port_ctrl(rocker_port, trans, ctrl_flags,
+ err = rocker_port_ctrl(rocker_port, trans_ph, ctrl_flags,
&rocker_ctrls[i]);
if (err)
goto err_out;
@@ -3826,14 +3826,14 @@ static int rocker_port_stp_update(struct rocker_port *rocker_port,
}
}
- err = rocker_port_fdb_flush(rocker_port, trans, flags);
+ err = rocker_port_fdb_flush(rocker_port, trans_ph, flags);
if (err)
goto err_out;
- err = rocker_port_fwding(rocker_port, trans, flags);
+ err = rocker_port_fwding(rocker_port, trans_ph, flags);
err_out:
- if (trans == SWITCHDEV_TRANS_PREPARE) {
+ if (trans_ph == SWITCHDEV_TRANS_PREPARE) {
memcpy(rocker_port->ctrls, prev_ctrls, sizeof(prev_ctrls));
rocker_port->stp_state = prev_state;
}
@@ -3842,26 +3842,26 @@ err_out:
}
static int rocker_port_fwd_enable(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags)
+ enum switchdev_trans_ph trans_ph, int flags)
{
if (rocker_port_is_bridged(rocker_port))
/* bridge STP will enable port */
return 0;
/* port is not bridged, so simulate going to FORWARDING state */
- return rocker_port_stp_update(rocker_port, trans, flags,
+ return rocker_port_stp_update(rocker_port, trans_ph, flags,
BR_STATE_FORWARDING);
}
static int rocker_port_fwd_disable(struct rocker_port *rocker_port,
- enum switchdev_trans trans, int flags)
+ enum switchdev_trans_ph trans_ph, int flags)
{
if (rocker_port_is_bridged(rocker_port))
/* bridge STP will disable port */
return 0;
/* port is not bridged, so simulate going to DISABLED state */
- return rocker_port_stp_update(rocker_port, trans, flags,
+ return rocker_port_stp_update(rocker_port, trans_ph, flags,
BR_STATE_DISABLED);
}
@@ -3952,7 +3952,7 @@ not_found:
}
static int rocker_port_fib_ipv4(struct rocker_port *rocker_port,
- enum switchdev_trans trans, __be32 dst,
+ enum switchdev_trans_ph trans_ph, __be32 dst,
int dst_len, const struct fib_info *fi,
u32 tb_id, int flags)
{
@@ -3976,7 +3976,7 @@ static int rocker_port_fib_ipv4(struct rocker_port *rocker_port,
has_gw = !!nh->nh_gw;
if (has_gw && nh_on_port) {
- err = rocker_port_ipv4_nh(rocker_port, trans, flags,
+ err = rocker_port_ipv4_nh(rocker_port, trans_ph, flags,
nh->nh_gw, &index);
if (err)
return err;
@@ -3987,7 +3987,7 @@ static int rocker_port_fib_ipv4(struct rocker_port *rocker_port,
group_id = ROCKER_GROUP_L2_INTERFACE(internal_vlan_id, 0);
}
- err = rocker_flow_tbl_ucast4_routing(rocker_port, trans, eth_type, dst,
+ err = rocker_flow_tbl_ucast4_routing(rocker_port, trans_ph, eth_type, dst,
dst_mask, priority, goto_tbl,
group_id, flags);
if (err)
@@ -4322,7 +4322,7 @@ static void rocker_port_trans_abort(const struct rocker_port *rocker_port)
}
static int rocker_port_brport_flags_set(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
unsigned long brport_flags)
{
unsigned long orig_flags;
@@ -4331,9 +4331,9 @@ static int rocker_port_brport_flags_set(struct rocker_port *rocker_port,
orig_flags = rocker_port->brport_flags;
rocker_port->brport_flags = brport_flags;
if ((orig_flags ^ rocker_port->brport_flags) & BR_LEARNING)
- err = rocker_port_set_learning(rocker_port, trans);
+ err = rocker_port_set_learning(rocker_port, trans_ph);
- if (trans == SWITCHDEV_TRANS_PREPARE)
+ if (trans_ph == SWITCHDEV_TRANS_PREPARE)
rocker_port->brport_flags = orig_flags;
return err;
@@ -4345,7 +4345,7 @@ static int rocker_port_attr_set(struct net_device *dev,
struct rocker_port *rocker_port = netdev_priv(dev);
int err = 0;
- switch (attr->trans) {
+ switch (attr->trans_ph) {
case SWITCHDEV_TRANS_PREPARE:
BUG_ON(!list_empty(&rocker_port->trans_mem));
break;
@@ -4358,12 +4358,12 @@ static int rocker_port_attr_set(struct net_device *dev,
switch (attr->id) {
case SWITCHDEV_ATTR_PORT_STP_STATE:
- err = rocker_port_stp_update(rocker_port, attr->trans,
+ err = rocker_port_stp_update(rocker_port, attr->trans_ph,
ROCKER_OP_FLAG_NOWAIT,
attr->u.stp_state);
break;
case SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS:
- err = rocker_port_brport_flags_set(rocker_port, attr->trans,
+ err = rocker_port_brport_flags_set(rocker_port, attr->trans_ph,
attr->u.brport_flags);
break;
default:
@@ -4375,33 +4375,33 @@ static int rocker_port_attr_set(struct net_device *dev,
}
static int rocker_port_vlan_add(struct rocker_port *rocker_port,
- enum switchdev_trans trans, u16 vid, u16 flags)
+ enum switchdev_trans_ph trans_ph, u16 vid, u16 flags)
{
int err;
/* XXX deal with flags for PVID and untagged */
- err = rocker_port_vlan(rocker_port, trans, 0, vid);
+ err = rocker_port_vlan(rocker_port, trans_ph, 0, vid);
if (err)
return err;
- err = rocker_port_router_mac(rocker_port, trans, 0, htons(vid));
+ err = rocker_port_router_mac(rocker_port, trans_ph, 0, htons(vid));
if (err)
- rocker_port_vlan(rocker_port, trans,
+ rocker_port_vlan(rocker_port, trans_ph,
ROCKER_OP_FLAG_REMOVE, vid);
return err;
}
static int rocker_port_vlans_add(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
const struct switchdev_obj_vlan *vlan)
{
u16 vid;
int err;
for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
- err = rocker_port_vlan_add(rocker_port, trans,
+ err = rocker_port_vlan_add(rocker_port, trans_ph,
vid, vlan->flags);
if (err)
return err;
@@ -4411,7 +4411,7 @@ static int rocker_port_vlans_add(struct rocker_port *rocker_port,
}
static int rocker_port_fdb_add(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
const struct switchdev_obj_fdb *fdb)
{
__be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL);
@@ -4420,7 +4420,7 @@ static int rocker_port_fdb_add(struct rocker_port *rocker_port,
if (!rocker_port_is_bridged(rocker_port))
return -EINVAL;
- return rocker_port_fdb(rocker_port, trans, fdb->addr, vlan_id, flags);
+ return rocker_port_fdb(rocker_port, trans_ph, fdb->addr, vlan_id, flags);
}
static int rocker_port_obj_add(struct net_device *dev,
@@ -4430,7 +4430,7 @@ static int rocker_port_obj_add(struct net_device *dev,
const struct switchdev_obj_ipv4_fib *fib4;
int err = 0;
- switch (obj->trans) {
+ switch (obj->trans_ph) {
case SWITCHDEV_TRANS_PREPARE:
BUG_ON(!list_empty(&rocker_port->trans_mem));
break;
@@ -4443,17 +4443,17 @@ static int rocker_port_obj_add(struct net_device *dev,
switch (obj->id) {
case SWITCHDEV_OBJ_PORT_VLAN:
- err = rocker_port_vlans_add(rocker_port, obj->trans,
+ err = rocker_port_vlans_add(rocker_port, obj->trans_ph,
&obj->u.vlan);
break;
case SWITCHDEV_OBJ_IPV4_FIB:
fib4 = &obj->u.ipv4_fib;
- err = rocker_port_fib_ipv4(rocker_port, obj->trans,
+ err = rocker_port_fib_ipv4(rocker_port, obj->trans_ph,
htonl(fib4->dst), fib4->dst_len,
fib4->fi, fib4->tb_id, 0);
break;
case SWITCHDEV_OBJ_PORT_FDB:
- err = rocker_port_fdb_add(rocker_port, obj->trans, &obj->u.fdb);
+ err = rocker_port_fdb_add(rocker_port, obj->trans_ph, &obj->u.fdb);
break;
default:
err = -EOPNOTSUPP;
@@ -4493,7 +4493,7 @@ static int rocker_port_vlans_del(struct rocker_port *rocker_port,
}
static int rocker_port_fdb_del(struct rocker_port *rocker_port,
- enum switchdev_trans trans,
+ enum switchdev_trans_ph trans_ph,
const struct switchdev_obj_fdb *fdb)
{
__be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL);
@@ -4502,7 +4502,7 @@ static int rocker_port_fdb_del(struct rocker_port *rocker_port,
if (!rocker_port_is_bridged(rocker_port))
return -EINVAL;
- return rocker_port_fdb(rocker_port, trans, fdb->addr, vlan_id, flags);
+ return rocker_port_fdb(rocker_port, trans_ph, fdb->addr, vlan_id, flags);
}
static int rocker_port_obj_del(struct net_device *dev,
@@ -4524,7 +4524,7 @@ static int rocker_port_obj_del(struct net_device *dev,
ROCKER_OP_FLAG_REMOVE);
break;
case SWITCHDEV_OBJ_PORT_FDB:
- err = rocker_port_fdb_del(rocker_port, obj->trans, &obj->u.fdb);
+ err = rocker_port_fdb_del(rocker_port, obj->trans_ph, &obj->u.fdb);
break;
default:
err = -EOPNOTSUPP;
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 319baab..494f510 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -16,7 +16,7 @@
#define SWITCHDEV_F_NO_RECURSE BIT(0)
-enum switchdev_trans {
+enum switchdev_trans_ph {
SWITCHDEV_TRANS_NONE,
SWITCHDEV_TRANS_PREPARE,
SWITCHDEV_TRANS_ABORT,
@@ -32,7 +32,7 @@ enum switchdev_attr_id {
struct switchdev_attr {
enum switchdev_attr_id id;
- enum switchdev_trans trans;
+ enum switchdev_trans_ph trans_ph;
u32 flags;
union {
struct netdev_phys_item_id ppid; /* PORT_PARENT_ID */
@@ -52,7 +52,7 @@ enum switchdev_obj_id {
struct switchdev_obj {
enum switchdev_obj_id id;
- enum switchdev_trans trans;
+ enum switchdev_trans_ph trans_ph;
int (*cb)(struct net_device *dev, struct switchdev_obj *obj);
union {
struct switchdev_obj_vlan { /* PORT_VLAN */
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index cce9738..7f50b74 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -250,7 +250,7 @@ static int dsa_slave_port_vlan_add(struct net_device *dev,
u16 vid;
int err;
- switch (obj->trans) {
+ switch (obj->trans_ph) {
case SWITCHDEV_TRANS_PREPARE:
if (!ds->drv->port_vlan_add || !ds->drv->port_pvid_set)
return -EOPNOTSUPP;
@@ -354,9 +354,9 @@ static int dsa_slave_port_fdb_add(struct net_device *dev,
struct dsa_switch *ds = p->parent;
int ret = -EOPNOTSUPP;
- if (obj->trans == SWITCHDEV_TRANS_PREPARE)
+ if (obj->trans_ph == SWITCHDEV_TRANS_PREPARE)
ret = ds->drv->port_fdb_add ? 0 : -EOPNOTSUPP;
- else if (obj->trans == SWITCHDEV_TRANS_COMMIT)
+ else if (obj->trans_ph == SWITCHDEV_TRANS_COMMIT)
ret = ds->drv->port_fdb_add(ds, p->port, fdb->addr, fdb->vid);
return ret;
@@ -462,7 +462,7 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
switch (attr->id) {
case SWITCHDEV_ATTR_PORT_STP_STATE:
- if (attr->trans == SWITCHDEV_TRANS_COMMIT)
+ if (attr->trans_ph == SWITCHDEV_TRANS_COMMIT)
ret = dsa_slave_stp_update(dev, attr->u.stp_state);
break;
default:
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index fda38f8..df5a544 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);
--
1.9.3
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [patch net-next RFC 2/6] switchdev: introduce transaction infrastructure for attr_set and obj_add
2015-09-19 12:29 [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 1/6] switchdev: rename "trans" to "trans_ph" Jiri Pirko
@ 2015-09-19 12:29 ` Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 3/6] rocker: switch to local transaction phase enum Jiri Pirko
` (6 subsequent siblings)
8 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2015-09-19 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, idosch, eladr, sfeldma, f.fainelli, linux, vivien.didelot
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. Commit/abort item destruction
is handled as well.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
drivers/net/ethernet/rocker/rocker.c | 6 ++-
include/net/switchdev.h | 24 ++++++++--
net/dsa/slave.c | 6 ++-
net/switchdev/switchdev.c | 87 ++++++++++++++++++++++++++++++------
4 files changed, 103 insertions(+), 20 deletions(-)
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index b5f2ff8..92e1520 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -4340,7 +4340,8 @@ static int rocker_port_brport_flags_set(struct rocker_port *rocker_port,
}
static int rocker_port_attr_set(struct net_device *dev,
- struct switchdev_attr *attr)
+ struct switchdev_attr *attr,
+ struct switchdev_trans *trans)
{
struct rocker_port *rocker_port = netdev_priv(dev);
int err = 0;
@@ -4424,7 +4425,8 @@ static int rocker_port_fdb_add(struct rocker_port *rocker_port,
}
static int rocker_port_obj_add(struct net_device *dev,
- struct switchdev_obj *obj)
+ struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
{
struct rocker_port *rocker_port = netdev_priv(dev);
const struct switchdev_obj_ipv4_fib *fib4;
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 494f510..1e394f1 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -1,6 +1,6 @@
/*
* include/net/switchdev.h - Switch device API
- * Copyright (c) 2014 Jiri Pirko <jiri@resnulli.us>
+ * Copyright (c) 2014-2015 Jiri Pirko <jiri@resnulli.us>
* Copyright (c) 2014-2015 Scott Feldman <sfeldma@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -13,6 +13,7 @@
#include <linux/netdevice.h>
#include <linux/notifier.h>
+#include <linux/list.h>
#define SWITCHDEV_F_NO_RECURSE BIT(0)
@@ -23,6 +24,16 @@ enum switchdev_trans_ph {
SWITCHDEV_TRANS_COMMIT,
};
+struct switchdev_trans_item {
+ struct list_head list;
+ void *data;
+ void (*destructor)(const void *data);
+};
+
+struct switchdev_trans {
+ struct list_head item_list;
+};
+
enum switchdev_attr_id {
SWITCHDEV_ATTR_UNDEFINED,
SWITCHDEV_ATTR_PORT_PARENT_ID,
@@ -77,6 +88,11 @@ struct switchdev_obj {
} u;
};
+void switchdev_trans_item_enqueue(struct switchdev_trans *trans,
+ void *data, void (*destructor)(void const *),
+ struct switchdev_trans_item *tritem);
+void *switchdev_trans_item_dequeue(struct switchdev_trans *trans);
+
/**
* struct switchdev_ops - switchdev operations
*
@@ -94,9 +110,11 @@ struct switchdev_ops {
int (*switchdev_port_attr_get)(struct net_device *dev,
struct switchdev_attr *attr);
int (*switchdev_port_attr_set)(struct net_device *dev,
- struct switchdev_attr *attr);
+ struct switchdev_attr *attr,
+ struct switchdev_trans *trans);
int (*switchdev_port_obj_add)(struct net_device *dev,
- struct switchdev_obj *obj);
+ struct switchdev_obj *obj,
+ struct switchdev_trans *trans);
int (*switchdev_port_obj_del)(struct net_device *dev,
struct switchdev_obj *obj);
int (*switchdev_port_obj_dump)(struct net_device *dev,
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 7f50b74..ac76fd1 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -456,7 +456,8 @@ static int dsa_slave_stp_update(struct net_device *dev, u8 state)
}
static int dsa_slave_port_attr_set(struct net_device *dev,
- struct switchdev_attr *attr)
+ struct switchdev_attr *attr,
+ struct switchdev_trans *trans)
{
int ret = 0;
@@ -474,7 +475,8 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
}
static int dsa_slave_port_obj_add(struct net_device *dev,
- struct switchdev_obj *obj)
+ struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
{
int err;
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index df5a544..a3647bf 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 <jiri@resnulli.us>
+ * Copyright (c) 2014-2015 Jiri Pirko <jiri@resnulli.us>
* Copyright (c) 2014-2015 Scott Feldman <sfeldma@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -16,9 +16,58 @@
#include <linux/notifier.h>
#include <linux/netdevice.h>
#include <linux/if_bridge.h>
+#include <linux/list.h>
#include <net/ip_fib.h>
#include <net/switchdev.h>
+void switchdev_trans_item_enqueue(struct switchdev_trans *trans,
+ void *data, void (*destructor)(void const *),
+ struct switchdev_trans_item *tritem)
+{
+ if (!trans)
+ return;
+ 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;
+}
+
+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);
+
+void switchdev_trans_init(struct switchdev_trans *trans)
+{
+ INIT_LIST_HEAD(&trans->item_list);
+}
+
+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);
+}
+
/**
* switchdev_port_attr_get - Get port attribute
*
@@ -62,7 +111,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 +120,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 +131,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 +194,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 +207,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 +217,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 +226,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 +239,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_destroy(&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 +258,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 +266,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 +288,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 +303,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 +312,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 +325,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_destroy(&trans);
return err;
}
--
1.9.3
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [patch net-next RFC 3/6] rocker: switch to local transaction phase enum
2015-09-19 12:29 [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 1/6] switchdev: rename "trans" to "trans_ph" Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 2/6] switchdev: introduce transaction infrastructure for attr_set and obj_add Jiri Pirko
@ 2015-09-19 12:29 ` Jiri Pirko
2015-09-19 19:25 ` Vivien Didelot
2015-09-19 12:29 ` [patch net-next RFC 4/6] switchdev: move transaction phase enum under transaction structure Jiri Pirko
` (5 subsequent siblings)
8 siblings, 1 reply; 23+ messages in thread
From: Jiri Pirko @ 2015-09-19 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, idosch, eladr, sfeldma, f.fainelli, linux, vivien.didelot
Since switchdev_trans_ph anum is going to be removed, and rocker code is
way too complicated in this matter to be converted, just introduce local
enum for transaction phase. Pass it around in local transaction
structure.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
drivers/net/ethernet/rocker/rocker.c | 469 ++++++++++++++++++-----------------
1 file changed, 245 insertions(+), 224 deletions(-)
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index 92e1520..de1a367 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -339,8 +339,19 @@ static bool rocker_port_is_ovsed(const struct rocker_port *rocker_port)
#define ROCKER_OP_FLAG_LEARNED BIT(2)
#define ROCKER_OP_FLAG_REFRESH BIT(3)
+enum rocker_trans_ph {
+ ROCKER_TRANS_PH_NONE,
+ ROCKER_TRANS_PH_PREPARE,
+ ROCKER_TRANS_PH_ABORT,
+ ROCKER_TRANS_PH_COMMIT,
+};
+
+struct rocker_trans {
+ enum rocker_trans_ph ph;
+};
+
static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
size_t size)
{
struct list_head *elem = NULL;
@@ -356,19 +367,19 @@ static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port,
* memory used in the commit phase.
*/
- switch (trans_ph) {
- case SWITCHDEV_TRANS_PREPARE:
+ switch (rtrans->ph) {
+ case ROCKER_TRANS_PH_PREPARE:
elem = kzalloc(size + sizeof(*elem), gfp_flags);
if (!elem)
return NULL;
list_add_tail(elem, &rocker_port->trans_mem);
break;
- case SWITCHDEV_TRANS_COMMIT:
+ case ROCKER_TRANS_PH_COMMIT:
BUG_ON(list_empty(&rocker_port->trans_mem));
elem = rocker_port->trans_mem.next;
list_del_init(elem);
break;
- case SWITCHDEV_TRANS_NONE:
+ case ROCKER_TRANS_PH_NONE:
elem = kzalloc(size + sizeof(*elem), gfp_flags);
if (elem)
INIT_LIST_HEAD(elem);
@@ -381,20 +392,20 @@ static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port,
}
static void *rocker_port_kzalloc(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
size_t size)
{
- return __rocker_port_mem_alloc(rocker_port, trans_ph, flags, size);
+ return __rocker_port_mem_alloc(rocker_port, rtrans, flags, size);
}
static void *rocker_port_kcalloc(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
size_t n, size_t size)
{
- return __rocker_port_mem_alloc(rocker_port, trans_ph, flags, n * size);
+ return __rocker_port_mem_alloc(rocker_port, rtrans, flags, n * size);
}
-static void rocker_port_kfree(enum switchdev_trans_ph trans_ph, const void *mem)
+static void rocker_port_kfree(struct rocker_trans *rtrans, const void *mem)
{
struct list_head *elem;
@@ -403,7 +414,7 @@ static void rocker_port_kfree(enum switchdev_trans_ph trans_ph, const void *mem)
* commit phase.
*/
- if (trans_ph == SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph == ROCKER_TRANS_PH_PREPARE)
return;
elem = (struct list_head *)mem - 1;
@@ -430,22 +441,22 @@ static void rocker_wait_init(struct rocker_wait *wait)
}
static struct rocker_wait *rocker_wait_create(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
int flags)
{
struct rocker_wait *wait;
- wait = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*wait));
+ wait = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*wait));
if (!wait)
return NULL;
rocker_wait_init(wait);
return wait;
}
-static void rocker_wait_destroy(enum switchdev_trans_ph trans_ph,
+static void rocker_wait_destroy(struct rocker_trans *rtrans,
struct rocker_wait *wait)
{
- rocker_port_kfree(trans_ph, wait);
+ rocker_port_kfree(rtrans, wait);
}
static bool rocker_wait_event_timeout(struct rocker_wait *wait,
@@ -1408,7 +1419,7 @@ static irqreturn_t rocker_cmd_irq_handler(int irq, void *dev_id)
wait = rocker_desc_cookie_ptr_get(desc_info);
if (wait->nowait) {
rocker_desc_gen_clear(desc_info);
- rocker_wait_destroy(SWITCHDEV_TRANS_NONE, wait);
+ rocker_wait_destroy(ROCKER_TRANS_PH_NONE, wait);
} else {
rocker_wait_wake_up(wait);
}
@@ -1463,7 +1474,7 @@ static int rocker_event_link_change(const struct rocker *rocker,
}
static int rocker_port_fdb(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
const unsigned char *addr,
__be16 vlan_id, int flags);
@@ -1496,7 +1507,7 @@ static int rocker_event_mac_vlan_seen(const struct rocker *rocker,
rocker_port->stp_state != BR_STATE_FORWARDING)
return 0;
- return rocker_port_fdb(rocker_port, SWITCHDEV_TRANS_NONE,
+ return rocker_port_fdb(rocker_port, ROCKER_TRANS_PH_NONE,
addr, vlan_id, flags);
}
@@ -1582,7 +1593,7 @@ typedef int (*rocker_cmd_proc_cb_t)(const struct rocker_port *rocker_port,
void *priv);
static int rocker_cmd_exec(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
rocker_cmd_prep_cb_t prepare, void *prepare_priv,
rocker_cmd_proc_cb_t process, void *process_priv)
{
@@ -1593,7 +1604,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port,
unsigned long lock_flags;
int err;
- wait = rocker_wait_create(rocker_port, trans_ph, flags);
+ wait = rocker_wait_create(rocker_port, rtrans, flags);
if (!wait)
return -ENOMEM;
wait->nowait = nowait;
@@ -1615,7 +1626,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port,
rocker_desc_cookie_ptr_set(desc_info, wait);
- if (trans_ph != SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph != ROCKER_TRANS_PH_PREPARE)
rocker_desc_head_set(rocker, &rocker->cmd_ring, desc_info);
spin_unlock_irqrestore(&rocker->cmd_ring_lock, lock_flags);
@@ -1623,7 +1634,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port,
if (nowait)
return 0;
- if (trans_ph != SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph != ROCKER_TRANS_PH_PREPARE)
if (!rocker_wait_event_timeout(wait, HZ / 10))
return -EIO;
@@ -1636,7 +1647,7 @@ static int rocker_cmd_exec(struct rocker_port *rocker_port,
rocker_desc_gen_clear(desc_info);
out:
- rocker_wait_destroy(trans_ph, wait);
+ rocker_wait_destroy(rtrans, wait);
return err;
}
@@ -1875,7 +1886,7 @@ rocker_cmd_set_port_learning_prep(const struct rocker_port *rocker_port,
static int rocker_cmd_get_port_settings_ethtool(struct rocker_port *rocker_port,
struct ethtool_cmd *ecmd)
{
- return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ return rocker_cmd_exec(rocker_port, ROCKER_TRANS_PH_NONE, 0,
rocker_cmd_get_port_settings_prep, NULL,
rocker_cmd_get_port_settings_ethtool_proc,
ecmd);
@@ -1884,7 +1895,7 @@ static int rocker_cmd_get_port_settings_ethtool(struct rocker_port *rocker_port,
static int rocker_cmd_get_port_settings_macaddr(struct rocker_port *rocker_port,
unsigned char *macaddr)
{
- return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ return rocker_cmd_exec(rocker_port, ROCKER_TRANS_PH_NONE, 0,
rocker_cmd_get_port_settings_prep, NULL,
rocker_cmd_get_port_settings_macaddr_proc,
macaddr);
@@ -1893,7 +1904,7 @@ static int rocker_cmd_get_port_settings_macaddr(struct rocker_port *rocker_port,
static int rocker_cmd_set_port_settings_ethtool(struct rocker_port *rocker_port,
struct ethtool_cmd *ecmd)
{
- return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ return rocker_cmd_exec(rocker_port, ROCKER_TRANS_PH_NONE, 0,
rocker_cmd_set_port_settings_ethtool_prep,
ecmd, NULL, NULL);
}
@@ -1901,7 +1912,7 @@ static int rocker_cmd_set_port_settings_ethtool(struct rocker_port *rocker_port,
static int rocker_cmd_set_port_settings_macaddr(struct rocker_port *rocker_port,
unsigned char *macaddr)
{
- return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ return rocker_cmd_exec(rocker_port, ROCKER_TRANS_PH_NONE, 0,
rocker_cmd_set_port_settings_macaddr_prep,
macaddr, NULL, NULL);
}
@@ -1909,15 +1920,15 @@ static int rocker_cmd_set_port_settings_macaddr(struct rocker_port *rocker_port,
static int rocker_cmd_set_port_settings_mtu(struct rocker_port *rocker_port,
int mtu)
{
- return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ return rocker_cmd_exec(rocker_port, ROCKER_TRANS_PH_NONE, 0,
rocker_cmd_set_port_settings_mtu_prep,
&mtu, NULL, NULL);
}
static int rocker_port_set_learning(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph)
+ struct rocker_trans *rtrans)
{
- return rocker_cmd_exec(rocker_port, trans_ph, 0,
+ return rocker_cmd_exec(rocker_port, rtrans, 0,
rocker_cmd_set_port_learning_prep,
NULL, NULL, NULL);
}
@@ -2433,7 +2444,7 @@ rocker_flow_tbl_find(const struct rocker *rocker,
}
static int rocker_flow_tbl_add(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
struct rocker_flow_tbl_entry *match)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2449,9 +2460,9 @@ static int rocker_flow_tbl_add(struct rocker_port *rocker_port,
if (found) {
match->cookie = found->cookie;
- if (trans_ph != SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph != ROCKER_TRANS_PH_PREPARE)
hash_del(&found->entry);
- rocker_port_kfree(trans_ph, found);
+ rocker_port_kfree(rtrans, found);
found = match;
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_MOD;
} else {
@@ -2460,17 +2471,17 @@ static int rocker_flow_tbl_add(struct rocker_port *rocker_port,
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_ADD;
}
- if (trans_ph != SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph != ROCKER_TRANS_PH_PREPARE)
hash_add(rocker->flow_tbl, &found->entry, found->key_crc32);
spin_unlock_irqrestore(&rocker->flow_tbl_lock, lock_flags);
- return rocker_cmd_exec(rocker_port, trans_ph, flags,
+ return rocker_cmd_exec(rocker_port, rtrans, flags,
rocker_cmd_flow_tbl_add, found, NULL, NULL);
}
static int rocker_flow_tbl_del(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
struct rocker_flow_tbl_entry *match)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2486,43 +2497,43 @@ static int rocker_flow_tbl_del(struct rocker_port *rocker_port,
found = rocker_flow_tbl_find(rocker, match);
if (found) {
- if (trans_ph != SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph != ROCKER_TRANS_PH_PREPARE)
hash_del(&found->entry);
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_FLOW_DEL;
}
spin_unlock_irqrestore(&rocker->flow_tbl_lock, lock_flags);
- rocker_port_kfree(trans_ph, match);
+ rocker_port_kfree(rtrans, match);
if (found) {
- err = rocker_cmd_exec(rocker_port, trans_ph, flags,
+ err = rocker_cmd_exec(rocker_port, rtrans, flags,
rocker_cmd_flow_tbl_del,
found, NULL, NULL);
- rocker_port_kfree(trans_ph, found);
+ rocker_port_kfree(rtrans, found);
}
return err;
}
static int rocker_flow_tbl_do(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
struct rocker_flow_tbl_entry *entry)
{
if (flags & ROCKER_OP_FLAG_REMOVE)
- return rocker_flow_tbl_del(rocker_port, trans_ph, flags, entry);
+ return rocker_flow_tbl_del(rocker_port, rtrans, flags, entry);
else
- return rocker_flow_tbl_add(rocker_port, trans_ph, flags, entry);
+ return rocker_flow_tbl_add(rocker_port, rtrans, flags, entry);
}
static int rocker_flow_tbl_ig_port(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
u32 in_pport, u32 in_pport_mask,
enum rocker_of_dpa_table_id goto_tbl)
{
struct rocker_flow_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2532,11 +2543,11 @@ static int rocker_flow_tbl_ig_port(struct rocker_port *rocker_port,
entry->key.ig_port.in_pport_mask = in_pport_mask;
entry->key.ig_port.goto_tbl = goto_tbl;
- return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry);
+ return rocker_flow_tbl_do(rocker_port, rtrans, flags, entry);
}
static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
u32 in_pport, __be16 vlan_id,
__be16 vlan_id_mask,
enum rocker_of_dpa_table_id goto_tbl,
@@ -2544,7 +2555,7 @@ static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port,
{
struct rocker_flow_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2558,11 +2569,11 @@ static int rocker_flow_tbl_vlan(struct rocker_port *rocker_port,
entry->key.vlan.untagged = untagged;
entry->key.vlan.new_vlan_id = new_vlan_id;
- return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry);
+ return rocker_flow_tbl_do(rocker_port, rtrans, flags, entry);
}
static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
u32 in_pport, u32 in_pport_mask,
__be16 eth_type, const u8 *eth_dst,
const u8 *eth_dst_mask, __be16 vlan_id,
@@ -2571,7 +2582,7 @@ static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port,
{
struct rocker_flow_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2595,11 +2606,11 @@ static int rocker_flow_tbl_term_mac(struct rocker_port *rocker_port,
entry->key.term_mac.vlan_id_mask = vlan_id_mask;
entry->key.term_mac.copy_to_cpu = copy_to_cpu;
- return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry);
+ return rocker_flow_tbl_do(rocker_port, rtrans, flags, entry);
}
static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
const u8 *eth_dst, const u8 *eth_dst_mask,
__be16 vlan_id, u32 tunnel_id,
enum rocker_of_dpa_table_id goto_tbl,
@@ -2611,7 +2622,7 @@ static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port,
bool dflt = !eth_dst || (eth_dst && eth_dst_mask);
bool wild = false;
- entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2649,11 +2660,11 @@ static int rocker_flow_tbl_bridge(struct rocker_port *rocker_port,
entry->key.bridge.group_id = group_id;
entry->key.bridge.copy_to_cpu = copy_to_cpu;
- return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry);
+ return rocker_flow_tbl_do(rocker_port, rtrans, flags, entry);
}
static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
__be16 eth_type, __be32 dst,
__be32 dst_mask, u32 priority,
enum rocker_of_dpa_table_id goto_tbl,
@@ -2661,7 +2672,7 @@ static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port,
{
struct rocker_flow_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2675,11 +2686,11 @@ static int rocker_flow_tbl_ucast4_routing(struct rocker_port *rocker_port,
entry->key_len = offsetof(struct rocker_flow_tbl_key,
ucast_routing.group_id);
- return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry);
+ return rocker_flow_tbl_do(rocker_port, rtrans, flags, entry);
}
static int rocker_flow_tbl_acl(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
u32 in_pport, u32 in_pport_mask,
const u8 *eth_src, const u8 *eth_src_mask,
const u8 *eth_dst, const u8 *eth_dst_mask,
@@ -2691,7 +2702,7 @@ static int rocker_flow_tbl_acl(struct rocker_port *rocker_port,
u32 priority;
struct rocker_flow_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2726,7 +2737,7 @@ static int rocker_flow_tbl_acl(struct rocker_port *rocker_port,
entry->key.acl.ip_tos_mask = ip_tos_mask;
entry->key.acl.group_id = group_id;
- return rocker_flow_tbl_do(rocker_port, trans_ph, flags, entry);
+ return rocker_flow_tbl_do(rocker_port, rtrans, flags, entry);
}
static struct rocker_group_tbl_entry *
@@ -2744,22 +2755,22 @@ rocker_group_tbl_find(const struct rocker *rocker,
return NULL;
}
-static void rocker_group_tbl_entry_free(enum switchdev_trans_ph trans_ph,
+static void rocker_group_tbl_entry_free(struct rocker_trans *rtrans,
struct rocker_group_tbl_entry *entry)
{
switch (ROCKER_GROUP_TYPE_GET(entry->group_id)) {
case ROCKER_OF_DPA_GROUP_TYPE_L2_FLOOD:
case ROCKER_OF_DPA_GROUP_TYPE_L2_MCAST:
- rocker_port_kfree(trans_ph, entry->group_ids);
+ rocker_port_kfree(rtrans, entry->group_ids);
break;
default:
break;
}
- rocker_port_kfree(trans_ph, entry);
+ rocker_port_kfree(rtrans, entry);
}
static int rocker_group_tbl_add(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
struct rocker_group_tbl_entry *match)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2771,9 +2782,9 @@ static int rocker_group_tbl_add(struct rocker_port *rocker_port,
found = rocker_group_tbl_find(rocker, match);
if (found) {
- if (trans_ph != SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph != ROCKER_TRANS_PH_PREPARE)
hash_del(&found->entry);
- rocker_group_tbl_entry_free(trans_ph, found);
+ rocker_group_tbl_entry_free(rtrans, found);
found = match;
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_MOD;
} else {
@@ -2781,17 +2792,17 @@ static int rocker_group_tbl_add(struct rocker_port *rocker_port,
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_ADD;
}
- if (trans_ph != SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph != ROCKER_TRANS_PH_PREPARE)
hash_add(rocker->group_tbl, &found->entry, found->group_id);
spin_unlock_irqrestore(&rocker->group_tbl_lock, lock_flags);
- return rocker_cmd_exec(rocker_port, trans_ph, flags,
+ return rocker_cmd_exec(rocker_port, rtrans, flags,
rocker_cmd_group_tbl_add, found, NULL, NULL);
}
static int rocker_group_tbl_del(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
struct rocker_group_tbl_entry *match)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2804,95 +2815,95 @@ static int rocker_group_tbl_del(struct rocker_port *rocker_port,
found = rocker_group_tbl_find(rocker, match);
if (found) {
- if (trans_ph != SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph != ROCKER_TRANS_PH_PREPARE)
hash_del(&found->entry);
found->cmd = ROCKER_TLV_CMD_TYPE_OF_DPA_GROUP_DEL;
}
spin_unlock_irqrestore(&rocker->group_tbl_lock, lock_flags);
- rocker_group_tbl_entry_free(trans_ph, match);
+ rocker_group_tbl_entry_free(rtrans, match);
if (found) {
- err = rocker_cmd_exec(rocker_port, trans_ph, flags,
+ err = rocker_cmd_exec(rocker_port, rtrans, flags,
rocker_cmd_group_tbl_del,
found, NULL, NULL);
- rocker_group_tbl_entry_free(trans_ph, found);
+ rocker_group_tbl_entry_free(rtrans, found);
}
return err;
}
static int rocker_group_tbl_do(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
struct rocker_group_tbl_entry *entry)
{
if (flags & ROCKER_OP_FLAG_REMOVE)
- return rocker_group_tbl_del(rocker_port, trans_ph, flags, entry);
+ return rocker_group_tbl_del(rocker_port, rtrans, flags, entry);
else
- return rocker_group_tbl_add(rocker_port, trans_ph, flags, entry);
+ return rocker_group_tbl_add(rocker_port, rtrans, flags, entry);
}
static int rocker_group_l2_interface(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
__be16 vlan_id, u32 out_pport,
int pop_vlan)
{
struct rocker_group_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
entry->group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport);
entry->l2_interface.pop_vlan = pop_vlan;
- return rocker_group_tbl_do(rocker_port, trans_ph, flags, entry);
+ return rocker_group_tbl_do(rocker_port, rtrans, flags, entry);
}
static int rocker_group_l2_fan_out(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
int flags, u8 group_count,
const u32 *group_ids, u32 group_id)
{
struct rocker_group_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
entry->group_id = group_id;
entry->group_count = group_count;
- entry->group_ids = rocker_port_kcalloc(rocker_port, trans_ph, flags,
+ entry->group_ids = rocker_port_kcalloc(rocker_port, rtrans, flags,
group_count, sizeof(u32));
if (!entry->group_ids) {
- rocker_port_kfree(trans_ph, entry);
+ rocker_port_kfree(rtrans, entry);
return -ENOMEM;
}
memcpy(entry->group_ids, group_ids, group_count * sizeof(u32));
- return rocker_group_tbl_do(rocker_port, trans_ph, flags, entry);
+ return rocker_group_tbl_do(rocker_port, rtrans, flags, entry);
}
static int rocker_group_l2_flood(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
__be16 vlan_id, u8 group_count,
const u32 *group_ids, u32 group_id)
{
- return rocker_group_l2_fan_out(rocker_port, trans_ph, flags,
+ return rocker_group_l2_fan_out(rocker_port, rtrans, flags,
group_count, group_ids,
group_id);
}
static int rocker_group_l3_unicast(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
u32 index, const u8 *src_mac, const u8 *dst_mac,
__be16 vlan_id, bool ttl_check, u32 pport)
{
struct rocker_group_tbl_entry *entry;
- entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2905,7 +2916,7 @@ static int rocker_group_l3_unicast(struct rocker_port *rocker_port,
entry->l3_unicast.ttl_check = ttl_check;
entry->l3_unicast.group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, pport);
- return rocker_group_tbl_do(rocker_port, trans_ph, flags, entry);
+ return rocker_group_tbl_do(rocker_port, rtrans, flags, entry);
}
static struct rocker_neigh_tbl_entry *
@@ -2922,43 +2933,43 @@ rocker_neigh_tbl_find(const struct rocker *rocker, __be32 ip_addr)
}
static void _rocker_neigh_add(struct rocker *rocker,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
struct rocker_neigh_tbl_entry *entry)
{
- if (trans_ph != SWITCHDEV_TRANS_COMMIT)
+ if (rtrans->ph != ROCKER_TRANS_PH_COMMIT)
entry->index = rocker->neigh_tbl_next_index++;
- if (trans_ph == SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph == ROCKER_TRANS_PH_PREPARE)
return;
entry->ref_count++;
hash_add(rocker->neigh_tbl, &entry->entry,
be32_to_cpu(entry->ip_addr));
}
-static void _rocker_neigh_del(enum switchdev_trans_ph trans_ph,
+static void _rocker_neigh_del(struct rocker_trans *rtrans,
struct rocker_neigh_tbl_entry *entry)
{
- if (trans_ph == SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph == ROCKER_TRANS_PH_PREPARE)
return;
if (--entry->ref_count == 0) {
hash_del(&entry->entry);
- rocker_port_kfree(trans_ph, entry);
+ rocker_port_kfree(rtrans, entry);
}
}
static void _rocker_neigh_update(struct rocker_neigh_tbl_entry *entry,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
const u8 *eth_dst, bool ttl_check)
{
if (eth_dst) {
ether_addr_copy(entry->eth_dst, eth_dst);
entry->ttl_check = ttl_check;
- } else if (trans_ph != SWITCHDEV_TRANS_PREPARE) {
+ } else if (rtrans->ph != ROCKER_TRANS_PH_PREPARE) {
entry->ref_count++;
}
}
static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
int flags, __be32 ip_addr, const u8 *eth_dst)
{
struct rocker *rocker = rocker_port->rocker;
@@ -2975,7 +2986,7 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port,
bool removing;
int err = 0;
- entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -2992,12 +3003,12 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port,
entry->dev = rocker_port->dev;
ether_addr_copy(entry->eth_dst, eth_dst);
entry->ttl_check = true;
- _rocker_neigh_add(rocker, trans_ph, entry);
+ _rocker_neigh_add(rocker, rtrans, entry);
} else if (removing) {
memcpy(entry, found, sizeof(*entry));
- _rocker_neigh_del(trans_ph, found);
+ _rocker_neigh_del(rtrans, found);
} else if (updating) {
- _rocker_neigh_update(found, trans_ph, eth_dst, true);
+ _rocker_neigh_update(found, rtrans, eth_dst, true);
memcpy(entry, found, sizeof(*entry));
} else {
err = -ENOENT;
@@ -3014,7 +3025,7 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port,
* other routes' nexthops.
*/
- err = rocker_group_l3_unicast(rocker_port, trans_ph, flags,
+ err = rocker_group_l3_unicast(rocker_port, rtrans, flags,
entry->index,
rocker_port->dev->dev_addr,
entry->eth_dst,
@@ -3030,7 +3041,7 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port,
if (adding || removing) {
group_id = ROCKER_GROUP_L3_UNICAST(entry->index);
- err = rocker_flow_tbl_ucast4_routing(rocker_port, trans_ph,
+ err = rocker_flow_tbl_ucast4_routing(rocker_port, rtrans,
eth_type, ip_addr,
inet_make_mask(32),
priority, goto_tbl,
@@ -3044,13 +3055,13 @@ static int rocker_port_ipv4_neigh(struct rocker_port *rocker_port,
err_out:
if (!adding)
- rocker_port_kfree(trans_ph, entry);
+ rocker_port_kfree(rtrans, entry);
return err;
}
static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, __be32 ip_addr)
+ struct rocker_trans *rtrans, __be32 ip_addr)
{
struct net_device *dev = rocker_port->dev;
struct neighbour *n = __ipv4_neigh_lookup(dev, (__force u32)ip_addr);
@@ -3068,7 +3079,7 @@ static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port,
*/
if (n->nud_state & NUD_VALID)
- err = rocker_port_ipv4_neigh(rocker_port, trans_ph, 0,
+ err = rocker_port_ipv4_neigh(rocker_port, rtrans, 0,
ip_addr, n->ha);
else
neigh_event_send(n, NULL);
@@ -3078,7 +3089,7 @@ static int rocker_port_ipv4_resolve(struct rocker_port *rocker_port,
}
static int rocker_port_ipv4_nh(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
__be32 ip_addr, u32 *index)
{
struct rocker *rocker = rocker_port->rocker;
@@ -3091,7 +3102,7 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port,
bool resolved = true;
int err = 0;
- entry = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*entry));
+ entry = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*entry));
if (!entry)
return -ENOMEM;
@@ -3108,13 +3119,13 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port,
if (adding) {
entry->ip_addr = ip_addr;
entry->dev = rocker_port->dev;
- _rocker_neigh_add(rocker, trans_ph, entry);
+ _rocker_neigh_add(rocker, rtrans, entry);
*index = entry->index;
resolved = false;
} else if (removing) {
- _rocker_neigh_del(trans_ph, found);
+ _rocker_neigh_del(rtrans, found);
} else if (updating) {
- _rocker_neigh_update(found, trans_ph, NULL, false);
+ _rocker_neigh_update(found, rtrans, NULL, false);
resolved = !is_zero_ether_addr(found->eth_dst);
} else {
err = -ENOENT;
@@ -3123,7 +3134,7 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port,
spin_unlock_irqrestore(&rocker->neigh_tbl_lock, lock_flags);
if (!adding)
- rocker_port_kfree(trans_ph, entry);
+ rocker_port_kfree(rtrans, entry);
if (err)
return err;
@@ -3131,13 +3142,13 @@ static int rocker_port_ipv4_nh(struct rocker_port *rocker_port,
/* Resolved means neigh ip_addr is resolved to neigh mac. */
if (!resolved)
- err = rocker_port_ipv4_resolve(rocker_port, trans_ph, ip_addr);
+ err = rocker_port_ipv4_resolve(rocker_port, rtrans, ip_addr);
return err;
}
static int rocker_port_vlan_flood_group(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
int flags, __be16 vlan_id)
{
struct rocker_port *p;
@@ -3148,7 +3159,7 @@ static int rocker_port_vlan_flood_group(struct rocker_port *rocker_port,
int err = 0;
int i;
- group_ids = rocker_port_kcalloc(rocker_port, trans_ph, flags,
+ group_ids = rocker_port_kcalloc(rocker_port, rtrans, flags,
rocker->port_count, sizeof(u32));
if (!group_ids)
return -ENOMEM;
@@ -3174,19 +3185,19 @@ static int rocker_port_vlan_flood_group(struct rocker_port *rocker_port,
if (group_count == 0)
goto no_ports_in_vlan;
- err = rocker_group_l2_flood(rocker_port, trans_ph, flags, vlan_id,
+ err = rocker_group_l2_flood(rocker_port, rtrans, flags, vlan_id,
group_count, group_ids, group_id);
if (err)
netdev_err(rocker_port->dev,
"Error (%d) port VLAN l2 flood group\n", err);
no_ports_in_vlan:
- rocker_port_kfree(trans_ph, group_ids);
+ rocker_port_kfree(rtrans, group_ids);
return err;
}
static int rocker_port_vlan_l2_groups(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
__be16 vlan_id, bool pop_vlan)
{
const struct rocker *rocker = rocker_port->rocker;
@@ -3204,7 +3215,7 @@ static int rocker_port_vlan_l2_groups(struct rocker_port *rocker_port,
if (rocker_port->stp_state == BR_STATE_LEARNING ||
rocker_port->stp_state == BR_STATE_FORWARDING) {
out_pport = rocker_port->pport;
- err = rocker_group_l2_interface(rocker_port, trans_ph, flags,
+ err = rocker_group_l2_interface(rocker_port, rtrans, flags,
vlan_id, out_pport, pop_vlan);
if (err) {
netdev_err(rocker_port->dev,
@@ -3229,7 +3240,7 @@ static int rocker_port_vlan_l2_groups(struct rocker_port *rocker_port,
return 0;
out_pport = 0;
- err = rocker_group_l2_interface(rocker_port, trans_ph, flags,
+ err = rocker_group_l2_interface(rocker_port, rtrans, flags,
vlan_id, out_pport, pop_vlan);
if (err) {
netdev_err(rocker_port->dev,
@@ -3292,7 +3303,7 @@ static struct rocker_ctrl {
};
static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
const struct rocker_ctrl *ctrl, __be16 vlan_id)
{
u32 in_pport = rocker_port->pport;
@@ -3308,7 +3319,7 @@ static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port,
u32 group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport);
int err;
- err = rocker_flow_tbl_acl(rocker_port, trans_ph, flags,
+ err = rocker_flow_tbl_acl(rocker_port, rtrans, flags,
in_pport, in_pport_mask,
eth_src, eth_src_mask,
ctrl->eth_dst, ctrl->eth_dst_mask,
@@ -3325,7 +3336,7 @@ static int rocker_port_ctrl_vlan_acl(struct rocker_port *rocker_port,
}
static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
const struct rocker_ctrl *ctrl,
__be16 vlan_id)
{
@@ -3338,7 +3349,7 @@ static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port,
if (!rocker_port_is_bridged(rocker_port))
return 0;
- err = rocker_flow_tbl_bridge(rocker_port, trans_ph, flags,
+ err = rocker_flow_tbl_bridge(rocker_port, rtrans, flags,
ctrl->eth_dst, ctrl->eth_dst_mask,
vlan_id, tunnel_id,
goto_tbl, group_id, ctrl->copy_to_cpu);
@@ -3350,7 +3361,7 @@ static int rocker_port_ctrl_vlan_bridge(struct rocker_port *rocker_port,
}
static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
const struct rocker_ctrl *ctrl, __be16 vlan_id)
{
u32 in_pport_mask = 0xffffffff;
@@ -3360,7 +3371,7 @@ static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port,
if (ntohs(vlan_id) == 0)
vlan_id = rocker_port->internal_vlan_id;
- err = rocker_flow_tbl_term_mac(rocker_port, trans_ph,
+ err = rocker_flow_tbl_term_mac(rocker_port, rtrans,
rocker_port->pport, in_pport_mask,
ctrl->eth_type, ctrl->eth_dst,
ctrl->eth_dst_mask, vlan_id,
@@ -3374,25 +3385,25 @@ static int rocker_port_ctrl_vlan_term(struct rocker_port *rocker_port,
}
static int rocker_port_ctrl_vlan(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
const struct rocker_ctrl *ctrl, __be16 vlan_id)
{
if (ctrl->acl)
- return rocker_port_ctrl_vlan_acl(rocker_port, trans_ph, flags,
+ return rocker_port_ctrl_vlan_acl(rocker_port, rtrans, flags,
ctrl, vlan_id);
if (ctrl->bridge)
- return rocker_port_ctrl_vlan_bridge(rocker_port, trans_ph, flags,
+ return rocker_port_ctrl_vlan_bridge(rocker_port, rtrans, flags,
ctrl, vlan_id);
if (ctrl->term)
- return rocker_port_ctrl_vlan_term(rocker_port, trans_ph, flags,
+ return rocker_port_ctrl_vlan_term(rocker_port, rtrans, flags,
ctrl, vlan_id);
return -EOPNOTSUPP;
}
static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
__be16 vlan_id)
{
int err = 0;
@@ -3400,7 +3411,7 @@ static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port,
for (i = 0; i < ROCKER_CTRL_MAX; i++) {
if (rocker_port->ctrls[i]) {
- err = rocker_port_ctrl_vlan(rocker_port, trans_ph, flags,
+ err = rocker_port_ctrl_vlan(rocker_port, rtrans, flags,
&rocker_ctrls[i], vlan_id);
if (err)
return err;
@@ -3411,7 +3422,7 @@ static int rocker_port_ctrl_vlan_add(struct rocker_port *rocker_port,
}
static int rocker_port_ctrl(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
const struct rocker_ctrl *ctrl)
{
u16 vid;
@@ -3420,7 +3431,7 @@ static int rocker_port_ctrl(struct rocker_port *rocker_port,
for (vid = 1; vid < VLAN_N_VID; vid++) {
if (!test_bit(vid, rocker_port->vlan_bitmap))
continue;
- err = rocker_port_ctrl_vlan(rocker_port, trans_ph, flags,
+ err = rocker_port_ctrl_vlan(rocker_port, rtrans, flags,
ctrl, htons(vid));
if (err)
break;
@@ -3430,7 +3441,7 @@ static int rocker_port_ctrl(struct rocker_port *rocker_port,
}
static int rocker_port_vlan(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags, u16 vid)
+ struct rocker_trans *rtrans, int flags, u16 vid)
{
enum rocker_of_dpa_table_id goto_tbl =
ROCKER_OF_DPA_TABLE_ID_TERMINATION_MAC;
@@ -3454,7 +3465,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port,
change_bit(ntohs(internal_vlan_id), rocker_port->vlan_bitmap);
if (adding) {
- err = rocker_port_ctrl_vlan_add(rocker_port, trans_ph, flags,
+ err = rocker_port_ctrl_vlan_add(rocker_port, rtrans, flags,
internal_vlan_id);
if (err) {
netdev_err(rocker_port->dev,
@@ -3463,7 +3474,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port,
}
}
- err = rocker_port_vlan_l2_groups(rocker_port, trans_ph, flags,
+ err = rocker_port_vlan_l2_groups(rocker_port, rtrans, flags,
internal_vlan_id, untagged);
if (err) {
netdev_err(rocker_port->dev,
@@ -3471,7 +3482,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port,
goto err_out;
}
- err = rocker_port_vlan_flood_group(rocker_port, trans_ph, flags,
+ err = rocker_port_vlan_flood_group(rocker_port, rtrans, flags,
internal_vlan_id);
if (err) {
netdev_err(rocker_port->dev,
@@ -3479,7 +3490,7 @@ static int rocker_port_vlan(struct rocker_port *rocker_port,
goto err_out;
}
- err = rocker_flow_tbl_vlan(rocker_port, trans_ph, flags,
+ err = rocker_flow_tbl_vlan(rocker_port, rtrans, flags,
in_pport, vlan_id, vlan_id_mask,
goto_tbl, untagged, internal_vlan_id);
if (err)
@@ -3487,14 +3498,14 @@ static int rocker_port_vlan(struct rocker_port *rocker_port,
"Error (%d) port VLAN table\n", err);
err_out:
- if (trans_ph == SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph == ROCKER_TRANS_PH_PREPARE)
change_bit(ntohs(internal_vlan_id), rocker_port->vlan_bitmap);
return err;
}
static int rocker_port_ig_tbl(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags)
+ struct rocker_trans *rtrans, int flags)
{
enum rocker_of_dpa_table_id goto_tbl;
u32 in_pport;
@@ -3509,7 +3520,7 @@ static int rocker_port_ig_tbl(struct rocker_port *rocker_port,
in_pport_mask = 0xffff0000;
goto_tbl = ROCKER_OF_DPA_TABLE_ID_VLAN;
- err = rocker_flow_tbl_ig_port(rocker_port, trans_ph, flags,
+ err = rocker_flow_tbl_ig_port(rocker_port, rtrans, flags,
in_pport, in_pport_mask,
goto_tbl);
if (err)
@@ -3522,7 +3533,7 @@ static int rocker_port_ig_tbl(struct rocker_port *rocker_port,
struct rocker_fdb_learn_work {
struct work_struct work;
struct rocker_port *rocker_port;
- enum switchdev_trans_ph trans_ph;
+ struct rocker_trans *rtrans;
int flags;
u8 addr[ETH_ALEN];
u16 vid;
@@ -3546,11 +3557,11 @@ static void rocker_port_fdb_learn_work(struct work_struct *work)
call_switchdev_notifiers(SWITCHDEV_FDB_ADD,
lw->rocker_port->dev, &info.info);
- rocker_port_kfree(lw->trans_ph, work);
+ rocker_port_kfree(lw->rtrans, work);
}
static int rocker_port_fdb_learn(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
const u8 *addr, __be16 vlan_id)
{
struct rocker_fdb_learn_work *lw;
@@ -3567,7 +3578,7 @@ static int rocker_port_fdb_learn(struct rocker_port *rocker_port,
group_id = ROCKER_GROUP_L2_INTERFACE(vlan_id, out_pport);
if (!(flags & ROCKER_OP_FLAG_REFRESH)) {
- err = rocker_flow_tbl_bridge(rocker_port, trans_ph, flags, addr,
+ err = rocker_flow_tbl_bridge(rocker_port, rtrans, flags, addr,
NULL, vlan_id, tunnel_id, goto_tbl,
group_id, copy_to_cpu);
if (err)
@@ -3580,20 +3591,20 @@ static int rocker_port_fdb_learn(struct rocker_port *rocker_port,
if (!rocker_port_is_bridged(rocker_port))
return 0;
- lw = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*lw));
+ lw = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*lw));
if (!lw)
return -ENOMEM;
INIT_WORK(&lw->work, rocker_port_fdb_learn_work);
lw->rocker_port = rocker_port;
- lw->trans_ph = trans_ph;
+ lw->rtrans = rtrans;
lw->flags = flags;
ether_addr_copy(lw->addr, addr);
lw->vid = rocker_port_vlan_to_vid(rocker_port, vlan_id);
- if (trans_ph == SWITCHDEV_TRANS_PREPARE)
- rocker_port_kfree(trans_ph, lw);
+ if (rtrans->ph == ROCKER_TRANS_PH_PREPARE)
+ rocker_port_kfree(rtrans, lw);
else
schedule_work(&lw->work);
@@ -3614,7 +3625,7 @@ rocker_fdb_tbl_find(const struct rocker *rocker,
}
static int rocker_port_fdb(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
const unsigned char *addr,
__be16 vlan_id, int flags)
{
@@ -3624,7 +3635,7 @@ static int rocker_port_fdb(struct rocker_port *rocker_port,
bool removing = (flags & ROCKER_OP_FLAG_REMOVE);
unsigned long lock_flags;
- fdb = rocker_port_kzalloc(rocker_port, trans_ph, flags, sizeof(*fdb));
+ fdb = rocker_port_kzalloc(rocker_port, rtrans, flags, sizeof(*fdb));
if (!fdb)
return -ENOMEM;
@@ -3639,11 +3650,11 @@ static int rocker_port_fdb(struct rocker_port *rocker_port,
found = rocker_fdb_tbl_find(rocker, fdb);
if (removing && found) {
- rocker_port_kfree(trans_ph, fdb);
- if (trans_ph != SWITCHDEV_TRANS_PREPARE)
+ rocker_port_kfree(rtrans, fdb);
+ if (rtrans->ph != ROCKER_TRANS_PH_PREPARE)
hash_del(&found->entry);
} else if (!removing && !found) {
- if (trans_ph != SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph != ROCKER_TRANS_PH_PREPARE)
hash_add(rocker->fdb_tbl, &fdb->entry, fdb->key_crc32);
}
@@ -3651,18 +3662,18 @@ static int rocker_port_fdb(struct rocker_port *rocker_port,
/* Check if adding and already exists, or removing and can't find */
if (!found != !removing) {
- rocker_port_kfree(trans_ph, fdb);
+ rocker_port_kfree(rtrans, fdb);
if (!found && removing)
return 0;
/* Refreshing existing to update aging timers */
flags |= ROCKER_OP_FLAG_REFRESH;
}
- return rocker_port_fdb_learn(rocker_port, trans_ph, flags, addr, vlan_id);
+ return rocker_port_fdb_learn(rocker_port, rtrans, flags, addr, vlan_id);
}
static int rocker_port_fdb_flush(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags)
+ struct rocker_trans *rtrans, int flags)
{
struct rocker *rocker = rocker_port->rocker;
struct rocker_fdb_tbl_entry *found;
@@ -3684,12 +3695,12 @@ static int rocker_port_fdb_flush(struct rocker_port *rocker_port,
continue;
if (!found->learned)
continue;
- err = rocker_port_fdb_learn(rocker_port, trans_ph, flags,
+ err = rocker_port_fdb_learn(rocker_port, rtrans, flags,
found->key.addr,
found->key.vlan_id);
if (err)
goto err_out;
- if (trans_ph != SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph != ROCKER_TRANS_PH_PREPARE)
hash_del(&found->entry);
}
@@ -3700,7 +3711,7 @@ err_out:
}
static int rocker_port_router_mac(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
__be16 vlan_id)
{
u32 in_pport_mask = 0xffffffff;
@@ -3714,7 +3725,7 @@ static int rocker_port_router_mac(struct rocker_port *rocker_port,
vlan_id = rocker_port->internal_vlan_id;
eth_type = htons(ETH_P_IP);
- err = rocker_flow_tbl_term_mac(rocker_port, trans_ph,
+ err = rocker_flow_tbl_term_mac(rocker_port, rtrans,
rocker_port->pport, in_pport_mask,
eth_type, rocker_port->dev->dev_addr,
dst_mac_mask, vlan_id, vlan_id_mask,
@@ -3723,7 +3734,7 @@ static int rocker_port_router_mac(struct rocker_port *rocker_port,
return err;
eth_type = htons(ETH_P_IPV6);
- err = rocker_flow_tbl_term_mac(rocker_port, trans_ph,
+ err = rocker_flow_tbl_term_mac(rocker_port, rtrans,
rocker_port->pport, in_pport_mask,
eth_type, rocker_port->dev->dev_addr,
dst_mac_mask, vlan_id, vlan_id_mask,
@@ -3733,7 +3744,7 @@ static int rocker_port_router_mac(struct rocker_port *rocker_port,
}
static int rocker_port_fwding(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags)
+ struct rocker_trans *rtrans, int flags)
{
bool pop_vlan;
u32 out_pport;
@@ -3758,7 +3769,7 @@ static int rocker_port_fwding(struct rocker_port *rocker_port,
continue;
vlan_id = htons(vid);
pop_vlan = rocker_vlan_id_is_internal(vlan_id);
- err = rocker_group_l2_interface(rocker_port, trans_ph, flags,
+ err = rocker_group_l2_interface(rocker_port, rtrans, flags,
vlan_id, out_pport, pop_vlan);
if (err) {
netdev_err(rocker_port->dev,
@@ -3772,7 +3783,7 @@ static int rocker_port_fwding(struct rocker_port *rocker_port,
}
static int rocker_port_stp_update(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags,
+ struct rocker_trans *rtrans, int flags,
u8 state)
{
bool want[ROCKER_CTRL_MAX] = { 0, };
@@ -3781,7 +3792,7 @@ static int rocker_port_stp_update(struct rocker_port *rocker_port,
int err;
int i;
- if (trans_ph == SWITCHDEV_TRANS_PREPARE) {
+ if (rtrans->ph == ROCKER_TRANS_PH_PREPARE) {
memcpy(prev_ctrls, rocker_port->ctrls, sizeof(prev_ctrls));
prev_state = rocker_port->stp_state;
}
@@ -3818,7 +3829,7 @@ static int rocker_port_stp_update(struct rocker_port *rocker_port,
if (want[i] != rocker_port->ctrls[i]) {
int ctrl_flags = flags |
(want[i] ? 0 : ROCKER_OP_FLAG_REMOVE);
- err = rocker_port_ctrl(rocker_port, trans_ph, ctrl_flags,
+ err = rocker_port_ctrl(rocker_port, rtrans, ctrl_flags,
&rocker_ctrls[i]);
if (err)
goto err_out;
@@ -3826,14 +3837,14 @@ static int rocker_port_stp_update(struct rocker_port *rocker_port,
}
}
- err = rocker_port_fdb_flush(rocker_port, trans_ph, flags);
+ err = rocker_port_fdb_flush(rocker_port, rtrans, flags);
if (err)
goto err_out;
- err = rocker_port_fwding(rocker_port, trans_ph, flags);
+ err = rocker_port_fwding(rocker_port, rtrans, flags);
err_out:
- if (trans_ph == SWITCHDEV_TRANS_PREPARE) {
+ if (rtrans->ph == ROCKER_TRANS_PH_PREPARE) {
memcpy(rocker_port->ctrls, prev_ctrls, sizeof(prev_ctrls));
rocker_port->stp_state = prev_state;
}
@@ -3842,26 +3853,26 @@ err_out:
}
static int rocker_port_fwd_enable(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags)
+ struct rocker_trans *rtrans, int flags)
{
if (rocker_port_is_bridged(rocker_port))
/* bridge STP will enable port */
return 0;
/* port is not bridged, so simulate going to FORWARDING state */
- return rocker_port_stp_update(rocker_port, trans_ph, flags,
+ return rocker_port_stp_update(rocker_port, rtrans, flags,
BR_STATE_FORWARDING);
}
static int rocker_port_fwd_disable(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, int flags)
+ struct rocker_trans *rtrans, int flags)
{
if (rocker_port_is_bridged(rocker_port))
/* bridge STP will disable port */
return 0;
/* port is not bridged, so simulate going to DISABLED state */
- return rocker_port_stp_update(rocker_port, trans_ph, flags,
+ return rocker_port_stp_update(rocker_port, rtrans, flags,
BR_STATE_DISABLED);
}
@@ -3952,7 +3963,7 @@ not_found:
}
static int rocker_port_fib_ipv4(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, __be32 dst,
+ struct rocker_trans *rtrans, __be32 dst,
int dst_len, const struct fib_info *fi,
u32 tb_id, int flags)
{
@@ -3976,7 +3987,7 @@ static int rocker_port_fib_ipv4(struct rocker_port *rocker_port,
has_gw = !!nh->nh_gw;
if (has_gw && nh_on_port) {
- err = rocker_port_ipv4_nh(rocker_port, trans_ph, flags,
+ err = rocker_port_ipv4_nh(rocker_port, rtrans, flags,
nh->nh_gw, &index);
if (err)
return err;
@@ -3987,7 +3998,7 @@ static int rocker_port_fib_ipv4(struct rocker_port *rocker_port,
group_id = ROCKER_GROUP_L2_INTERFACE(internal_vlan_id, 0);
}
- err = rocker_flow_tbl_ucast4_routing(rocker_port, trans_ph, eth_type, dst,
+ err = rocker_flow_tbl_ucast4_routing(rocker_port, rtrans, eth_type, dst,
dst_mask, priority, goto_tbl,
group_id, flags);
if (err)
@@ -4026,7 +4037,7 @@ static int rocker_port_open(struct net_device *dev)
goto err_request_rx_irq;
}
- err = rocker_port_fwd_enable(rocker_port, SWITCHDEV_TRANS_NONE, 0);
+ err = rocker_port_fwd_enable(rocker_port, ROCKER_TRANS_PH_NONE, 0);
if (err)
goto err_fwd_enable;
@@ -4054,7 +4065,7 @@ static int rocker_port_stop(struct net_device *dev)
rocker_port_set_enable(rocker_port, false);
napi_disable(&rocker_port->napi_rx);
napi_disable(&rocker_port->napi_tx);
- rocker_port_fwd_disable(rocker_port, SWITCHDEV_TRANS_NONE,
+ rocker_port_fwd_disable(rocker_port, ROCKER_TRANS_PH_NONE,
ROCKER_OP_FLAG_NOWAIT);
free_irq(rocker_msix_rx_vector(rocker_port), rocker_port);
free_irq(rocker_msix_tx_vector(rocker_port), rocker_port);
@@ -4240,7 +4251,7 @@ static int rocker_port_get_phys_port_name(struct net_device *dev,
struct port_name name = { .buf = buf, .len = len };
int err;
- err = rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ err = rocker_cmd_exec(rocker_port, ROCKER_TRANS_PH_NONE, 0,
rocker_cmd_get_port_settings_prep, NULL,
rocker_cmd_get_port_settings_phys_name_proc,
&name);
@@ -4265,7 +4276,7 @@ static void rocker_port_neigh_destroy(struct neighbour *n)
int flags = ROCKER_OP_FLAG_REMOVE | ROCKER_OP_FLAG_NOWAIT;
__be32 ip_addr = *(__be32 *)n->primary_key;
- rocker_port_ipv4_neigh(rocker_port, SWITCHDEV_TRANS_NONE,
+ rocker_port_ipv4_neigh(rocker_port, ROCKER_TRANS_PH_NONE,
flags, ip_addr, n->ha);
}
@@ -4322,7 +4333,7 @@ static void rocker_port_trans_abort(const struct rocker_port *rocker_port)
}
static int rocker_port_brport_flags_set(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
unsigned long brport_flags)
{
unsigned long orig_flags;
@@ -4331,9 +4342,9 @@ static int rocker_port_brport_flags_set(struct rocker_port *rocker_port,
orig_flags = rocker_port->brport_flags;
rocker_port->brport_flags = brport_flags;
if ((orig_flags ^ rocker_port->brport_flags) & BR_LEARNING)
- err = rocker_port_set_learning(rocker_port, trans_ph);
+ err = rocker_port_set_learning(rocker_port, rtrans);
- if (trans_ph == SWITCHDEV_TRANS_PREPARE)
+ if (rtrans->ph == ROCKER_TRANS_PH_PREPARE)
rocker_port->brport_flags = orig_flags;
return err;
@@ -4344,13 +4355,16 @@ static int rocker_port_attr_set(struct net_device *dev,
struct switchdev_trans *trans)
{
struct rocker_port *rocker_port = netdev_priv(dev);
+ struct rocker_trans rtrans = {
+ .ph = attr->trans_ph,
+ };
int err = 0;
- switch (attr->trans_ph) {
- case SWITCHDEV_TRANS_PREPARE:
+ switch (rtrans.ph) {
+ case ROCKER_TRANS_PH_PREPARE:
BUG_ON(!list_empty(&rocker_port->trans_mem));
break;
- case SWITCHDEV_TRANS_ABORT:
+ case ROCKER_TRANS_PH_ABORT:
rocker_port_trans_abort(rocker_port);
return 0;
default:
@@ -4359,12 +4373,12 @@ static int rocker_port_attr_set(struct net_device *dev,
switch (attr->id) {
case SWITCHDEV_ATTR_PORT_STP_STATE:
- err = rocker_port_stp_update(rocker_port, attr->trans_ph,
+ err = rocker_port_stp_update(rocker_port, &rtrans,
ROCKER_OP_FLAG_NOWAIT,
attr->u.stp_state);
break;
case SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS:
- err = rocker_port_brport_flags_set(rocker_port, attr->trans_ph,
+ err = rocker_port_brport_flags_set(rocker_port, &rtrans,
attr->u.brport_flags);
break;
default:
@@ -4376,33 +4390,33 @@ static int rocker_port_attr_set(struct net_device *dev,
}
static int rocker_port_vlan_add(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph, u16 vid, u16 flags)
+ struct rocker_trans *rtrans, u16 vid, u16 flags)
{
int err;
/* XXX deal with flags for PVID and untagged */
- err = rocker_port_vlan(rocker_port, trans_ph, 0, vid);
+ err = rocker_port_vlan(rocker_port, rtrans, 0, vid);
if (err)
return err;
- err = rocker_port_router_mac(rocker_port, trans_ph, 0, htons(vid));
+ err = rocker_port_router_mac(rocker_port, rtrans, 0, htons(vid));
if (err)
- rocker_port_vlan(rocker_port, trans_ph,
+ rocker_port_vlan(rocker_port, rtrans,
ROCKER_OP_FLAG_REMOVE, vid);
return err;
}
static int rocker_port_vlans_add(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
const struct switchdev_obj_vlan *vlan)
{
u16 vid;
int err;
for (vid = vlan->vid_begin; vid <= vlan->vid_end; vid++) {
- err = rocker_port_vlan_add(rocker_port, trans_ph,
+ err = rocker_port_vlan_add(rocker_port, rtrans,
vid, vlan->flags);
if (err)
return err;
@@ -4412,7 +4426,7 @@ static int rocker_port_vlans_add(struct rocker_port *rocker_port,
}
static int rocker_port_fdb_add(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
const struct switchdev_obj_fdb *fdb)
{
__be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL);
@@ -4421,7 +4435,7 @@ static int rocker_port_fdb_add(struct rocker_port *rocker_port,
if (!rocker_port_is_bridged(rocker_port))
return -EINVAL;
- return rocker_port_fdb(rocker_port, trans_ph, fdb->addr, vlan_id, flags);
+ return rocker_port_fdb(rocker_port, rtrans, fdb->addr, vlan_id, flags);
}
static int rocker_port_obj_add(struct net_device *dev,
@@ -4429,14 +4443,17 @@ static int rocker_port_obj_add(struct net_device *dev,
struct switchdev_trans *trans)
{
struct rocker_port *rocker_port = netdev_priv(dev);
+ struct rocker_trans rtrans = {
+ .ph = obj->trans_ph,
+ };
const struct switchdev_obj_ipv4_fib *fib4;
int err = 0;
- switch (obj->trans_ph) {
- case SWITCHDEV_TRANS_PREPARE:
+ switch (rtrans.ph) {
+ case ROCKER_TRANS_PH_PREPARE:
BUG_ON(!list_empty(&rocker_port->trans_mem));
break;
- case SWITCHDEV_TRANS_ABORT:
+ case ROCKER_TRANS_PH_ABORT:
rocker_port_trans_abort(rocker_port);
return 0;
default:
@@ -4445,17 +4462,17 @@ static int rocker_port_obj_add(struct net_device *dev,
switch (obj->id) {
case SWITCHDEV_OBJ_PORT_VLAN:
- err = rocker_port_vlans_add(rocker_port, obj->trans_ph,
+ err = rocker_port_vlans_add(rocker_port, &rtrans,
&obj->u.vlan);
break;
case SWITCHDEV_OBJ_IPV4_FIB:
fib4 = &obj->u.ipv4_fib;
- err = rocker_port_fib_ipv4(rocker_port, obj->trans_ph,
+ err = rocker_port_fib_ipv4(rocker_port, &rtrans,
htonl(fib4->dst), fib4->dst_len,
fib4->fi, fib4->tb_id, 0);
break;
case SWITCHDEV_OBJ_PORT_FDB:
- err = rocker_port_fdb_add(rocker_port, obj->trans_ph, &obj->u.fdb);
+ err = rocker_port_fdb_add(rocker_port, &rtrans, &obj->u.fdb);
break;
default:
err = -EOPNOTSUPP;
@@ -4470,12 +4487,12 @@ static int rocker_port_vlan_del(struct rocker_port *rocker_port,
{
int err;
- err = rocker_port_router_mac(rocker_port, SWITCHDEV_TRANS_NONE,
+ err = rocker_port_router_mac(rocker_port, ROCKER_TRANS_PH_NONE,
ROCKER_OP_FLAG_REMOVE, htons(vid));
if (err)
return err;
- return rocker_port_vlan(rocker_port, SWITCHDEV_TRANS_NONE,
+ return rocker_port_vlan(rocker_port, ROCKER_TRANS_PH_NONE,
ROCKER_OP_FLAG_REMOVE, vid);
}
@@ -4495,7 +4512,7 @@ static int rocker_port_vlans_del(struct rocker_port *rocker_port,
}
static int rocker_port_fdb_del(struct rocker_port *rocker_port,
- enum switchdev_trans_ph trans_ph,
+ struct rocker_trans *rtrans,
const struct switchdev_obj_fdb *fdb)
{
__be16 vlan_id = rocker_port_vid_to_vlan(rocker_port, fdb->vid, NULL);
@@ -4504,13 +4521,16 @@ static int rocker_port_fdb_del(struct rocker_port *rocker_port,
if (!rocker_port_is_bridged(rocker_port))
return -EINVAL;
- return rocker_port_fdb(rocker_port, trans_ph, fdb->addr, vlan_id, flags);
+ return rocker_port_fdb(rocker_port, rtrans, fdb->addr, vlan_id, flags);
}
static int rocker_port_obj_del(struct net_device *dev,
struct switchdev_obj *obj)
{
struct rocker_port *rocker_port = netdev_priv(dev);
+ struct rocker_trans rtrans = {
+ .ph = ROCKER_TRANS_PH_NONE,
+ };
const struct switchdev_obj_ipv4_fib *fib4;
int err = 0;
@@ -4520,13 +4540,14 @@ static int rocker_port_obj_del(struct net_device *dev,
break;
case SWITCHDEV_OBJ_IPV4_FIB:
fib4 = &obj->u.ipv4_fib;
- err = rocker_port_fib_ipv4(rocker_port, SWITCHDEV_TRANS_NONE,
+ err = rocker_port_fib_ipv4(rocker_port, &rtrans,
htonl(fib4->dst), fib4->dst_len,
fib4->fi, fib4->tb_id,
ROCKER_OP_FLAG_REMOVE);
break;
case SWITCHDEV_OBJ_PORT_FDB:
- err = rocker_port_fdb_del(rocker_port, obj->trans_ph, &obj->u.fdb);
+ err = rocker_port_fdb_del(rocker_port, &rtrans,
+ &obj->u.fdb);
break;
default:
err = -EOPNOTSUPP;
@@ -4740,7 +4761,7 @@ rocker_cmd_get_port_stats_ethtool_proc(const struct rocker_port *rocker_port,
static int rocker_cmd_get_port_stats_ethtool(struct rocker_port *rocker_port,
void *priv)
{
- return rocker_cmd_exec(rocker_port, SWITCHDEV_TRANS_NONE, 0,
+ return rocker_cmd_exec(rocker_port, ROCKER_TRANS_PH_NONE, 0,
rocker_cmd_get_port_stats_prep, NULL,
rocker_cmd_get_port_stats_ethtool_proc,
priv);
@@ -4932,7 +4953,7 @@ static void rocker_remove_ports(const struct rocker *rocker)
rocker_port = rocker->ports[i];
if (!rocker_port)
continue;
- rocker_port_ig_tbl(rocker_port, SWITCHDEV_TRANS_NONE,
+ rocker_port_ig_tbl(rocker_port, ROCKER_TRANS_PH_NONE,
ROCKER_OP_FLAG_REMOVE);
unregister_netdev(rocker_port->dev);
free_netdev(rocker_port->dev);
@@ -4994,9 +5015,9 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
switchdev_port_fwd_mark_set(rocker_port->dev, NULL, false);
- rocker_port_set_learning(rocker_port, SWITCHDEV_TRANS_NONE);
+ rocker_port_set_learning(rocker_port, ROCKER_TRANS_PH_NONE);
- err = rocker_port_ig_tbl(rocker_port, SWITCHDEV_TRANS_NONE, 0);
+ err = rocker_port_ig_tbl(rocker_port, ROCKER_TRANS_PH_NONE, 0);
if (err) {
netdev_err(rocker_port->dev, "install ig port table failed\n");
goto err_port_ig_tbl;
@@ -5005,7 +5026,7 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
rocker_port->internal_vlan_id =
rocker_port_internal_vlan_id_get(rocker_port, dev->ifindex);
- err = rocker_port_vlan_add(rocker_port, SWITCHDEV_TRANS_NONE,
+ err = rocker_port_vlan_add(rocker_port, ROCKER_TRANS_PH_NONE,
untagged_vid, 0);
if (err) {
netdev_err(rocker_port->dev, "install untagged VLAN failed\n");
@@ -5015,7 +5036,7 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
return 0;
err_untagged_vlan:
- rocker_port_ig_tbl(rocker_port, SWITCHDEV_TRANS_NONE,
+ rocker_port_ig_tbl(rocker_port, ROCKER_TRANS_PH_NONE,
ROCKER_OP_FLAG_REMOVE);
err_port_ig_tbl:
rocker->ports[port_number] = NULL;
@@ -5277,7 +5298,7 @@ static int rocker_port_bridge_join(struct rocker_port *rocker_port,
rocker_port->bridge_dev = bridge;
switchdev_port_fwd_mark_set(rocker_port->dev, bridge, true);
- return rocker_port_vlan_add(rocker_port, SWITCHDEV_TRANS_NONE,
+ return rocker_port_vlan_add(rocker_port, ROCKER_TRANS_PH_NONE,
untagged_vid, 0);
}
@@ -5300,14 +5321,14 @@ static int rocker_port_bridge_leave(struct rocker_port *rocker_port)
false);
rocker_port->bridge_dev = NULL;
- err = rocker_port_vlan_add(rocker_port, SWITCHDEV_TRANS_NONE,
+ err = rocker_port_vlan_add(rocker_port, ROCKER_TRANS_PH_NONE,
untagged_vid, 0);
if (err)
return err;
if (rocker_port->dev->flags & IFF_UP)
err = rocker_port_fwd_enable(rocker_port,
- SWITCHDEV_TRANS_NONE, 0);
+ ROCKER_TRANS_PH_NONE, 0);
return err;
}
@@ -5320,10 +5341,10 @@ static int rocker_port_ovs_changed(struct rocker_port *rocker_port,
rocker_port->bridge_dev = master;
- err = rocker_port_fwd_disable(rocker_port, SWITCHDEV_TRANS_NONE, 0);
+ err = rocker_port_fwd_disable(rocker_port, ROCKER_TRANS_PH_NONE, 0);
if (err)
return err;
- err = rocker_port_fwd_enable(rocker_port, SWITCHDEV_TRANS_NONE, 0);
+ err = rocker_port_fwd_enable(rocker_port, ROCKER_TRANS_PH_NONE, 0);
return err;
}
@@ -5401,7 +5422,7 @@ static int rocker_neigh_update(struct net_device *dev, struct neighbour *n)
ROCKER_OP_FLAG_NOWAIT;
__be32 ip_addr = *(__be32 *)n->primary_key;
- return rocker_port_ipv4_neigh(rocker_port, SWITCHDEV_TRANS_NONE,
+ return rocker_port_ipv4_neigh(rocker_port, ROCKER_TRANS_PH_NONE,
flags, ip_addr, n->ha);
}
--
1.9.3
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [patch net-next RFC 4/6] switchdev: move transaction phase enum under transaction structure
2015-09-19 12:29 [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Jiri Pirko
` (2 preceding siblings ...)
2015-09-19 12:29 ` [patch net-next RFC 3/6] rocker: switch to local transaction phase enum Jiri Pirko
@ 2015-09-19 12:29 ` Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 5/6] rocker: use switchdev transaction queue for allocated memory Jiri Pirko
` (4 subsequent siblings)
8 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2015-09-19 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, idosch, eladr, sfeldma, f.fainelli, linux, vivien.didelot
Before it disappears completely, move transaction phase enum under
transaction structure and make attr/obj structures a bit cleaner.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
drivers/net/ethernet/rocker/rocker.c | 4 ++--
include/net/switchdev.h | 3 +--
net/dsa/slave.c | 18 ++++++++++--------
net/switchdev/switchdev.c | 12 ++++++------
4 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index de1a367..9750840 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -4356,7 +4356,7 @@ static int rocker_port_attr_set(struct net_device *dev,
{
struct rocker_port *rocker_port = netdev_priv(dev);
struct rocker_trans rtrans = {
- .ph = attr->trans_ph,
+ .ph = trans->ph,
};
int err = 0;
@@ -4444,7 +4444,7 @@ static int rocker_port_obj_add(struct net_device *dev,
{
struct rocker_port *rocker_port = netdev_priv(dev);
struct rocker_trans rtrans = {
- .ph = obj->trans_ph,
+ .ph = trans->ph,
};
const struct switchdev_obj_ipv4_fib *fib4;
int err = 0;
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 1e394f1..368a642 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -32,6 +32,7 @@ struct switchdev_trans_item {
struct switchdev_trans {
struct list_head item_list;
+ enum switchdev_trans_ph ph;
};
enum switchdev_attr_id {
@@ -43,7 +44,6 @@ enum switchdev_attr_id {
struct switchdev_attr {
enum switchdev_attr_id id;
- enum switchdev_trans_ph trans_ph;
u32 flags;
union {
struct netdev_phys_item_id ppid; /* PORT_PARENT_ID */
@@ -63,7 +63,6 @@ enum switchdev_obj_id {
struct switchdev_obj {
enum switchdev_obj_id id;
- enum switchdev_trans_ph trans_ph;
int (*cb)(struct net_device *dev, struct switchdev_obj *obj);
union {
struct switchdev_obj_vlan { /* PORT_VLAN */
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index ac76fd1..748cc63 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -242,7 +242,8 @@ static int dsa_bridge_check_vlan_range(struct dsa_switch *ds,
}
static int dsa_slave_port_vlan_add(struct net_device *dev,
- struct switchdev_obj *obj)
+ struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
{
struct switchdev_obj_vlan *vlan = &obj->u.vlan;
struct dsa_slave_priv *p = netdev_priv(dev);
@@ -250,7 +251,7 @@ static int dsa_slave_port_vlan_add(struct net_device *dev,
u16 vid;
int err;
- switch (obj->trans_ph) {
+ switch (trans->ph) {
case SWITCHDEV_TRANS_PREPARE:
if (!ds->drv->port_vlan_add || !ds->drv->port_pvid_set)
return -EOPNOTSUPP;
@@ -347,16 +348,17 @@ static int dsa_slave_port_vlan_dump(struct net_device *dev,
}
static int dsa_slave_port_fdb_add(struct net_device *dev,
- struct switchdev_obj *obj)
+ struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
{
struct switchdev_obj_fdb *fdb = &obj->u.fdb;
struct dsa_slave_priv *p = netdev_priv(dev);
struct dsa_switch *ds = p->parent;
int ret = -EOPNOTSUPP;
- if (obj->trans_ph == SWITCHDEV_TRANS_PREPARE)
+ if (trans->ph == SWITCHDEV_TRANS_PREPARE)
ret = ds->drv->port_fdb_add ? 0 : -EOPNOTSUPP;
- else if (obj->trans_ph == SWITCHDEV_TRANS_COMMIT)
+ else if (trans->ph == SWITCHDEV_TRANS_COMMIT)
ret = ds->drv->port_fdb_add(ds, p->port, fdb->addr, fdb->vid);
return ret;
@@ -463,7 +465,7 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
switch (attr->id) {
case SWITCHDEV_ATTR_PORT_STP_STATE:
- if (attr->trans_ph == SWITCHDEV_TRANS_COMMIT)
+ if (trans->ph == SWITCHDEV_TRANS_COMMIT)
ret = dsa_slave_stp_update(dev, attr->u.stp_state);
break;
default:
@@ -487,10 +489,10 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
switch (obj->id) {
case SWITCHDEV_OBJ_PORT_FDB:
- err = dsa_slave_port_fdb_add(dev, obj);
+ err = dsa_slave_port_fdb_add(dev, obj, trans);
break;
case SWITCHDEV_OBJ_PORT_VLAN:
- err = dsa_slave_port_vlan_add(dev, obj);
+ err = dsa_slave_port_vlan_add(dev, obj, trans);
break;
default:
err = -EOPNOTSUPP;
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index a3647bf..82f8bcd 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -216,7 +216,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
@@ -225,7 +225,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);
}
@@ -238,7 +238,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);
@@ -302,7 +302,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
@@ -311,7 +311,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);
}
@@ -324,7 +324,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_destroy(&trans);
--
1.9.3
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [patch net-next RFC 5/6] rocker: use switchdev transaction queue for allocated memory
2015-09-19 12:29 [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Jiri Pirko
` (3 preceding siblings ...)
2015-09-19 12:29 ` [patch net-next RFC 4/6] switchdev: move transaction phase enum under transaction structure Jiri Pirko
@ 2015-09-19 12:29 ` Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 6/6] switchdev: split commit and prepare phase into two callbacks Jiri Pirko
` (3 subsequent siblings)
8 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2015-09-19 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, idosch, eladr, sfeldma, f.fainelli, linux, vivien.didelot
Benefit from previously introduced infra and remove rocker specific
transaction memory management.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
drivers/net/ethernet/rocker/rocker.c | 64 ++++++++----------------------------
1 file changed, 13 insertions(+), 51 deletions(-)
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index 9750840..0735d90 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -226,7 +226,6 @@ struct rocker_port {
struct napi_struct napi_rx;
struct rocker_dma_ring_info tx_ring;
struct rocker_dma_ring_info rx_ring;
- struct list_head trans_mem;
};
struct rocker {
@@ -347,6 +346,7 @@ enum rocker_trans_ph {
};
struct rocker_trans {
+ struct switchdev_trans *trans;
enum rocker_trans_ph ph;
};
@@ -354,7 +354,7 @@ static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port,
struct rocker_trans *rtrans, int flags,
size_t size)
{
- struct list_head *elem = NULL;
+ struct switchdev_trans_item *elem = NULL;
gfp_t gfp_flags = (flags & ROCKER_OP_FLAG_NOWAIT) ?
GFP_ATOMIC : GFP_KERNEL;
@@ -369,20 +369,15 @@ static void *__rocker_port_mem_alloc(struct rocker_port *rocker_port,
switch (rtrans->ph) {
case ROCKER_TRANS_PH_PREPARE:
- elem = kzalloc(size + sizeof(*elem), gfp_flags);
+ elem = kzalloc(size + sizeof(elem), gfp_flags);
if (!elem)
return NULL;
- list_add_tail(elem, &rocker_port->trans_mem);
- break;
+ switchdev_trans_item_enqueue(rtrans->trans, elem, kfree, elem);
case ROCKER_TRANS_PH_COMMIT:
- BUG_ON(list_empty(&rocker_port->trans_mem));
- elem = rocker_port->trans_mem.next;
- list_del_init(elem);
+ elem = switchdev_trans_item_dequeue(rtrans->trans);
break;
case ROCKER_TRANS_PH_NONE:
- elem = kzalloc(size + sizeof(*elem), gfp_flags);
- if (elem)
- INIT_LIST_HEAD(elem);
+ elem = kzalloc(size + sizeof(elem), gfp_flags);
break;
default:
break;
@@ -407,18 +402,16 @@ static void *rocker_port_kcalloc(struct rocker_port *rocker_port,
static void rocker_port_kfree(struct rocker_trans *rtrans, const void *mem)
{
- struct list_head *elem;
+ struct switchdev_trans_item *elem;
- /* Frees are ignored if in transaction prepare phase. The
- * memory remains on the per-port list until freed in the
- * commit phase.
+ /* Free only in case of NONE phase, otherwise, switchdev core
+ * will take care of the cleanup
*/
- if (rtrans->ph == ROCKER_TRANS_PH_PREPARE)
+ if (rtrans->ph != ROCKER_TRANS_PH_NONE)
return;
- elem = (struct list_head *)mem - 1;
- BUG_ON(!list_empty(elem));
+ elem = (struct switchdev_trans_item *) mem - 1;
kfree(elem);
}
@@ -4322,16 +4315,6 @@ static int rocker_port_attr_get(struct net_device *dev,
return 0;
}
-static void rocker_port_trans_abort(const struct rocker_port *rocker_port)
-{
- struct list_head *mem, *tmp;
-
- list_for_each_safe(mem, tmp, &rocker_port->trans_mem) {
- list_del(mem);
- kfree(mem);
- }
-}
-
static int rocker_port_brport_flags_set(struct rocker_port *rocker_port,
struct rocker_trans *rtrans,
unsigned long brport_flags)
@@ -4357,20 +4340,10 @@ static int rocker_port_attr_set(struct net_device *dev,
struct rocker_port *rocker_port = netdev_priv(dev);
struct rocker_trans rtrans = {
.ph = trans->ph,
+ .trans = trans,
};
int err = 0;
- switch (rtrans.ph) {
- case ROCKER_TRANS_PH_PREPARE:
- BUG_ON(!list_empty(&rocker_port->trans_mem));
- break;
- case ROCKER_TRANS_PH_ABORT:
- rocker_port_trans_abort(rocker_port);
- return 0;
- default:
- break;
- }
-
switch (attr->id) {
case SWITCHDEV_ATTR_PORT_STP_STATE:
err = rocker_port_stp_update(rocker_port, &rtrans,
@@ -4445,21 +4418,11 @@ static int rocker_port_obj_add(struct net_device *dev,
struct rocker_port *rocker_port = netdev_priv(dev);
struct rocker_trans rtrans = {
.ph = trans->ph,
+ .trans = trans,
};
const struct switchdev_obj_ipv4_fib *fib4;
int err = 0;
- switch (rtrans.ph) {
- case ROCKER_TRANS_PH_PREPARE:
- BUG_ON(!list_empty(&rocker_port->trans_mem));
- break;
- case ROCKER_TRANS_PH_ABORT:
- rocker_port_trans_abort(rocker_port);
- return 0;
- default:
- break;
- }
-
switch (obj->id) {
case SWITCHDEV_OBJ_PORT_VLAN:
err = rocker_port_vlans_add(rocker_port, &rtrans,
@@ -4992,7 +4955,6 @@ static int rocker_probe_port(struct rocker *rocker, unsigned int port_number)
rocker_port->port_number = port_number;
rocker_port->pport = port_number + 1;
rocker_port->brport_flags = BR_LEARNING | BR_LEARNING_SYNC;
- INIT_LIST_HEAD(&rocker_port->trans_mem);
rocker_port_dev_addr_init(rocker_port);
dev->netdev_ops = &rocker_port_netdev_ops;
--
1.9.3
^ permalink raw reply related [flat|nested] 23+ messages in thread
* [patch net-next RFC 6/6] switchdev: split commit and prepare phase into two callbacks
2015-09-19 12:29 [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Jiri Pirko
` (4 preceding siblings ...)
2015-09-19 12:29 ` [patch net-next RFC 5/6] rocker: use switchdev transaction queue for allocated memory Jiri Pirko
@ 2015-09-19 12:29 ` Jiri Pirko
2015-09-19 13:35 ` [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Rosen, Rami
` (2 subsequent siblings)
8 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2015-09-19 12:29 UTC (permalink / raw)
To: netdev; +Cc: davem, idosch, eladr, sfeldma, f.fainelli, linux, vivien.didelot
It is nore convenient to have prepare and commit phase for attr_set and
obj_add as separete callbacks. If a driver needs to do it differently, it
can easily do in inside its code.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
---
drivers/net/ethernet/rocker/rocker.c | 88 +++++++++++++++++++-------
include/net/switchdev.h | 18 +++---
net/dsa/slave.c | 117 +++++++++++++++++++++++------------
net/switchdev/switchdev.c | 74 +++++++++++++++++-----
4 files changed, 210 insertions(+), 87 deletions(-)
diff --git a/drivers/net/ethernet/rocker/rocker.c b/drivers/net/ethernet/rocker/rocker.c
index 0735d90..42aa86c 100644
--- a/drivers/net/ethernet/rocker/rocker.c
+++ b/drivers/net/ethernet/rocker/rocker.c
@@ -4333,35 +4333,55 @@ static int rocker_port_brport_flags_set(struct rocker_port *rocker_port,
return err;
}
-static int rocker_port_attr_set(struct net_device *dev,
- struct switchdev_attr *attr,
- struct switchdev_trans *trans)
+static int __rocker_port_attr_set(struct rocker_port *rocker_port,
+ struct switchdev_attr *attr,
+ struct rocker_trans *rtrans)
{
- struct rocker_port *rocker_port = netdev_priv(dev);
- struct rocker_trans rtrans = {
- .ph = trans->ph,
- .trans = trans,
- };
int err = 0;
switch (attr->id) {
case SWITCHDEV_ATTR_PORT_STP_STATE:
- err = rocker_port_stp_update(rocker_port, &rtrans,
+ err = rocker_port_stp_update(rocker_port, rtrans,
ROCKER_OP_FLAG_NOWAIT,
attr->u.stp_state);
break;
case SWITCHDEV_ATTR_PORT_BRIDGE_FLAGS:
- err = rocker_port_brport_flags_set(rocker_port, &rtrans,
+ err = rocker_port_brport_flags_set(rocker_port, rtrans,
attr->u.brport_flags);
break;
default:
err = -EOPNOTSUPP;
break;
}
-
return err;
}
+static int rocker_port_attr_pre_set(struct net_device *dev,
+ struct switchdev_attr *attr,
+ struct switchdev_trans *trans)
+{
+ struct rocker_port *rocker_port = netdev_priv(dev);
+ struct rocker_trans rtrans = {
+ .ph = ROCKER_TRANS_PH_PREPARE,
+ .trans = trans,
+ };
+
+ return __rocker_port_attr_set(rocker_port, attr, &rtrans);
+}
+
+static int rocker_port_attr_set(struct net_device *dev,
+ struct switchdev_attr *attr,
+ struct switchdev_trans *trans)
+{
+ struct rocker_port *rocker_port = netdev_priv(dev);
+ struct rocker_trans rtrans = {
+ .ph = ROCKER_TRANS_PH_COMMIT,
+ .trans = trans,
+ };
+
+ return __rocker_port_attr_set(rocker_port, attr, &rtrans);
+}
+
static int rocker_port_vlan_add(struct rocker_port *rocker_port,
struct rocker_trans *rtrans, u16 vid, u16 flags)
{
@@ -4411,40 +4431,60 @@ static int rocker_port_fdb_add(struct rocker_port *rocker_port,
return rocker_port_fdb(rocker_port, rtrans, fdb->addr, vlan_id, flags);
}
-static int rocker_port_obj_add(struct net_device *dev,
- struct switchdev_obj *obj,
- struct switchdev_trans *trans)
+static int __rocker_port_obj_add(struct rocker_port *rocker_port,
+ struct switchdev_obj *obj,
+ struct rocker_trans *rtrans)
{
- struct rocker_port *rocker_port = netdev_priv(dev);
- struct rocker_trans rtrans = {
- .ph = trans->ph,
- .trans = trans,
- };
const struct switchdev_obj_ipv4_fib *fib4;
int err = 0;
switch (obj->id) {
case SWITCHDEV_OBJ_PORT_VLAN:
- err = rocker_port_vlans_add(rocker_port, &rtrans,
+ err = rocker_port_vlans_add(rocker_port, rtrans,
&obj->u.vlan);
break;
case SWITCHDEV_OBJ_IPV4_FIB:
fib4 = &obj->u.ipv4_fib;
- err = rocker_port_fib_ipv4(rocker_port, &rtrans,
+ err = rocker_port_fib_ipv4(rocker_port, rtrans,
htonl(fib4->dst), fib4->dst_len,
fib4->fi, fib4->tb_id, 0);
break;
case SWITCHDEV_OBJ_PORT_FDB:
- err = rocker_port_fdb_add(rocker_port, &rtrans, &obj->u.fdb);
+ err = rocker_port_fdb_add(rocker_port, rtrans, &obj->u.fdb);
break;
default:
err = -EOPNOTSUPP;
break;
}
-
return err;
}
+static int rocker_port_obj_pre_add(struct net_device *dev,
+ struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
+{
+ struct rocker_port *rocker_port = netdev_priv(dev);
+ struct rocker_trans rtrans = {
+ .ph = ROCKER_TRANS_PH_PREPARE,
+ .trans = trans,
+ };
+
+ return __rocker_port_obj_add(rocker_port, obj, &rtrans);
+}
+
+static int rocker_port_obj_add(struct net_device *dev,
+ struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
+{
+ struct rocker_port *rocker_port = netdev_priv(dev);
+ struct rocker_trans rtrans = {
+ .ph = ROCKER_TRANS_PH_COMMIT,
+ .trans = trans,
+ };
+
+ return __rocker_port_obj_add(rocker_port, obj, &rtrans);
+}
+
static int rocker_port_vlan_del(struct rocker_port *rocker_port,
u16 vid, u16 flags)
{
@@ -4593,7 +4633,9 @@ static int rocker_port_obj_dump(struct net_device *dev,
static const struct switchdev_ops rocker_port_switchdev_ops = {
.switchdev_port_attr_get = rocker_port_attr_get,
+ .switchdev_port_attr_pre_set = rocker_port_attr_pre_set,
.switchdev_port_attr_set = rocker_port_attr_set,
+ .switchdev_port_obj_pre_add = rocker_port_obj_pre_add,
.switchdev_port_obj_add = rocker_port_obj_add,
.switchdev_port_obj_del = rocker_port_obj_del,
.switchdev_port_obj_dump = rocker_port_obj_dump,
diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 368a642..30f62f3 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -17,13 +17,6 @@
#define SWITCHDEV_F_NO_RECURSE BIT(0)
-enum switchdev_trans_ph {
- SWITCHDEV_TRANS_NONE,
- SWITCHDEV_TRANS_PREPARE,
- SWITCHDEV_TRANS_ABORT,
- SWITCHDEV_TRANS_COMMIT,
-};
-
struct switchdev_trans_item {
struct list_head list;
void *data;
@@ -32,7 +25,6 @@ struct switchdev_trans_item {
struct switchdev_trans {
struct list_head item_list;
- enum switchdev_trans_ph ph;
};
enum switchdev_attr_id {
@@ -97,8 +89,12 @@ void *switchdev_trans_item_dequeue(struct switchdev_trans *trans);
*
* @switchdev_port_attr_get: Get a port attribute (see switchdev_attr).
*
+ * @switchdev_port_attr_pre_set: Prepare to set a port attribute (see switchdev_attr).
+ *
* @switchdev_port_attr_set: Set a port attribute (see switchdev_attr).
*
+ * @switchdev_port_obj_pre_add: Prepare to add an object to port (see switchdev_obj).
+ *
* @switchdev_port_obj_add: Add an object to port (see switchdev_obj).
*
* @switchdev_port_obj_del: Delete an object from port (see switchdev_obj).
@@ -108,9 +104,15 @@ void *switchdev_trans_item_dequeue(struct switchdev_trans *trans);
struct switchdev_ops {
int (*switchdev_port_attr_get)(struct net_device *dev,
struct switchdev_attr *attr);
+ int (*switchdev_port_attr_pre_set)(struct net_device *dev,
+ struct switchdev_attr *attr,
+ struct switchdev_trans *trans);
int (*switchdev_port_attr_set)(struct net_device *dev,
struct switchdev_attr *attr,
struct switchdev_trans *trans);
+ int (*switchdev_port_obj_pre_add)(struct net_device *dev,
+ struct switchdev_obj *obj,
+ struct switchdev_trans *trans);
int (*switchdev_port_obj_add)(struct net_device *dev,
struct switchdev_obj *obj,
struct switchdev_trans *trans);
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 748cc63..ed773bc 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -241,6 +241,29 @@ static int dsa_bridge_check_vlan_range(struct dsa_switch *ds,
return err == -ENOENT ? 0 : err;
}
+static int dsa_slave_port_vlan_pre_add(struct net_device *dev,
+ struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
+{
+ struct switchdev_obj_vlan *vlan = &obj->u.vlan;
+ struct dsa_slave_priv *p = netdev_priv(dev);
+ struct dsa_switch *ds = p->parent;
+ int err;
+
+ if (!ds->drv->port_vlan_add || !ds->drv->port_pvid_set)
+ return -EOPNOTSUPP;
+
+ /* If the requested port doesn't belong to the same bridge as
+ * the VLAN members, fallback to software VLAN (hopefully).
+ */
+ err = dsa_bridge_check_vlan_range(ds, p->bridge_dev,
+ vlan->vid_begin,
+ vlan->vid_end);
+ if (err)
+ return err;
+ return 0;
+}
+
static int dsa_slave_port_vlan_add(struct net_device *dev,
struct switchdev_obj *obj,
struct switchdev_trans *trans)
@@ -251,35 +274,15 @@ static int dsa_slave_port_vlan_add(struct net_device *dev,
u16 vid;
int err;
- switch (trans->ph) {
- case SWITCHDEV_TRANS_PREPARE:
- if (!ds->drv->port_vlan_add || !ds->drv->port_pvid_set)
- return -EOPNOTSUPP;
-
- /* If the requested port doesn't belong to the same bridge as
- * the VLAN members, fallback to software VLAN (hopefully).
- */
- err = dsa_bridge_check_vlan_range(ds, p->bridge_dev,
- vlan->vid_begin,
- vlan->vid_end);
+ for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
+ err = ds->drv->port_vlan_add(ds, p->port, vid,
+ vlan->flags &
+ BRIDGE_VLAN_INFO_UNTAGGED);
+ if (!err && vlan->flags & BRIDGE_VLAN_INFO_PVID)
+ err = ds->drv->port_pvid_set(ds, p->port, vid);
if (err)
return err;
- break;
- case SWITCHDEV_TRANS_COMMIT:
- for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) {
- err = ds->drv->port_vlan_add(ds, p->port, vid,
- vlan->flags &
- BRIDGE_VLAN_INFO_UNTAGGED);
- if (!err && vlan->flags & BRIDGE_VLAN_INFO_PVID)
- err = ds->drv->port_pvid_set(ds, p->port, vid);
- if (err)
- return err;
- }
- break;
- default:
- return -EOPNOTSUPP;
}
-
return 0;
}
@@ -347,6 +350,16 @@ static int dsa_slave_port_vlan_dump(struct net_device *dev,
return err == -ENOENT ? 0 : err;
}
+static int dsa_slave_port_fdb_pre_add(struct net_device *dev,
+ struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
+{
+ struct dsa_slave_priv *p = netdev_priv(dev);
+ struct dsa_switch *ds = p->parent;
+
+ return ds->drv->port_fdb_add ? 0 : -EOPNOTSUPP;
+}
+
static int dsa_slave_port_fdb_add(struct net_device *dev,
struct switchdev_obj *obj,
struct switchdev_trans *trans)
@@ -354,14 +367,8 @@ static int dsa_slave_port_fdb_add(struct net_device *dev,
struct switchdev_obj_fdb *fdb = &obj->u.fdb;
struct dsa_slave_priv *p = netdev_priv(dev);
struct dsa_switch *ds = p->parent;
- int ret = -EOPNOTSUPP;
-
- if (trans->ph == SWITCHDEV_TRANS_PREPARE)
- ret = ds->drv->port_fdb_add ? 0 : -EOPNOTSUPP;
- else if (trans->ph == SWITCHDEV_TRANS_COMMIT)
- ret = ds->drv->port_fdb_add(ds, p->port, fdb->addr, fdb->vid);
- return ret;
+ return ds->drv->port_fdb_add(ds, p->port, fdb->addr, fdb->vid);
}
static int dsa_slave_port_fdb_del(struct net_device *dev,
@@ -457,17 +464,24 @@ static int dsa_slave_stp_update(struct net_device *dev, u8 state)
return ret;
}
+static int dsa_slave_port_attr_pre_set(struct net_device *dev,
+ struct switchdev_attr *attr,
+ struct switchdev_trans *trans)
+{
+ if (attr->id != SWITCHDEV_ATTR_PORT_STP_STATE)
+ return -EOPNOTSUPP;
+ return 0;
+}
+
static int dsa_slave_port_attr_set(struct net_device *dev,
struct switchdev_attr *attr,
struct switchdev_trans *trans)
{
- int ret = 0;
+ int ret;
switch (attr->id) {
case SWITCHDEV_ATTR_PORT_STP_STATE:
- if (trans->ph == SWITCHDEV_TRANS_COMMIT)
- ret = dsa_slave_stp_update(dev, attr->u.stp_state);
- break;
+ ret = dsa_slave_stp_update(dev, attr->u.stp_state);
default:
ret = -EOPNOTSUPP;
break;
@@ -476,9 +490,9 @@ static int dsa_slave_port_attr_set(struct net_device *dev,
return ret;
}
-static int dsa_slave_port_obj_add(struct net_device *dev,
- struct switchdev_obj *obj,
- struct switchdev_trans *trans)
+static int dsa_slave_port_obj_pre_add(struct net_device *dev,
+ struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
{
int err;
@@ -489,6 +503,27 @@ static int dsa_slave_port_obj_add(struct net_device *dev,
switch (obj->id) {
case SWITCHDEV_OBJ_PORT_FDB:
+ err = dsa_slave_port_fdb_pre_add(dev, obj, trans);
+ break;
+ case SWITCHDEV_OBJ_PORT_VLAN:
+ err = dsa_slave_port_vlan_pre_add(dev, obj, trans);
+ break;
+ default:
+ err = -EOPNOTSUPP;
+ break;
+ }
+
+ return err;
+}
+
+static int dsa_slave_port_obj_add(struct net_device *dev,
+ struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
+{
+ int err;
+
+ switch (obj->id) {
+ case SWITCHDEV_OBJ_PORT_FDB:
err = dsa_slave_port_fdb_add(dev, obj, trans);
break;
case SWITCHDEV_OBJ_PORT_VLAN:
@@ -960,7 +995,9 @@ static const struct net_device_ops dsa_slave_netdev_ops = {
static const struct switchdev_ops dsa_slave_switchdev_ops = {
.switchdev_port_attr_get = dsa_slave_port_attr_get,
+ .switchdev_port_attr_pre_set = dsa_slave_port_attr_pre_set,
.switchdev_port_attr_set = dsa_slave_port_attr_set,
+ .switchdev_port_obj_pre_add = dsa_slave_port_obj_pre_add,
.switchdev_port_obj_add = dsa_slave_port_obj_add,
.switchdev_port_obj_del = dsa_slave_port_obj_del,
.switchdev_port_obj_dump = dsa_slave_port_obj_dump,
diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c
index 82f8bcd..9278643 100644
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -110,6 +110,34 @@ 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_pre_set(struct net_device *dev,
+ struct switchdev_attr *attr,
+ struct switchdev_trans *trans)
+{
+ const struct switchdev_ops *ops = dev->switchdev_ops;
+ struct net_device *lower_dev;
+ struct list_head *iter;
+ int err = -EOPNOTSUPP;
+
+ if (ops && ops->switchdev_port_attr_pre_set)
+ return ops->switchdev_port_attr_pre_set(dev, attr, trans);
+
+ if (attr->flags & SWITCHDEV_F_NO_RECURSE)
+ return err;
+
+ /* Switch device port(s) may be stacked under
+ * bond/team/vlan dev, so recurse down to prepare to set attr on
+ * each port.
+ */
+
+ netdev_for_each_lower_dev(dev, lower_dev, iter) {
+ err = __switchdev_port_attr_pre_set(lower_dev, attr, trans);
+ if (err)
+ break;
+ }
+
+ return err;
+}
static int __switchdev_port_attr_set(struct net_device *dev,
struct switchdev_attr *attr,
struct switchdev_trans *trans)
@@ -216,20 +244,15 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr)
* but should not commit the attr.
*/
- trans.ph = SWITCHDEV_TRANS_PREPARE;
- err = __switchdev_port_attr_set(dev, attr, &trans);
+ err = __switchdev_port_attr_pre_set(dev, attr, &trans);
if (err) {
/* Prepare phase failed: abort the transaction. Any
* resources reserved in the prepare phase are
* 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;
}
@@ -238,7 +261,6 @@ 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;
err = __switchdev_port_attr_set(dev, attr, &trans);
WARN(err, "%s: Commit of attribute (id=%d) failed.\n",
dev->name, attr->id);
@@ -274,6 +296,32 @@ static int __switchdev_port_obj_add(struct net_device *dev,
return err;
}
+static int __switchdev_port_obj_pre_add(struct net_device *dev,
+ struct switchdev_obj *obj,
+ struct switchdev_trans *trans)
+{
+ const struct switchdev_ops *ops = dev->switchdev_ops;
+ struct net_device *lower_dev;
+ struct list_head *iter;
+ int err = -EOPNOTSUPP;
+
+ if (ops && ops->switchdev_port_obj_pre_add)
+ return ops->switchdev_port_obj_pre_add(dev, obj, trans);
+
+ /* Switch device port(s) may be stacked under
+ * bond/team/vlan dev, so recurse down to prepare to add object on
+ * each port.
+ */
+
+ netdev_for_each_lower_dev(dev, lower_dev, iter) {
+ err = __switchdev_port_obj_pre_add(lower_dev, obj, trans);
+ if (err)
+ break;
+ }
+
+ return err;
+}
+
/**
* switchdev_port_obj_add - Add port object
*
@@ -302,20 +350,15 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj)
* but should not commit the obj.
*/
- trans.ph = SWITCHDEV_TRANS_PREPARE;
- err = __switchdev_port_obj_add(dev, obj, &trans);
+ err = __switchdev_port_obj_pre_add(dev, obj, &trans);
if (err) {
/* Prepare phase failed: abort the transaction. Any
* resources reserved in the prepare phase are
* 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;
}
@@ -324,7 +367,6 @@ 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;
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_destroy(&trans);
--
1.9.3
^ permalink raw reply related [flat|nested] 23+ messages in thread
* RE: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-19 12:29 [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Jiri Pirko
` (5 preceding siblings ...)
2015-09-19 12:29 ` [patch net-next RFC 6/6] switchdev: split commit and prepare phase into two callbacks Jiri Pirko
@ 2015-09-19 13:35 ` Rosen, Rami
2015-09-19 16:23 ` Jiri Pirko
2015-09-19 17:46 ` Scott Feldman
2015-09-21 7:23 ` Scott Feldman
8 siblings, 1 reply; 23+ messages in thread
From: Rosen, Rami @ 2015-09-19 13:35 UTC (permalink / raw)
To: Jiri Pirko, netdev@vger.kernel.org
Cc: davem@davemloft.net, idosch@mellanox.com, eladr@mellanox.com,
sfeldma@gmail.com, f.fainelli@gmail.com, linux@roeck-us.net,
vivien.didelot@savoirfairelinux.com
Hi,
>introduce tranction enfra and for pre-commit split
Typo:
Instead "tranction enfra" should be "transaction infrastructure".
Regards,
Rami Rosen
Intel Corporation
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-19 13:35 ` [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Rosen, Rami
@ 2015-09-19 16:23 ` Jiri Pirko
2015-09-19 19:02 ` Vivien Didelot
0 siblings, 1 reply; 23+ messages in thread
From: Jiri Pirko @ 2015-09-19 16:23 UTC (permalink / raw)
To: Rosen, Rami
Cc: netdev@vger.kernel.org, davem@davemloft.net, idosch@mellanox.com,
eladr@mellanox.com, sfeldma@gmail.com, f.fainelli@gmail.com,
linux@roeck-us.net, vivien.didelot@savoirfairelinux.com
Sat, Sep 19, 2015 at 03:35:51PM CEST, rami.rosen@intel.com wrote:
>Hi,
>
>>introduce tranction enfra and for pre-commit split
>
>Typo:
>Instead "tranction enfra" should be "transaction infrastructure".
Will fix. Thanks!
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-19 12:29 [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Jiri Pirko
` (6 preceding siblings ...)
2015-09-19 13:35 ` [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Rosen, Rami
@ 2015-09-19 17:46 ` Scott Feldman
2015-09-20 8:34 ` Jiri Pirko
2015-09-21 7:23 ` Scott Feldman
8 siblings, 1 reply; 23+ messages in thread
From: Scott Feldman @ 2015-09-19 17:46 UTC (permalink / raw)
To: Jiri Pirko
Cc: Netdev, David S. Miller, Ido Schimmel, eladr, Florian Fainelli,
Guenter Roeck, Vivien Didelot
On Sat, Sep 19, 2015 at 5:29 AM, Jiri Pirko <jiri@resnulli.us> wrote:
> Jiri Pirko (6):
> switchdev: rename "trans" to "trans_ph".
> switchdev: introduce transaction infrastructure for attr_set and
> obj_add
> rocker: switch to local transaction phase enum
> switchdev: move transaction phase enum under transaction structure
> rocker: use switchdev transaction queue for allocated memory
> switchdev: split commit and prepare phase into two callbacks
Whew, that's a lot of work! Seems like a good idea to up-level this
for other drivers to share. Let me apply the patches and run my tests
and get back to you.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-19 16:23 ` Jiri Pirko
@ 2015-09-19 19:02 ` Vivien Didelot
2015-09-20 8:33 ` Jiri Pirko
0 siblings, 1 reply; 23+ messages in thread
From: Vivien Didelot @ 2015-09-19 19:02 UTC (permalink / raw)
To: Jiri Pirko
Cc: Rosen, Rami, netdev@vger.kernel.org, davem@davemloft.net,
idosch@mellanox.com, eladr@mellanox.com, sfeldma@gmail.com,
f.fainelli@gmail.com, linux@roeck-us.net
Hi Jiri,
On Sep. Saturday 19 (38) 06:23 PM, Jiri Pirko wrote:
> Sat, Sep 19, 2015 at 03:35:51PM CEST, rami.rosen@intel.com wrote:
> >Hi,
> >
> >>introduce tranction enfra and for pre-commit split
> >
> >Typo:
> >Instead "tranction enfra" should be "transaction infrastructure".
>
> Will fix. Thanks!
Just being picky, there are a couple more typos in:
2/6: s/separatelly/separately/
6/6: s/nore/more/ and s/separete/separate/
Thanks,
-v
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 3/6] rocker: switch to local transaction phase enum
2015-09-19 12:29 ` [patch net-next RFC 3/6] rocker: switch to local transaction phase enum Jiri Pirko
@ 2015-09-19 19:25 ` Vivien Didelot
2015-09-20 8:59 ` Jiri Pirko
0 siblings, 1 reply; 23+ messages in thread
From: Vivien Didelot @ 2015-09-19 19:25 UTC (permalink / raw)
To: Jiri Pirko; +Cc: netdev, davem, idosch, eladr, sfeldma, f.fainelli, linux
Hi Jiri,
On Sep. Saturday 19 (38) 02:29 PM, Jiri Pirko wrote:
> Since switchdev_trans_ph anum is going to be removed, and rocker code is
> way too complicated in this matter to be converted, just introduce local
> enum for transaction phase. Pass it around in local transaction
> structure.
I missed this typo here: s/anum/enum/.
> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
I found the renaming trick is a bit hard to follow. I am wondering if
this patch could be used first and drop patch 1/6?
That way, you can first add the rocker_trans structure and set its ph
member to obj->trans in obj_add/attr_set, then the following patch
(currently 2/6) would just assign it to the new trans parameter.
Thanks,
-v
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-19 19:02 ` Vivien Didelot
@ 2015-09-20 8:33 ` Jiri Pirko
0 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2015-09-20 8:33 UTC (permalink / raw)
To: Vivien Didelot
Cc: Rosen, Rami, netdev@vger.kernel.org, davem@davemloft.net,
idosch@mellanox.com, eladr@mellanox.com, sfeldma@gmail.com,
f.fainelli@gmail.com, linux@roeck-us.net
Sat, Sep 19, 2015 at 09:02:00PM CEST, vivien.didelot@savoirfairelinux.com wrote:
>Hi Jiri,
>
>On Sep. Saturday 19 (38) 06:23 PM, Jiri Pirko wrote:
>> Sat, Sep 19, 2015 at 03:35:51PM CEST, rami.rosen@intel.com wrote:
>> >Hi,
>> >
>> >>introduce tranction enfra and for pre-commit split
>> >
>> >Typo:
>> >Instead "tranction enfra" should be "transaction infrastructure".
>>
>> Will fix. Thanks!
>
>Just being picky, there are a couple more typos in:
>
>2/6: s/separatelly/separately/
>6/6: s/nore/more/ and s/separete/separate/
Will fix. Thanks!
>
>
>Thanks,
>-v
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-19 17:46 ` Scott Feldman
@ 2015-09-20 8:34 ` Jiri Pirko
0 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2015-09-20 8:34 UTC (permalink / raw)
To: Scott Feldman
Cc: Netdev, David S. Miller, Ido Schimmel, eladr, Florian Fainelli,
Guenter Roeck, Vivien Didelot
Sat, Sep 19, 2015 at 07:46:14PM CEST, sfeldma@gmail.com wrote:
>On Sat, Sep 19, 2015 at 5:29 AM, Jiri Pirko <jiri@resnulli.us> wrote:
>> Jiri Pirko (6):
>> switchdev: rename "trans" to "trans_ph".
>> switchdev: introduce transaction infrastructure for attr_set and
>> obj_add
>> rocker: switch to local transaction phase enum
>> switchdev: move transaction phase enum under transaction structure
>> rocker: use switchdev transaction queue for allocated memory
>> switchdev: split commit and prepare phase into two callbacks
>
>Whew, that's a lot of work! Seems like a good idea to up-level this
>for other drivers to share. Let me apply the patches and run my tests
>and get back to you.
Expect some blow-ups. Untested. Will test, fix some spelling issues and
post v1, most probably during Monday.
Thanks.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 3/6] rocker: switch to local transaction phase enum
2015-09-19 19:25 ` Vivien Didelot
@ 2015-09-20 8:59 ` Jiri Pirko
0 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2015-09-20 8:59 UTC (permalink / raw)
To: Vivien Didelot; +Cc: netdev, davem, idosch, eladr, sfeldma, f.fainelli, linux
Sat, Sep 19, 2015 at 09:25:04PM CEST, vivien.didelot@savoirfairelinux.com wrote:
>Hi Jiri,
>
>On Sep. Saturday 19 (38) 02:29 PM, Jiri Pirko wrote:
>> Since switchdev_trans_ph anum is going to be removed, and rocker code is
>> way too complicated in this matter to be converted, just introduce local
>> enum for transaction phase. Pass it around in local transaction
>> structure.
>
>I missed this typo here: s/anum/enum/.
>
>> Signed-off-by: Jiri Pirko <jiri@resnulli.us>
>
>I found the renaming trick is a bit hard to follow. I am wondering if
>this patch could be used first and drop patch 1/6?
>
>That way, you can first add the rocker_trans structure and set its ph
>member to obj->trans in obj_add/attr_set, then the following patch
>(currently 2/6) would just assign it to the new trans parameter.
That could work locally for rocker, but for the rest of the code, I
belive it would not. Anyway, the result would be the same.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-19 12:29 [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Jiri Pirko
` (7 preceding siblings ...)
2015-09-19 17:46 ` Scott Feldman
@ 2015-09-21 7:23 ` Scott Feldman
2015-09-21 8:09 ` Jiri Pirko
8 siblings, 1 reply; 23+ messages in thread
From: Scott Feldman @ 2015-09-21 7:23 UTC (permalink / raw)
To: Jiri Pirko
Cc: Netdev, David S. Miller, Ido Schimmel, eladr, Florian Fainelli,
Guenter Roeck, Vivien Didelot
On Sat, Sep 19, 2015 at 5:29 AM, Jiri Pirko <jiri@resnulli.us> wrote:
> Jiri Pirko (6):
> switchdev: rename "trans" to "trans_ph".
> switchdev: introduce transaction infrastructure for attr_set and
> obj_add
> rocker: switch to local transaction phase enum
> switchdev: move transaction phase enum under transaction structure
> rocker: use switchdev transaction queue for allocated memory
> switchdev: split commit and prepare phase into two callbacks
Patches compile, but first test bombs. Cut-and-paste of dump at end
of this email.
I'm not sure I'm liking this patchset because it looks like a way for
switchdev drivers to easily opt-out of the prepare-commit transaction
model by simply not implementing the *_pre op. I would rather drivers
explicitly handle the PREPARE phase in code, even if that means
skipping it gracefully (in code) with a comment (in code) explaining
why it does not matter for this device/operation. That's what DSA had
done, mostly because it was a retro-fit.
Also, the patchset removes the ABORT callback in case of a rollback
due to a failed PREPARE. We can't make the assumption that it's just
a memory list to destroy on ABORT. The driver, on PREPARE, may have
reserved device space or staged an operation on the device which we'll
need to undo on ABORT.
So we need ABORT back, and we need PREPARE to not be optional, so
what's left list enqueue/dequeue helpers, which I'm not seeing much
value in up-leveling as the driver can do list_add/del itself.
Am I missing something? I didn't see a motivation statement for the
RFC so I'm not sure where you wanted to take this.
-scott
[ 1.998791] BUG: unable to handle kernel NULL pointer dereference
at 0000000000000008
[ 2.000005] IP: [<ffffffffa005a2c5>]
rocker_port_kzalloc.isra.50+0x5/0x10 [rocker]
[ 2.000005] PGD 0
[ 2.000005] Oops: 0000 [#1] SMP
[ 2.000005] Modules linked in: floppy(+) ata_piix(+) libata
rocker(+) virtio_pci(+) virtio_ring virtio scsi_mod
[ 2.000005] CPU: 0 PID: 91 Comm: modprobe Not tainted 4.2.0+ #3
[ 2.000005] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014
[ 2.000005] task: ffff88000f5e0800 ti: ffff88000f5f8000 task.ti:
ffff88000f5f8000
[ 2.000005] RIP: 0010:[<ffffffffa005a2c5>] [<ffffffffa005a2c5>]
rocker_port_kzalloc.isra.50+0x5/0x10 [rocker]
[ 2.000005] RSP: 0018:ffff88000f5fba20 EFLAGS: 00010246
[ 2.000005] RAX: ffff88000f17c050 RBX: ffff88000b400000 RCX: 0000000000000020
[ 2.000005] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
[ 2.000005] RBP: 0000000000000000 R08: 0000000000000000 R09: ffffffffa0058680
[ 2.000005] R10: 0000000000000001 R11: 0000000000009319 R12: 0000000000000000
[ 2.000005] R13: ffff88000f5b7000 R14: ffff88000f5b7840 R15: 0000000000000000
[ 2.000005] FS: 00007fd132237700(0000) GS:ffff88000fc00000(0000)
knlGS:0000000000000000
[ 2.000005] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[ 2.000005] CR2: 0000000000000008 CR3: 000000000f5d5000 CR4: 00000000000006f0
[ 2.000005] Stack:
[ 2.000005] ffffffffa005a32a 0000000000000001 00ff88000f5b7000
ffffffff8175725a
[ 2.000005] ffffffffa0057750 0000000000000000 ffffffffa0058680
000000200000001a
[ 2.000005] ffff88000b400000 0000000000000000 ffff88000ea06000
ffff88000f5b7000
[ 2.000005] Call Trace:
[ 2.000005] [<ffffffffa005a32a>] ? rocker_cmd_exec+0x5a/0x1f0 [rocker]
[ 2.000005] [<ffffffffa0057750>] ?
rocker_cmd_get_port_stats_prep+0x90/0x90 [rocker]
[ 2.000005] [<ffffffffa0058680>] ?
rocker_cmd_get_port_settings_phys_name_proc+0xb0/0xb0 [rocker]
[ 2.000005] [<ffffffffa005e37a>] ? rocker_probe+0xb6a/0xe59 [rocker]
[ 2.000005] [<ffffffff812b6608>] ? local_pci_probe+0x48/0xa0
[ 2.000005] [<ffffffff812b7142>] ? pci_device_probe+0x112/0x130
[ 2.000005] [<ffffffff81384b46>] ? driver_probe_device+0x196/0x2a0
[ 2.000005] [<ffffffff81384c50>] ? driver_probe_device+0x2a0/0x2a0
[ 2.000005] [<ffffffff81384cdd>] ? __driver_attach+0x8d/0x90
[ 2.000005] [<ffffffff81384c50>] ? driver_probe_device+0x2a0/0x2a0
[ 2.000005] [<ffffffff81382f3c>] ? bus_for_each_dev+0x4c/0x80
[ 2.000005] [<ffffffff81384219>] ? bus_add_driver+0x119/0x220
[ 2.000005] [<ffffffffa0065000>] ? 0xffffffffa0065000
[ 2.000005] [<ffffffff813854ba>] ? driver_register+0x5a/0xe0
[ 2.000005] [<ffffffffa0065000>] ? 0xffffffffa0065000
[ 2.000005] [<ffffffffa0065033>] ? rocker_module_init+0x33/0x1000 [rocker]
[ 2.000005] [<ffffffff81002110>] ? do_one_initcall+0x90/0x1e0
[ 2.000005] [<ffffffff81110bd0>] ? do_init_module+0x50/0x1d8
[ 2.000005] [<ffffffff810d632c>] ? load_module+0x1c1c/0x2240
[ 2.000005] [<ffffffff810d33e0>] ? show_initstate+0x50/0x50
[ 2.000005] [<ffffffff810d6a54>] ? SyS_init_module+0x104/0x130
[ 2.000005] [<ffffffff81508ef6>] ? entry_SYSCALL_64_fastpath+0x16/0x75
[ 2.000005] Code: 48 89 c1 48 c7 c2 10 dc 15 81 48 89 c6 e8 e4 0d
4a e1 48 8b 3b e8 1c 1b 4a e1 eb b6 66 2e 0f 1f 84 00 00 00 00 00 48
89 d1 89 f2 <8b> 77 08 e9 73 ff ff ff 0f 1f 00 48 83 ec 68 4c 89 7c 24
60 41
[ 2.000005] RIP [<ffffffffa005a2c5>]
rocker_port_kzalloc.isra.50+0x5/0x10 [rocker]
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-21 7:23 ` Scott Feldman
@ 2015-09-21 8:09 ` Jiri Pirko
2015-09-21 16:34 ` Scott Feldman
2015-09-21 17:13 ` Vivien Didelot
0 siblings, 2 replies; 23+ messages in thread
From: Jiri Pirko @ 2015-09-21 8:09 UTC (permalink / raw)
To: Scott Feldman
Cc: Netdev, David S. Miller, Ido Schimmel, eladr, Florian Fainelli,
Guenter Roeck, Vivien Didelot
Mon, Sep 21, 2015 at 09:23:24AM CEST, sfeldma@gmail.com wrote:
>On Sat, Sep 19, 2015 at 5:29 AM, Jiri Pirko <jiri@resnulli.us> wrote:
>> Jiri Pirko (6):
>> switchdev: rename "trans" to "trans_ph".
>> switchdev: introduce transaction infrastructure for attr_set and
>> obj_add
>> rocker: switch to local transaction phase enum
>> switchdev: move transaction phase enum under transaction structure
>> rocker: use switchdev transaction queue for allocated memory
>> switchdev: split commit and prepare phase into two callbacks
>
>Patches compile, but first test bombs. Cut-and-paste of dump at end
>of this email.
Told you :)
>
>I'm not sure I'm liking this patchset because it looks like a way for
>switchdev drivers to easily opt-out of the prepare-commit transaction
>model by simply not implementing the *_pre op. I would rather drivers
>explicitly handle the PREPARE phase in code, even if that means
>skipping it gracefully (in code) with a comment (in code) explaining
>why it does not matter for this device/operation. That's what DSA had
>done, mostly because it was a retro-fit.
Each driver should handle this inside it. If it does not need prepare
state, it simply does not implement it. That is the same for all cb,
ndos, netdev notifiers, etc. It is much cleaner and nicer to have these as
separate callbacks. Implementing multiple callback in one is just ugly,
sorry.
>
>Also, the patchset removes the ABORT callback in case of a rollback
>due to a failed PREPARE. We can't make the assumption that it's just
>a memory list to destroy on ABORT. The driver, on PREPARE, may have
>reserved device space or staged an operation on the device which we'll
>need to undo on ABORT.
Yep, just register an item with custom destructor, there you can do
whatever. Also, I believe much nicer comparing to current code.
>
>So we need ABORT back, and we need PREPARE to not be optional, so
>what's left list enqueue/dequeue helpers, which I'm not seeing much
>value in up-leveling as the driver can do list_add/del itself.
Why would every driver do it itself, over and over when there can be a
clean infrastructure to do that. Including abort phase. Without the driver
needed to be involved.
>
>Am I missing something? I didn't see a motivation statement for the
>RFC so I'm not sure where you wanted to take this.
I want to make current code much nicer, easier to read and implement in
other drivers. Look at rocker.c and how often there is == PREPARE there.
It's nearly impossible to followthe code, sorry.
My next patchset is to un-mess rocker.c (that freaking ofdpa stuff is everywhere)
>
>-scott
>
>
>
>[ 1.998791] BUG: unable to handle kernel NULL pointer dereference
>at 0000000000000008
>[ 2.000005] IP: [<ffffffffa005a2c5>]
>rocker_port_kzalloc.isra.50+0x5/0x10 [rocker]
>[ 2.000005] PGD 0
>[ 2.000005] Oops: 0000 [#1] SMP
>[ 2.000005] Modules linked in: floppy(+) ata_piix(+) libata
>rocker(+) virtio_pci(+) virtio_ring virtio scsi_mod
>[ 2.000005] CPU: 0 PID: 91 Comm: modprobe Not tainted 4.2.0+ #3
>[ 2.000005] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
>BIOS rel-1.8.2-0-g33fbe13 by qemu-project.org 04/01/2014
>[ 2.000005] task: ffff88000f5e0800 ti: ffff88000f5f8000 task.ti:
>ffff88000f5f8000
>[ 2.000005] RIP: 0010:[<ffffffffa005a2c5>] [<ffffffffa005a2c5>]
>rocker_port_kzalloc.isra.50+0x5/0x10 [rocker]
>[ 2.000005] RSP: 0018:ffff88000f5fba20 EFLAGS: 00010246
>[ 2.000005] RAX: ffff88000f17c050 RBX: ffff88000b400000 RCX: 0000000000000020
>[ 2.000005] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
>[ 2.000005] RBP: 0000000000000000 R08: 0000000000000000 R09: ffffffffa0058680
>[ 2.000005] R10: 0000000000000001 R11: 0000000000009319 R12: 0000000000000000
>[ 2.000005] R13: ffff88000f5b7000 R14: ffff88000f5b7840 R15: 0000000000000000
>[ 2.000005] FS: 00007fd132237700(0000) GS:ffff88000fc00000(0000)
>knlGS:0000000000000000
>[ 2.000005] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
>[ 2.000005] CR2: 0000000000000008 CR3: 000000000f5d5000 CR4: 00000000000006f0
>[ 2.000005] Stack:
>[ 2.000005] ffffffffa005a32a 0000000000000001 00ff88000f5b7000
>ffffffff8175725a
>[ 2.000005] ffffffffa0057750 0000000000000000 ffffffffa0058680
>000000200000001a
>[ 2.000005] ffff88000b400000 0000000000000000 ffff88000ea06000
>ffff88000f5b7000
>[ 2.000005] Call Trace:
>[ 2.000005] [<ffffffffa005a32a>] ? rocker_cmd_exec+0x5a/0x1f0 [rocker]
>[ 2.000005] [<ffffffffa0057750>] ?
>rocker_cmd_get_port_stats_prep+0x90/0x90 [rocker]
>[ 2.000005] [<ffffffffa0058680>] ?
>rocker_cmd_get_port_settings_phys_name_proc+0xb0/0xb0 [rocker]
>[ 2.000005] [<ffffffffa005e37a>] ? rocker_probe+0xb6a/0xe59 [rocker]
>[ 2.000005] [<ffffffff812b6608>] ? local_pci_probe+0x48/0xa0
>[ 2.000005] [<ffffffff812b7142>] ? pci_device_probe+0x112/0x130
>[ 2.000005] [<ffffffff81384b46>] ? driver_probe_device+0x196/0x2a0
>[ 2.000005] [<ffffffff81384c50>] ? driver_probe_device+0x2a0/0x2a0
>[ 2.000005] [<ffffffff81384cdd>] ? __driver_attach+0x8d/0x90
>[ 2.000005] [<ffffffff81384c50>] ? driver_probe_device+0x2a0/0x2a0
>[ 2.000005] [<ffffffff81382f3c>] ? bus_for_each_dev+0x4c/0x80
>[ 2.000005] [<ffffffff81384219>] ? bus_add_driver+0x119/0x220
>[ 2.000005] [<ffffffffa0065000>] ? 0xffffffffa0065000
>[ 2.000005] [<ffffffff813854ba>] ? driver_register+0x5a/0xe0
>[ 2.000005] [<ffffffffa0065000>] ? 0xffffffffa0065000
>[ 2.000005] [<ffffffffa0065033>] ? rocker_module_init+0x33/0x1000 [rocker]
>[ 2.000005] [<ffffffff81002110>] ? do_one_initcall+0x90/0x1e0
>[ 2.000005] [<ffffffff81110bd0>] ? do_init_module+0x50/0x1d8
>[ 2.000005] [<ffffffff810d632c>] ? load_module+0x1c1c/0x2240
>[ 2.000005] [<ffffffff810d33e0>] ? show_initstate+0x50/0x50
>[ 2.000005] [<ffffffff810d6a54>] ? SyS_init_module+0x104/0x130
>[ 2.000005] [<ffffffff81508ef6>] ? entry_SYSCALL_64_fastpath+0x16/0x75
>[ 2.000005] Code: 48 89 c1 48 c7 c2 10 dc 15 81 48 89 c6 e8 e4 0d
>4a e1 48 8b 3b e8 1c 1b 4a e1 eb b6 66 2e 0f 1f 84 00 00 00 00 00 48
>89 d1 89 f2 <8b> 77 08 e9 73 ff ff ff 0f 1f 00 48 83 ec 68 4c 89 7c 24
>60 41
>[ 2.000005] RIP [<ffffffffa005a2c5>]
>rocker_port_kzalloc.isra.50+0x5/0x10 [rocker]
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-21 8:09 ` Jiri Pirko
@ 2015-09-21 16:34 ` Scott Feldman
2015-09-21 19:06 ` Jiri Pirko
2015-09-21 17:13 ` Vivien Didelot
1 sibling, 1 reply; 23+ messages in thread
From: Scott Feldman @ 2015-09-21 16:34 UTC (permalink / raw)
To: Jiri Pirko
Cc: Netdev, David S. Miller, Ido Schimmel, eladr, Florian Fainelli,
Guenter Roeck, Vivien Didelot
On Mon, Sep 21, 2015 at 1:09 AM, Jiri Pirko <jiri@resnulli.us> wrote:
> Mon, Sep 21, 2015 at 09:23:24AM CEST, sfeldma@gmail.com wrote:
>>On Sat, Sep 19, 2015 at 5:29 AM, Jiri Pirko <jiri@resnulli.us> wrote:
>>> Jiri Pirko (6):
>>> switchdev: rename "trans" to "trans_ph".
>>> switchdev: introduce transaction infrastructure for attr_set and
>>> obj_add
>>> rocker: switch to local transaction phase enum
>>> switchdev: move transaction phase enum under transaction structure
>>> rocker: use switchdev transaction queue for allocated memory
>>> switchdev: split commit and prepare phase into two callbacks
>>
>>Patches compile, but first test bombs. Cut-and-paste of dump at end
>>of this email.
>
> Told you :)
>
>
>>
>>I'm not sure I'm liking this patchset because it looks like a way for
>>switchdev drivers to easily opt-out of the prepare-commit transaction
>>model by simply not implementing the *_pre op. I would rather drivers
>>explicitly handle the PREPARE phase in code, even if that means
>>skipping it gracefully (in code) with a comment (in code) explaining
>>why it does not matter for this device/operation. That's what DSA had
>>done, mostly because it was a retro-fit.
>
> Each driver should handle this inside it. If it does not need prepare
> state, it simply does not implement it. That is the same for all cb,
> ndos, netdev notifiers, etc. It is much cleaner and nicer to have these as
> separate callbacks. Implementing multiple callback in one is just ugly,
> sorry.
>
>
>>
>>Also, the patchset removes the ABORT callback in case of a rollback
>>due to a failed PREPARE. We can't make the assumption that it's just
>>a memory list to destroy on ABORT. The driver, on PREPARE, may have
>>reserved device space or staged an operation on the device which we'll
>>need to undo on ABORT.
>
> Yep, just register an item with custom destructor, there you can do
> whatever. Also, I believe much nicer comparing to current code.
>
>
>>
>>So we need ABORT back, and we need PREPARE to not be optional, so
>>what's left list enqueue/dequeue helpers, which I'm not seeing much
>>value in up-leveling as the driver can do list_add/del itself.
>
> Why would every driver do it itself, over and over when there can be a
> clean infrastructure to do that. Including abort phase. Without the driver
> needed to be involved.
>
>
>>
>>Am I missing something? I didn't see a motivation statement for the
>>RFC so I'm not sure where you wanted to take this.
>
> I want to make current code much nicer, easier to read and implement in
> other drivers. Look at rocker.c and how often there is == PREPARE there.
> It's nearly impossible to followthe code, sorry.
You're going to end up duplicate a lot of code and make it easier to
make mistakes. The reason why the == PREPARE checks are there is the
same code is run for both PREPARE and COMMIT, with == PREPARE checks
right at the last moment to avoid a irreversible change, such as
deleting an entry from a table or changing a state variable or bumping
a hardware desc pointer. Otherwise the code paths should be the same
for PREPARE and COMMIT. If you split these, you're going to duplicate
lots of code and one path will deviate from the other over time and
now we've broken the prepare-commit model. We want PREPARE to answer
the question "is it OK to do this?" and COMMIT to do without failure.
Do you have a specific example where you can't follow the code with == PREPARE?
> My next patchset is to un-mess rocker.c (that freaking ofdpa stuff is everywhere)
Rocker implements OF-DPA so it's seems natural that freaking OF-DPA
stuff would be everywhere.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-21 8:09 ` Jiri Pirko
2015-09-21 16:34 ` Scott Feldman
@ 2015-09-21 17:13 ` Vivien Didelot
2015-09-21 18:25 ` Jiri Pirko
1 sibling, 1 reply; 23+ messages in thread
From: Vivien Didelot @ 2015-09-21 17:13 UTC (permalink / raw)
To: Jiri Pirko
Cc: Scott Feldman, Netdev, David S. Miller, Ido Schimmel, eladr,
Florian Fainelli, Guenter Roeck
Hi Jiri, Scott,
On Sep. Monday 21 (39) 10:09 AM, Jiri Pirko wrote:
> Mon, Sep 21, 2015 at 09:23:24AM CEST, sfeldma@gmail.com wrote:
> >On Sat, Sep 19, 2015 at 5:29 AM, Jiri Pirko <jiri@resnulli.us> wrote:
> >> Jiri Pirko (6):
> >> switchdev: rename "trans" to "trans_ph".
> >> switchdev: introduce transaction infrastructure for attr_set and
> >> obj_add
> >> rocker: switch to local transaction phase enum
> >> switchdev: move transaction phase enum under transaction structure
> >> rocker: use switchdev transaction queue for allocated memory
> >> switchdev: split commit and prepare phase into two callbacks
> >
> >Patches compile, but first test bombs. Cut-and-paste of dump at end
> >of this email.
>
> Told you :)
>
>
> >
> >I'm not sure I'm liking this patchset because it looks like a way for
> >switchdev drivers to easily opt-out of the prepare-commit transaction
> >model by simply not implementing the *_pre op. I would rather drivers
> >explicitly handle the PREPARE phase in code, even if that means
> >skipping it gracefully (in code) with a comment (in code) explaining
> >why it does not matter for this device/operation. That's what DSA had
> >done, mostly because it was a retro-fit.
>
> Each driver should handle this inside it. If it does not need prepare
> state, it simply does not implement it. That is the same for all cb,
> ndos, netdev notifiers, etc. It is much cleaner and nicer to have these as
> separate callbacks. Implementing multiple callback in one is just ugly,
> sorry.
This is true, (in DSA) we don't have to implement the prepare phase if
we fully support the feature in hardware.
To give a real example, Marvell switch drivers currently implement all
add/del/dump calls for VLAN FDB (where VID 0 means the port itself). No
prepare phase needed.
Now, I have local patches to enable strict 802.1Q mode in these switches
(all the logic is based on the hardware VLAN table). But it does not use
per-port FDB, so fdb_add with VID 0 doesn't make sense anymore. That's
why we need to push the feature checking down to the drivers in DSA.
I have another pending patch to add .port_fdb_pre_add, where mv88e6xxx
code will return -EOPNOTSUPP if the given VID is 0.
Another example: mv88e6xxx support tagged VLANs, so no hardware check
needed. But the Broadcom Starfighter 2 only supports port-based VLANs
(which is today wrongly implemented through "bridge_join/leave"). By
implementing .port_vlan_pre_add (another pending patch for DSA), the
driver will be able to return -EOPNOTSUPP if !BRIDGE_VLAN_INFO_PVID.
Also, having logic in switchdev drivers to check SWITCHDEV_TRANS_NONE
and SWITCHDEV_TRANS_ABORT is not really nice. Having switchdev handle
the abort phase (calling each destructor) and getting rid of the
SWITCHDEV_TRANS_* flags sounds better to me.
> >Also, the patchset removes the ABORT callback in case of a rollback
> >due to a failed PREPARE. We can't make the assumption that it's just
> >a memory list to destroy on ABORT. The driver, on PREPARE, may have
> >reserved device space or staged an operation on the device which we'll
> >need to undo on ABORT.
>
> Yep, just register an item with custom destructor, there you can do
> whatever. Also, I believe much nicer comparing to current code.
>
>
> >
> >So we need ABORT back, and we need PREPARE to not be optional, so
> >what's left list enqueue/dequeue helpers, which I'm not seeing much
> >value in up-leveling as the driver can do list_add/del itself.
>
> Why would every driver do it itself, over and over when there can be a
> clean infrastructure to do that. Including abort phase. Without the driver
> needed to be involved.
Maybe the term ".destructor" has a too strong meaning to deallocation,
but you can indeed do whatever you need in this function.
> >Am I missing something? I didn't see a motivation statement for the
> >RFC so I'm not sure where you wanted to take this.
>
> I want to make current code much nicer, easier to read and implement in
> other drivers. Look at rocker.c and how often there is == PREPARE there.
> It's nearly impossible to followthe code, sorry.
>
> My next patchset is to un-mess rocker.c (that freaking ofdpa stuff is
> everywhere)
I'm basically for this patchset, but I do have some concerns about the
general switchdev transaction design.
I certainly don't have the perspective that you guys have, so please
tell me if I'm totally wrong. From my point of view (with DSA drivers),
the emphase should be done on asking the hardware if it can handle or
not a given transaction (not simply an hardware feature!).
The driver can handle any allocation and preparation itself, and also
errors can actually occur *during* a commit phase.
Being able to return -EOPNOTSUPP from any add/del/dump function would be
just perfect.
I ideally imagine the following implementation in switchdev drivers:
int foo_port_obj_add(struct net_device *dev, int id, void *obj)
{
struct foo *foo = netdev_priv(dev);
struct switchdev_obj_port_fdb *fdb;
struct switchdev_obj_port_vlan *vlan;
int err;
switch(id) {
case SWITCHDEV_OBJ_PORT_FDB:
fdb = obj;
err = foo_port_fdb_add(foo, fdb);
break;
case SWITCHDEV_OBJ_PORT_VLAN:
vlan = obj;
err = foo_port_vlan_add(foo, vlan);
break;
default:
err = -EOPNOTSUPP;
break;
}
return err;
}
Where foo_port_{fdb,vlan}_add can still return -EOPNOTSUPP depending on
their current state.
Thanks,
-v
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-21 17:13 ` Vivien Didelot
@ 2015-09-21 18:25 ` Jiri Pirko
2015-09-22 1:36 ` Vivien Didelot
0 siblings, 1 reply; 23+ messages in thread
From: Jiri Pirko @ 2015-09-21 18:25 UTC (permalink / raw)
To: Vivien Didelot
Cc: Scott Feldman, Netdev, David S. Miller, Ido Schimmel, eladr,
Florian Fainelli, Guenter Roeck
Mon, Sep 21, 2015 at 07:13:58PM CEST, vivien.didelot@savoirfairelinux.com wrote:
>Hi Jiri, Scott,
>
>On Sep. Monday 21 (39) 10:09 AM, Jiri Pirko wrote:
>> Mon, Sep 21, 2015 at 09:23:24AM CEST, sfeldma@gmail.com wrote:
>> >On Sat, Sep 19, 2015 at 5:29 AM, Jiri Pirko <jiri@resnulli.us> wrote:
>> >> Jiri Pirko (6):
>> >> switchdev: rename "trans" to "trans_ph".
>> >> switchdev: introduce transaction infrastructure for attr_set and
>> >> obj_add
>> >> rocker: switch to local transaction phase enum
>> >> switchdev: move transaction phase enum under transaction structure
>> >> rocker: use switchdev transaction queue for allocated memory
>> >> switchdev: split commit and prepare phase into two callbacks
>> >
>> >Patches compile, but first test bombs. Cut-and-paste of dump at end
>> >of this email.
>>
>> Told you :)
>>
>>
>> >
>> >I'm not sure I'm liking this patchset because it looks like a way for
>> >switchdev drivers to easily opt-out of the prepare-commit transaction
>> >model by simply not implementing the *_pre op. I would rather drivers
>> >explicitly handle the PREPARE phase in code, even if that means
>> >skipping it gracefully (in code) with a comment (in code) explaining
>> >why it does not matter for this device/operation. That's what DSA had
>> >done, mostly because it was a retro-fit.
>>
>> Each driver should handle this inside it. If it does not need prepare
>> state, it simply does not implement it. That is the same for all cb,
>> ndos, netdev notifiers, etc. It is much cleaner and nicer to have these as
>> separate callbacks. Implementing multiple callback in one is just ugly,
>> sorry.
>
>This is true, (in DSA) we don't have to implement the prepare phase if
>we fully support the feature in hardware.
>
>To give a real example, Marvell switch drivers currently implement all
>add/del/dump calls for VLAN FDB (where VID 0 means the port itself). No
>prepare phase needed.
>
>Now, I have local patches to enable strict 802.1Q mode in these switches
>(all the logic is based on the hardware VLAN table). But it does not use
>per-port FDB, so fdb_add with VID 0 doesn't make sense anymore. That's
>why we need to push the feature checking down to the drivers in DSA.
>
>I have another pending patch to add .port_fdb_pre_add, where mv88e6xxx
>code will return -EOPNOTSUPP if the given VID is 0.
>
>Another example: mv88e6xxx support tagged VLANs, so no hardware check
>needed. But the Broadcom Starfighter 2 only supports port-based VLANs
>(which is today wrongly implemented through "bridge_join/leave"). By
>implementing .port_vlan_pre_add (another pending patch for DSA), the
>driver will be able to return -EOPNOTSUPP if !BRIDGE_VLAN_INFO_PVID.
>
>Also, having logic in switchdev drivers to check SWITCHDEV_TRANS_NONE
>and SWITCHDEV_TRANS_ABORT is not really nice. Having switchdev handle
>the abort phase (calling each destructor) and getting rid of the
>SWITCHDEV_TRANS_* flags sounds better to me.
Agree, if pre/commit is going to be in one function, we should have
only prepare/commit enums. It can be carried around as a single bool
value in switchdev_trans structure. Will include that in my transaction
patchset.
>
>> >Also, the patchset removes the ABORT callback in case of a rollback
>> >due to a failed PREPARE. We can't make the assumption that it's just
>> >a memory list to destroy on ABORT. The driver, on PREPARE, may have
>> >reserved device space or staged an operation on the device which we'll
>> >need to undo on ABORT.
>>
>> Yep, just register an item with custom destructor, there you can do
>> whatever. Also, I believe much nicer comparing to current code.
>>
>>
>> >
>> >So we need ABORT back, and we need PREPARE to not be optional, so
>> >what's left list enqueue/dequeue helpers, which I'm not seeing much
>> >value in up-leveling as the driver can do list_add/del itself.
>>
>> Why would every driver do it itself, over and over when there can be a
>> clean infrastructure to do that. Including abort phase. Without the driver
>> needed to be involved.
>
>Maybe the term ".destructor" has a too strong meaning to deallocation,
>but you can indeed do whatever you need in this function.
It is a destructor. Don't know about a better name, suggestions?
>
>> >Am I missing something? I didn't see a motivation statement for the
>> >RFC so I'm not sure where you wanted to take this.
>>
>> I want to make current code much nicer, easier to read and implement in
>> other drivers. Look at rocker.c and how often there is == PREPARE there.
>> It's nearly impossible to followthe code, sorry.
>>
>> My next patchset is to un-mess rocker.c (that freaking ofdpa stuff is
>> everywhere)
>
>I'm basically for this patchset, but I do have some concerns about the
>general switchdev transaction design.
>
>I certainly don't have the perspective that you guys have, so please
>tell me if I'm totally wrong. From my point of view (with DSA drivers),
>the emphase should be done on asking the hardware if it can handle or
>not a given transaction (not simply an hardware feature!).
>
>The driver can handle any allocation and preparation itself, and also
>errors can actually occur *during* a commit phase.
But during commit phase, the odds that error is going to happen is a lot
smaller. Prepare phase should resolve all common fails like memory
allocations and resource limitation checks.
>
>Being able to return -EOPNOTSUPP from any add/del/dump function would be
>just perfect.
Looking at this, I agree that for switchdev_port_obj_add and
switchdev_port_attr_set if would make more sense to return 0 in case of
hw does not actuall support. Callers check for -EOPNOTSUP and treat
that as 0 anyway. Feel free to send a patch for this.
>
>I ideally imagine the following implementation in switchdev drivers:
>
> int foo_port_obj_add(struct net_device *dev, int id, void *obj)
> {
> struct foo *foo = netdev_priv(dev);
> struct switchdev_obj_port_fdb *fdb;
> struct switchdev_obj_port_vlan *vlan;
> int err;
>
> switch(id) {
> case SWITCHDEV_OBJ_PORT_FDB:
> fdb = obj;
> err = foo_port_fdb_add(foo, fdb);
> break;
> case SWITCHDEV_OBJ_PORT_VLAN:
> vlan = obj;
> err = foo_port_vlan_add(foo, vlan);
> break;
> default:
> err = -EOPNOTSUPP;
> break;
> }
>
> return err;
> }
>
>Where foo_port_{fdb,vlan}_add can still return -EOPNOTSUPP depending on
>their current state.
Yep, seems correct.
>
>Thanks,
>-v
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-21 16:34 ` Scott Feldman
@ 2015-09-21 19:06 ` Jiri Pirko
0 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2015-09-21 19:06 UTC (permalink / raw)
To: Scott Feldman
Cc: Netdev, David S. Miller, Ido Schimmel, eladr, Florian Fainelli,
Guenter Roeck, Vivien Didelot
Mon, Sep 21, 2015 at 06:34:33PM CEST, sfeldma@gmail.com wrote:
>On Mon, Sep 21, 2015 at 1:09 AM, Jiri Pirko <jiri@resnulli.us> wrote:
>> Mon, Sep 21, 2015 at 09:23:24AM CEST, sfeldma@gmail.com wrote:
>>>On Sat, Sep 19, 2015 at 5:29 AM, Jiri Pirko <jiri@resnulli.us> wrote:
>>>> Jiri Pirko (6):
>>>> switchdev: rename "trans" to "trans_ph".
>>>> switchdev: introduce transaction infrastructure for attr_set and
>>>> obj_add
>>>> rocker: switch to local transaction phase enum
>>>> switchdev: move transaction phase enum under transaction structure
>>>> rocker: use switchdev transaction queue for allocated memory
>>>> switchdev: split commit and prepare phase into two callbacks
>>>
>>>Patches compile, but first test bombs. Cut-and-paste of dump at end
>>>of this email.
>>
>> Told you :)
>>
>>
>>>
>>>I'm not sure I'm liking this patchset because it looks like a way for
>>>switchdev drivers to easily opt-out of the prepare-commit transaction
>>>model by simply not implementing the *_pre op. I would rather drivers
>>>explicitly handle the PREPARE phase in code, even if that means
>>>skipping it gracefully (in code) with a comment (in code) explaining
>>>why it does not matter for this device/operation. That's what DSA had
>>>done, mostly because it was a retro-fit.
>>
>> Each driver should handle this inside it. If it does not need prepare
>> state, it simply does not implement it. That is the same for all cb,
>> ndos, netdev notifiers, etc. It is much cleaner and nicer to have these as
>> separate callbacks. Implementing multiple callback in one is just ugly,
>> sorry.
>>
>>
>>>
>>>Also, the patchset removes the ABORT callback in case of a rollback
>>>due to a failed PREPARE. We can't make the assumption that it's just
>>>a memory list to destroy on ABORT. The driver, on PREPARE, may have
>>>reserved device space or staged an operation on the device which we'll
>>>need to undo on ABORT.
>>
>> Yep, just register an item with custom destructor, there you can do
>> whatever. Also, I believe much nicer comparing to current code.
>>
>>
>>>
>>>So we need ABORT back, and we need PREPARE to not be optional, so
>>>what's left list enqueue/dequeue helpers, which I'm not seeing much
>>>value in up-leveling as the driver can do list_add/del itself.
>>
>> Why would every driver do it itself, over and over when there can be a
>> clean infrastructure to do that. Including abort phase. Without the driver
>> needed to be involved.
>>
>>
>>>
>>>Am I missing something? I didn't see a motivation statement for the
>>>RFC so I'm not sure where you wanted to take this.
>>
>> I want to make current code much nicer, easier to read and implement in
>> other drivers. Look at rocker.c and how often there is == PREPARE there.
>> It's nearly impossible to followthe code, sorry.
>
>You're going to end up duplicate a lot of code and make it easier to
>make mistakes. The reason why the == PREPARE checks are there is the
>same code is run for both PREPARE and COMMIT, with == PREPARE checks
>right at the last moment to avoid a irreversible change, such as
>deleting an entry from a table or changing a state variable or bumping
>a hardware desc pointer. Otherwise the code paths should be the same
>for PREPARE and COMMIT. If you split these, you're going to duplicate
>lots of code and one path will deviate from the other over time and
>now we've broken the prepare-commit model. We want PREPARE to answer
>the question "is it OK to do this?" and COMMIT to do without failure.
Okay, I'll leave the last patch out for now. Let's see what the
future brings :)
I really don't like "NONE" phase, does not make sense for switchdev code
and it is just a hack for rocker. So I will kick it out from switchdev
anyway.
"ABORT" phase also does not allign to what you say about
one-code-two-passes and I think that my patchset is actually handling
abort nicely.
That leaves only "PREPARE" and "COMMIT"
Makes sense?
>
>Do you have a specific example where you can't follow the code with == PREPARE?
>
>> My next patchset is to un-mess rocker.c (that freaking ofdpa stuff is everywhere)
>
>Rocker implements OF-DPA so it's seems natural that freaking OF-DPA
>stuff would be everywhere.
Well, no. It is only one of many possible worlds. In qemu, the split is
done nicely. However in kernel, the ofdpa stuff is squashed to
the generic rocker stuff. I have a patchset for splitting
that under construction for some time. This week I have some time
allocated for that so I hopefully will send the patchset
this Thursday (fingers crossed).
Thanks for review!
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-21 18:25 ` Jiri Pirko
@ 2015-09-22 1:36 ` Vivien Didelot
2015-09-22 6:12 ` Jiri Pirko
0 siblings, 1 reply; 23+ messages in thread
From: Vivien Didelot @ 2015-09-22 1:36 UTC (permalink / raw)
To: Jiri Pirko
Cc: Scott Feldman, Netdev, David S. Miller, Ido Schimmel, eladr,
Florian Fainelli, Guenter Roeck
Hi Jiri,
On Sep. Monday 21 (39) 08:25 PM, Jiri Pirko wrote:
> Mon, Sep 21, 2015 at 07:13:58PM CEST, vivien.didelot@savoirfairelinux.com wrote:
> >Hi Jiri, Scott,
> >
> >On Sep. Monday 21 (39) 10:09 AM, Jiri Pirko wrote:
> >> Mon, Sep 21, 2015 at 09:23:24AM CEST, sfeldma@gmail.com wrote:
> >> >On Sat, Sep 19, 2015 at 5:29 AM, Jiri Pirko <jiri@resnulli.us> wrote:
> >> >> Jiri Pirko (6):
> >> >> switchdev: rename "trans" to "trans_ph".
> >> >> switchdev: introduce transaction infrastructure for attr_set and
> >> >> obj_add
> >> >> rocker: switch to local transaction phase enum
> >> >> switchdev: move transaction phase enum under transaction structure
> >> >> rocker: use switchdev transaction queue for allocated memory
> >> >> switchdev: split commit and prepare phase into two callbacks
> >> >
> >> >Patches compile, but first test bombs. Cut-and-paste of dump at end
> >> >of this email.
> >>
> >> Told you :)
> >>
> >>
> >> >
> >> >I'm not sure I'm liking this patchset because it looks like a way for
> >> >switchdev drivers to easily opt-out of the prepare-commit transaction
> >> >model by simply not implementing the *_pre op. I would rather drivers
> >> >explicitly handle the PREPARE phase in code, even if that means
> >> >skipping it gracefully (in code) with a comment (in code) explaining
> >> >why it does not matter for this device/operation. That's what DSA had
> >> >done, mostly because it was a retro-fit.
> >>
> >> Each driver should handle this inside it. If it does not need prepare
> >> state, it simply does not implement it. That is the same for all cb,
> >> ndos, netdev notifiers, etc. It is much cleaner and nicer to have these as
> >> separate callbacks. Implementing multiple callback in one is just ugly,
> >> sorry.
> >
> >This is true, (in DSA) we don't have to implement the prepare phase if
> >we fully support the feature in hardware.
> >
> >To give a real example, Marvell switch drivers currently implement all
> >add/del/dump calls for VLAN FDB (where VID 0 means the port itself). No
> >prepare phase needed.
> >
> >Now, I have local patches to enable strict 802.1Q mode in these switches
> >(all the logic is based on the hardware VLAN table). But it does not use
> >per-port FDB, so fdb_add with VID 0 doesn't make sense anymore. That's
> >why we need to push the feature checking down to the drivers in DSA.
> >
> >I have another pending patch to add .port_fdb_pre_add, where mv88e6xxx
> >code will return -EOPNOTSUPP if the given VID is 0.
> >
> >Another example: mv88e6xxx support tagged VLANs, so no hardware check
> >needed. But the Broadcom Starfighter 2 only supports port-based VLANs
> >(which is today wrongly implemented through "bridge_join/leave"). By
> >implementing .port_vlan_pre_add (another pending patch for DSA), the
> >driver will be able to return -EOPNOTSUPP if !BRIDGE_VLAN_INFO_PVID.
> >
> >Also, having logic in switchdev drivers to check SWITCHDEV_TRANS_NONE
> >and SWITCHDEV_TRANS_ABORT is not really nice. Having switchdev handle
> >the abort phase (calling each destructor) and getting rid of the
> >SWITCHDEV_TRANS_* flags sounds better to me.
>
> Agree, if pre/commit is going to be in one function, we should have
> only prepare/commit enums. It can be carried around as a single bool
> value in switchdev_trans structure. Will include that in my transaction
> patchset.
>
>
> >
> >> >Also, the patchset removes the ABORT callback in case of a rollback
> >> >due to a failed PREPARE. We can't make the assumption that it's just
> >> >a memory list to destroy on ABORT. The driver, on PREPARE, may have
> >> >reserved device space or staged an operation on the device which we'll
> >> >need to undo on ABORT.
> >>
> >> Yep, just register an item with custom destructor, there you can do
> >> whatever. Also, I believe much nicer comparing to current code.
> >>
> >>
> >> >
> >> >So we need ABORT back, and we need PREPARE to not be optional, so
> >> >what's left list enqueue/dequeue helpers, which I'm not seeing much
> >> >value in up-leveling as the driver can do list_add/del itself.
> >>
> >> Why would every driver do it itself, over and over when there can be a
> >> clean infrastructure to do that. Including abort phase. Without the driver
> >> needed to be involved.
> >
> >Maybe the term ".destructor" has a too strong meaning to deallocation,
> >but you can indeed do whatever you need in this function.
>
> It is a destructor. Don't know about a better name, suggestions?
Nope, I'm personally fine with this term.
> >
> >> >Am I missing something? I didn't see a motivation statement for the
> >> >RFC so I'm not sure where you wanted to take this.
> >>
> >> I want to make current code much nicer, easier to read and implement in
> >> other drivers. Look at rocker.c and how often there is == PREPARE there.
> >> It's nearly impossible to followthe code, sorry.
> >>
> >> My next patchset is to un-mess rocker.c (that freaking ofdpa stuff is
> >> everywhere)
> >
> >I'm basically for this patchset, but I do have some concerns about the
> >general switchdev transaction design.
> >
> >I certainly don't have the perspective that you guys have, so please
> >tell me if I'm totally wrong. From my point of view (with DSA drivers),
> >the emphase should be done on asking the hardware if it can handle or
> >not a given transaction (not simply an hardware feature!).
> >
> >The driver can handle any allocation and preparation itself, and also
> >errors can actually occur *during* a commit phase.
>
> But during commit phase, the odds that error is going to happen is a lot
> smaller. Prepare phase should resolve all common fails like memory
> allocations and resource limitation checks.
With mv88e6xxx, we do MDIO calls in the commit phase that we don't do in
the prepare phase, and they can actually fail.
switchdev assumes that no error can occur during a commit, this is
wrong. It also triggers a WARN() in that case, which is bad IMHO.
The prepare phase tries to help drivers with allocation and partial
checking, while this can be nice, it is not even switch-specific. That
can totally be done at the driver level, if it needs to.
I'm really trying to understand what is the real value behind this two
phases model, but looking at really use cases like DSA, I can't see one.
Maybe DSA is a specific case. Do you have a concrete example of
situation where a switch or driver would really need this pre-phase?
>
> >
> >Being able to return -EOPNOTSUPP from any add/del/dump function would be
> >just perfect.
>
> Looking at this, I agree that for switchdev_port_obj_add and
> switchdev_port_attr_set if would make more sense to return 0 in case of
> hw does not actuall support. Callers check for -EOPNOTSUP and treat
> that as 0 anyway. Feel free to send a patch for this.
I am not sure to understand. Are you suggesting to make the prepare
phase optional? Something like this:
--- a/net/switchdev/switchdev.c
+++ b/net/switchdev/switchdev.c
@@ -186,7 +186,7 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr)
attr->trans = SWITCHDEV_TRANS_COMMIT;
err = __switchdev_port_attr_set(dev, attr);
- WARN(err, "%s: Commit of attribute (id=%d) failed.\n",
+ WARN(err != -EOPNOTSUPP, "%s: Commit of attribute (id=%d) failed.\n",
dev->name, attr->id);
return err;
@@ -266,7 +266,8 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj)
obj->trans = SWITCHDEV_TRANS_COMMIT;
err = __switchdev_port_obj_add(dev, obj);
- WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id);
+ WARN(err != -EOPNOTSUPP, "%s: Commit of object (id=%d) failed.\n",
+ dev->name, obj->id);
return err;
}
If yes, that would allow simple driver like DSA to return 0 in the
prepare phrase (to basically ignore it) and let the drivers eventually
return -EOPNOTSUPP in the commit phase, which is way more simple.
But then, is there really a need for the prepare phase again?
Thanks,
-v
>
>
> >
> >I ideally imagine the following implementation in switchdev drivers:
> >
> > int foo_port_obj_add(struct net_device *dev, int id, void *obj)
> > {
> > struct foo *foo = netdev_priv(dev);
> > struct switchdev_obj_port_fdb *fdb;
> > struct switchdev_obj_port_vlan *vlan;
> > int err;
> >
> > switch(id) {
> > case SWITCHDEV_OBJ_PORT_FDB:
> > fdb = obj;
> > err = foo_port_fdb_add(foo, fdb);
> > break;
> > case SWITCHDEV_OBJ_PORT_VLAN:
> > vlan = obj;
> > err = foo_port_vlan_add(foo, vlan);
> > break;
> > default:
> > err = -EOPNOTSUPP;
> > break;
> > }
> >
> > return err;
> > }
> >
> >Where foo_port_{fdb,vlan}_add can still return -EOPNOTSUPP depending on
> >their current state.
>
> Yep, seems correct.
Thanks,
-v
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split
2015-09-22 1:36 ` Vivien Didelot
@ 2015-09-22 6:12 ` Jiri Pirko
0 siblings, 0 replies; 23+ messages in thread
From: Jiri Pirko @ 2015-09-22 6:12 UTC (permalink / raw)
To: Vivien Didelot
Cc: Scott Feldman, Netdev, David S. Miller, Ido Schimmel, eladr,
Florian Fainelli, Guenter Roeck
Tue, Sep 22, 2015 at 03:36:28AM CEST, vivien.didelot@savoirfairelinux.com wrote:
>Hi Jiri,
>
>On Sep. Monday 21 (39) 08:25 PM, Jiri Pirko wrote:
>> Mon, Sep 21, 2015 at 07:13:58PM CEST, vivien.didelot@savoirfairelinux.com wrote:
>> >Hi Jiri, Scott,
>> >
>> >On Sep. Monday 21 (39) 10:09 AM, Jiri Pirko wrote:
>> >> Mon, Sep 21, 2015 at 09:23:24AM CEST, sfeldma@gmail.com wrote:
>> >> >On Sat, Sep 19, 2015 at 5:29 AM, Jiri Pirko <jiri@resnulli.us> wrote:
>> >> >> Jiri Pirko (6):
>> >> >> switchdev: rename "trans" to "trans_ph".
>> >> >> switchdev: introduce transaction infrastructure for attr_set and
>> >> >> obj_add
>> >> >> rocker: switch to local transaction phase enum
>> >> >> switchdev: move transaction phase enum under transaction structure
>> >> >> rocker: use switchdev transaction queue for allocated memory
>> >> >> switchdev: split commit and prepare phase into two callbacks
>> >> >
>> >> >Patches compile, but first test bombs. Cut-and-paste of dump at end
>> >> >of this email.
>> >>
>> >> Told you :)
>> >>
>> >>
>> >> >
>> >> >I'm not sure I'm liking this patchset because it looks like a way for
>> >> >switchdev drivers to easily opt-out of the prepare-commit transaction
>> >> >model by simply not implementing the *_pre op. I would rather drivers
>> >> >explicitly handle the PREPARE phase in code, even if that means
>> >> >skipping it gracefully (in code) with a comment (in code) explaining
>> >> >why it does not matter for this device/operation. That's what DSA had
>> >> >done, mostly because it was a retro-fit.
>> >>
>> >> Each driver should handle this inside it. If it does not need prepare
>> >> state, it simply does not implement it. That is the same for all cb,
>> >> ndos, netdev notifiers, etc. It is much cleaner and nicer to have these as
>> >> separate callbacks. Implementing multiple callback in one is just ugly,
>> >> sorry.
>> >
>> >This is true, (in DSA) we don't have to implement the prepare phase if
>> >we fully support the feature in hardware.
>> >
>> >To give a real example, Marvell switch drivers currently implement all
>> >add/del/dump calls for VLAN FDB (where VID 0 means the port itself). No
>> >prepare phase needed.
>> >
>> >Now, I have local patches to enable strict 802.1Q mode in these switches
>> >(all the logic is based on the hardware VLAN table). But it does not use
>> >per-port FDB, so fdb_add with VID 0 doesn't make sense anymore. That's
>> >why we need to push the feature checking down to the drivers in DSA.
>> >
>> >I have another pending patch to add .port_fdb_pre_add, where mv88e6xxx
>> >code will return -EOPNOTSUPP if the given VID is 0.
>> >
>> >Another example: mv88e6xxx support tagged VLANs, so no hardware check
>> >needed. But the Broadcom Starfighter 2 only supports port-based VLANs
>> >(which is today wrongly implemented through "bridge_join/leave"). By
>> >implementing .port_vlan_pre_add (another pending patch for DSA), the
>> >driver will be able to return -EOPNOTSUPP if !BRIDGE_VLAN_INFO_PVID.
>> >
>> >Also, having logic in switchdev drivers to check SWITCHDEV_TRANS_NONE
>> >and SWITCHDEV_TRANS_ABORT is not really nice. Having switchdev handle
>> >the abort phase (calling each destructor) and getting rid of the
>> >SWITCHDEV_TRANS_* flags sounds better to me.
>>
>> Agree, if pre/commit is going to be in one function, we should have
>> only prepare/commit enums. It can be carried around as a single bool
>> value in switchdev_trans structure. Will include that in my transaction
>> patchset.
>>
>>
>> >
>> >> >Also, the patchset removes the ABORT callback in case of a rollback
>> >> >due to a failed PREPARE. We can't make the assumption that it's just
>> >> >a memory list to destroy on ABORT. The driver, on PREPARE, may have
>> >> >reserved device space or staged an operation on the device which we'll
>> >> >need to undo on ABORT.
>> >>
>> >> Yep, just register an item with custom destructor, there you can do
>> >> whatever. Also, I believe much nicer comparing to current code.
>> >>
>> >>
>> >> >
>> >> >So we need ABORT back, and we need PREPARE to not be optional, so
>> >> >what's left list enqueue/dequeue helpers, which I'm not seeing much
>> >> >value in up-leveling as the driver can do list_add/del itself.
>> >>
>> >> Why would every driver do it itself, over and over when there can be a
>> >> clean infrastructure to do that. Including abort phase. Without the driver
>> >> needed to be involved.
>> >
>> >Maybe the term ".destructor" has a too strong meaning to deallocation,
>> >but you can indeed do whatever you need in this function.
>>
>> It is a destructor. Don't know about a better name, suggestions?
>
>Nope, I'm personally fine with this term.
>
>> >
>> >> >Am I missing something? I didn't see a motivation statement for the
>> >> >RFC so I'm not sure where you wanted to take this.
>> >>
>> >> I want to make current code much nicer, easier to read and implement in
>> >> other drivers. Look at rocker.c and how often there is == PREPARE there.
>> >> It's nearly impossible to followthe code, sorry.
>> >>
>> >> My next patchset is to un-mess rocker.c (that freaking ofdpa stuff is
>> >> everywhere)
>> >
>> >I'm basically for this patchset, but I do have some concerns about the
>> >general switchdev transaction design.
>> >
>> >I certainly don't have the perspective that you guys have, so please
>> >tell me if I'm totally wrong. From my point of view (with DSA drivers),
>> >the emphase should be done on asking the hardware if it can handle or
>> >not a given transaction (not simply an hardware feature!).
>> >
>> >The driver can handle any allocation and preparation itself, and also
>> >errors can actually occur *during* a commit phase.
>>
>> But during commit phase, the odds that error is going to happen is a lot
>> smaller. Prepare phase should resolve all common fails like memory
>> allocations and resource limitation checks.
>
>With mv88e6xxx, we do MDIO calls in the commit phase that we don't do in
>the prepare phase, and they can actually fail.
>
>switchdev assumes that no error can occur during a commit, this is
>wrong. It also triggers a WARN() in that case, which is bad IMHO.
>
>The prepare phase tries to help drivers with allocation and partial
>checking, while this can be nice, it is not even switch-specific. That
>can totally be done at the driver level, if it needs to.
>
>I'm really trying to understand what is the real value behind this two
>phases model, but looking at really use cases like DSA, I can't see one.
>
>Maybe DSA is a specific case. Do you have a concrete example of
>situation where a switch or driver would really need this pre-phase?
>
>>
>> >
>> >Being able to return -EOPNOTSUPP from any add/del/dump function would be
>> >just perfect.
>>
>> Looking at this, I agree that for switchdev_port_obj_add and
>> switchdev_port_attr_set if would make more sense to return 0 in case of
>> hw does not actuall support. Callers check for -EOPNOTSUP and treat
>> that as 0 anyway. Feel free to send a patch for this.
>
>I am not sure to understand. Are you suggesting to make the prepare
>phase optional? Something like this:
>
>--- a/net/switchdev/switchdev.c
>+++ b/net/switchdev/switchdev.c
>@@ -186,7 +186,7 @@ int switchdev_port_attr_set(struct net_device *dev, struct switchdev_attr *attr)
>
> attr->trans = SWITCHDEV_TRANS_COMMIT;
> err = __switchdev_port_attr_set(dev, attr);
>- WARN(err, "%s: Commit of attribute (id=%d) failed.\n",
>+ WARN(err != -EOPNOTSUPP, "%s: Commit of attribute (id=%d) failed.\n",
> dev->name, attr->id);
>
> return err;
>@@ -266,7 +266,8 @@ int switchdev_port_obj_add(struct net_device *dev, struct switchdev_obj *obj)
>
> obj->trans = SWITCHDEV_TRANS_COMMIT;
> err = __switchdev_port_obj_add(dev, obj);
>- WARN(err, "%s: Commit of object (id=%d) failed.\n", dev->name, obj->id);
>+ WARN(err != -EOPNOTSUPP, "%s: Commit of object (id=%d) failed.\n",
>+ dev->name, obj->id);
>
> return err;
> }
>
>
>If yes, that would allow simple driver like DSA to return 0 in the
>prepare phrase (to basically ignore it) and let the drivers eventually
>return -EOPNOTSUPP in the commit phase, which is way more simple.
>
>But then, is there really a need for the prepare phase again?
I have very similar doubts about prepare-commit phases as you have.
Scott, DaveM, any comments?
^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2015-09-22 6:12 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-19 12:29 [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 1/6] switchdev: rename "trans" to "trans_ph" Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 2/6] switchdev: introduce transaction infrastructure for attr_set and obj_add Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 3/6] rocker: switch to local transaction phase enum Jiri Pirko
2015-09-19 19:25 ` Vivien Didelot
2015-09-20 8:59 ` Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 4/6] switchdev: move transaction phase enum under transaction structure Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 5/6] rocker: use switchdev transaction queue for allocated memory Jiri Pirko
2015-09-19 12:29 ` [patch net-next RFC 6/6] switchdev: split commit and prepare phase into two callbacks Jiri Pirko
2015-09-19 13:35 ` [patch net-next RFC 0/6] switchdev: introduce tranction enfra and for pre-commit split Rosen, Rami
2015-09-19 16:23 ` Jiri Pirko
2015-09-19 19:02 ` Vivien Didelot
2015-09-20 8:33 ` Jiri Pirko
2015-09-19 17:46 ` Scott Feldman
2015-09-20 8:34 ` Jiri Pirko
2015-09-21 7:23 ` Scott Feldman
2015-09-21 8:09 ` Jiri Pirko
2015-09-21 16:34 ` Scott Feldman
2015-09-21 19:06 ` Jiri Pirko
2015-09-21 17:13 ` Vivien Didelot
2015-09-21 18:25 ` Jiri Pirko
2015-09-22 1:36 ` Vivien Didelot
2015-09-22 6:12 ` Jiri Pirko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).