* correct ops are always set.
*/
- if (!team->en_port_count || !team_is_mode_set(team) ||
+ if (!team->tx_en_port_count || !team_is_mode_set(team) ||
!team->mode->ops->transmit)
team->ops.transmit = team_dummy_transmit;
else
team->ops.transmit = team->mode->ops->transmit;
- if (!team->en_port_count || !team_is_mode_set(team) ||
+ if (!team->tx_en_port_count || !team_is_mode_set(team) ||
!team->mode->ops->receive)
team->ops.receive = team_dummy_receive;
else
return true;
if (port->priority > cur->priority)
return false;
- if (port->index < cur->index)
+ if (port->tx_index < cur->tx_index)
return true;
return false;
}
/*
* Enable/disable port by adding to enabled port hashlist and setting
- * port->index (Might be racy so reader could see incorrect ifindex when
+ * port->tx_index (Might be racy so reader could see incorrect ifindex when
* processing a flying packet, but that is not a problem). Write guarded
* by RTNL.
*/
{
if (team_port_enabled(port))
return;
- WRITE_ONCE(port->index, team->en_port_count);
- WRITE_ONCE(team->en_port_count, team->en_port_count + 1);
- hlist_add_head_rcu(&port->hlist,
- team_port_index_hash(team, port->index));
+ WRITE_ONCE(port->tx_index, team->tx_en_port_count);
+ WRITE_ONCE(team->tx_en_port_count, team->tx_en_port_count + 1);
+ hlist_add_head_rcu(&port->tx_hlist,
+ team_tx_port_index_hash(team, port->tx_index));
team_adjust_ops(team);
team_queue_override_port_add(team, port);
team_notify_peers(team);
static void __reconstruct_port_hlist(struct team *team, int rm_index)
{
- int i;
+ struct hlist_head *tx_port_index_hash;
struct team_port *port;
+ int i;
- for (i = rm_index + 1; i < team->en_port_count; i++) {
- port = team_get_port_by_index(team, i);
- hlist_del_rcu(&port->hlist);
- WRITE_ONCE(port->index, port->index - 1);
- hlist_add_head_rcu(&port->hlist,
- team_port_index_hash(team, port->index));
+ for (i = rm_index + 1; i < team->tx_en_port_count; i++) {
+ port = team_get_port_by_tx_index(team, i);
+ hlist_del_rcu(&port->tx_hlist);
+ WRITE_ONCE(port->tx_index, port->tx_index - 1);
+ tx_port_index_hash = team_tx_port_index_hash(team,
+ port->tx_index);
+ hlist_add_head_rcu(&port->tx_hlist, tx_port_index_hash);
}
}
return;
if (team->ops.port_tx_disabled)
team->ops.port_tx_disabled(team, port);
- hlist_del_rcu(&port->hlist);
- __reconstruct_port_hlist(team, port->index);
- WRITE_ONCE(port->index, -1);
- WRITE_ONCE(team->en_port_count, team->en_port_count - 1);
+ hlist_del_rcu(&port->tx_hlist);
+ __reconstruct_port_hlist(team, port->tx_index);
+ WRITE_ONCE(port->tx_index, -1);
+ WRITE_ONCE(team->tx_en_port_count, team->tx_en_port_count - 1);
team_queue_override_port_del(team, port);
team_adjust_ops(team);
team_lower_state_changed(port);
netif_addr_unlock_bh(dev);
}
- WRITE_ONCE(port->index, -1);
+ WRITE_ONCE(port->tx_index, -1);
list_add_tail_rcu(&port->list, &team->port_list);
team_port_enable(team, port);
netdev_compute_master_upper_features(dev, true);
return -ENOMEM;
for (i = 0; i < TEAM_PORT_HASHENTRIES; i++)
- INIT_HLIST_HEAD(&team->en_port_hlist[i]);
+ INIT_HLIST_HEAD(&team->tx_en_port_hlist[i]);
INIT_LIST_HEAD(&team->port_list);
err = team_queue_override_init(team);
if (err)
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 linkup; /* either state.linkup or user.linkup */
static inline bool team_port_enabled(struct team_port *port)
{
- return READ_ONCE(port->index) != -1;
+ return READ_ONCE(port->tx_index) != -1;
}
static inline bool team_port_txable(struct team_port *port)
const struct header_ops *header_ops_cache;
/*
- * 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;
+ struct hlist_head tx_en_port_hlist[TEAM_PORT_HASHENTRIES];
struct list_head port_list; /* list of all ports */
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 (READ_ONCE(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;
}