summaryrefslogtreecommitdiff
path: root/include/linux/if_team.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/if_team.h')
-rw-r--r--include/linux/if_team.h69
1 files changed, 39 insertions, 30 deletions
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index cdc684e04a2f..3d21e06fda67 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -27,10 +27,11 @@ struct team;
struct team_port {
struct net_device *dev;
- struct hlist_node hlist; /* node in enabled ports hash list */
+ struct hlist_node tx_hlist; /* node in tx-enabled ports hash list */
struct list_head list; /* node in ordinary list */
struct team *team;
- int index; /* index of enabled port. If disabled, it's set to -1 */
+ int tx_index; /* index of tx enabled port. If disabled, -1 */
+ bool rx_enabled;
bool linkup; /* either state.linkup or user.linkup */
@@ -75,14 +76,24 @@ static inline struct team_port *team_port_get_rcu(const struct net_device *dev)
return rcu_dereference(dev->rx_handler_data);
}
+static inline bool team_port_rx_enabled(struct team_port *port)
+{
+ return READ_ONCE(port->rx_enabled);
+}
+
+static inline bool team_port_tx_enabled(struct team_port *port)
+{
+ return READ_ONCE(port->tx_index) != -1;
+}
+
static inline bool team_port_enabled(struct team_port *port)
{
- return port->index != -1;
+ return team_port_rx_enabled(port) && team_port_tx_enabled(port);
}
static inline bool team_port_txable(struct team_port *port)
{
- return port->linkup && team_port_enabled(port);
+ return port->linkup && team_port_tx_enabled(port);
}
static inline bool team_port_dev_txable(const struct net_device *port_dev)
@@ -121,8 +132,7 @@ struct team_mode_ops {
int (*port_enter)(struct team *team, struct team_port *port);
void (*port_leave)(struct team *team, struct team_port *port);
void (*port_change_dev_addr)(struct team *team, struct team_port *port);
- void (*port_enabled)(struct team *team, struct team_port *port);
- void (*port_disabled)(struct team *team, struct team_port *port);
+ void (*port_tx_disabled)(struct team *team, struct team_port *port);
};
extern int team_modeop_port_enter(struct team *team, struct team_port *port);
@@ -186,18 +196,16 @@ struct team_mode {
#define TEAM_MODE_PRIV_SIZE (sizeof(long) * TEAM_MODE_PRIV_LONGS)
struct team {
- struct net_device *dev; /* associated netdevice */
struct team_pcpu_stats __percpu *pcpu_stats;
const struct header_ops *header_ops_cache;
- struct mutex lock; /* used for overall locking, e.g. port lists write */
-
/*
- * List of enabled ports and their count
+ * List of tx-enabled ports and counts of rx and tx-enabled ports.
*/
- int en_port_count;
- struct hlist_head en_port_hlist[TEAM_PORT_HASHENTRIES];
+ int tx_en_port_count;
+ int rx_en_port_count;
+ struct hlist_head tx_en_port_hlist[TEAM_PORT_HASHENTRIES];
struct list_head port_list; /* list of all ports */
@@ -223,7 +231,6 @@ struct team {
atomic_t count_pending;
struct delayed_work dw;
} mcast_rejoin;
- struct lock_class_key team_lock_key;
long mode_priv[TEAM_MODE_PRIV_LONGS];
};
@@ -235,48 +242,50 @@ static inline int team_dev_queue_xmit(struct team *team, struct team_port *port,
skb_set_queue_mapping(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping);
skb->dev = port->dev;
- if (unlikely(netpoll_tx_running(team->dev))) {
+ if (unlikely(netpoll_tx_running(netdev_from_priv(team)))) {
team_netpoll_send_skb(port, skb);
return 0;
}
return dev_queue_xmit(skb);
}
-static inline struct hlist_head *team_port_index_hash(struct team *team,
- int port_index)
+static inline struct hlist_head *team_tx_port_index_hash(struct team *team,
+ int tx_port_index)
{
- return &team->en_port_hlist[port_index & (TEAM_PORT_HASHENTRIES - 1)];
+ unsigned int list_entry = tx_port_index & (TEAM_PORT_HASHENTRIES - 1);
+
+ return &team->tx_en_port_hlist[list_entry];
}
-static inline struct team_port *team_get_port_by_index(struct team *team,
- int port_index)
+static inline struct team_port *team_get_port_by_tx_index(struct team *team,
+ int tx_port_index)
{
+ struct hlist_head *head = team_tx_port_index_hash(team, tx_port_index);
struct team_port *port;
- struct hlist_head *head = team_port_index_hash(team, port_index);
- hlist_for_each_entry(port, head, hlist)
- if (port->index == port_index)
+ hlist_for_each_entry(port, head, tx_hlist)
+ if (port->tx_index == tx_port_index)
return port;
return NULL;
}
static inline int team_num_to_port_index(struct team *team, unsigned int num)
{
- int en_port_count = READ_ONCE(team->en_port_count);
+ int tx_en_port_count = READ_ONCE(team->tx_en_port_count);
- if (unlikely(!en_port_count))
+ if (unlikely(!tx_en_port_count))
return 0;
- return num % en_port_count;
+ return num % tx_en_port_count;
}
-static inline struct team_port *team_get_port_by_index_rcu(struct team *team,
- int port_index)
+static inline struct team_port *team_get_port_by_tx_index_rcu(struct team *team,
+ int tx_port_index)
{
+ struct hlist_head *head = team_tx_port_index_hash(team, tx_port_index);
struct team_port *port;
- struct hlist_head *head = team_port_index_hash(team, port_index);
- hlist_for_each_entry_rcu(port, head, hlist)
- if (port->index == port_index)
+ hlist_for_each_entry_rcu(port, head, tx_hlist)
+ if (READ_ONCE(port->tx_index) == tx_port_index)
return port;
return NULL;
}