aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Pirko <jiri@resnulli.us>2012-07-19 22:28:51 -0400
committerDavid S. Miller <davem@davemloft.net>2012-07-20 14:07:00 -0400
commit6c85f2bdda2086d804e198a3f31b685bc2f86b04 (patch)
tree49abe1f74a0a3290cf611878a704914a9f5e6577
parent8a540ff9e1d685b5feb0a9df5d2b74db1e0b4d39 (diff)
team: add multiqueue support
Largely copied from bonding code. Signed-off-by: Jiri Pirko <jiri@resnulli.us> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/team/team.c65
-rw-r--r--include/linux/if_team.h8
2 files changed, 68 insertions, 5 deletions
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c
index 813e1319095f..b104c05225f7 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -27,6 +27,7 @@
27#include <net/rtnetlink.h> 27#include <net/rtnetlink.h>
28#include <net/genetlink.h> 28#include <net/genetlink.h>
29#include <net/netlink.h> 29#include <net/netlink.h>
30#include <net/sch_generic.h>
30#include <linux/if_team.h> 31#include <linux/if_team.h>
31 32
32#define DRV_NAME "team" 33#define DRV_NAME "team"
@@ -1121,6 +1122,22 @@ static const struct team_option team_options[] = {
1121 }, 1122 },
1122}; 1123};
1123 1124
1125static struct lock_class_key team_netdev_xmit_lock_key;
1126static struct lock_class_key team_netdev_addr_lock_key;
1127
1128static void team_set_lockdep_class_one(struct net_device *dev,
1129 struct netdev_queue *txq,
1130 void *unused)
1131{
1132 lockdep_set_class(&txq->_xmit_lock, &team_netdev_xmit_lock_key);
1133}
1134
1135static void team_set_lockdep_class(struct net_device *dev)
1136{
1137 lockdep_set_class(&dev->addr_list_lock, &team_netdev_addr_lock_key);
1138 netdev_for_each_tx_queue(dev, team_set_lockdep_class_one, NULL);
1139}
1140
1124static int team_init(struct net_device *dev) 1141static int team_init(struct net_device *dev)
1125{ 1142{
1126 struct team *team = netdev_priv(dev); 1143 struct team *team = netdev_priv(dev);
@@ -1148,6 +1165,8 @@ static int team_init(struct net_device *dev)
1148 goto err_options_register; 1165 goto err_options_register;
1149 netif_carrier_off(dev); 1166 netif_carrier_off(dev);
1150 1167
1168 team_set_lockdep_class(dev);
1169
1151 return 0; 1170 return 0;
1152 1171
1153err_options_register: 1172err_options_register:
@@ -1216,6 +1235,29 @@ static netdev_tx_t team_xmit(struct sk_buff *skb, struct net_device *dev)
1216 return NETDEV_TX_OK; 1235 return NETDEV_TX_OK;
1217} 1236}
1218 1237
1238static u16 team_select_queue(struct net_device *dev, struct sk_buff *skb)
1239{
1240 /*
1241 * This helper function exists to help dev_pick_tx get the correct
1242 * destination queue. Using a helper function skips a call to
1243 * skb_tx_hash and will put the skbs in the queue we expect on their
1244 * way down to the team driver.
1245 */
1246 u16 txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
1247
1248 /*
1249 * Save the original txq to restore before passing to the driver
1250 */
1251 qdisc_skb_cb(skb)->slave_dev_queue_mapping = skb->queue_mapping;
1252
1253 if (unlikely(txq >= dev->real_num_tx_queues)) {
1254 do {
1255 txq -= dev->real_num_tx_queues;
1256 } while (txq >= dev->real_num_tx_queues);
1257 }
1258 return txq;
1259}
1260
1219static void team_change_rx_flags(struct net_device *dev, int change) 1261static void team_change_rx_flags(struct net_device *dev, int change)
1220{ 1262{
1221 struct team *team = netdev_priv(dev); 1263 struct team *team = netdev_priv(dev);
@@ -1469,6 +1511,7 @@ static const struct net_device_ops team_netdev_ops = {
1469 .ndo_open = team_open, 1511 .ndo_open = team_open,
1470 .ndo_stop = team_close, 1512 .ndo_stop = team_close,
1471 .ndo_start_xmit = team_xmit, 1513 .ndo_start_xmit = team_xmit,
1514 .ndo_select_queue = team_select_queue,
1472 .ndo_change_rx_flags = team_change_rx_flags, 1515 .ndo_change_rx_flags = team_change_rx_flags,
1473 .ndo_set_rx_mode = team_set_rx_mode, 1516 .ndo_set_rx_mode = team_set_rx_mode,
1474 .ndo_set_mac_address = team_set_mac_address, 1517 .ndo_set_mac_address = team_set_mac_address,
@@ -1543,12 +1586,24 @@ static int team_validate(struct nlattr *tb[], struct nlattr *data[])
1543 return 0; 1586 return 0;
1544} 1587}
1545 1588
1589static unsigned int team_get_num_tx_queues(void)
1590{
1591 return TEAM_DEFAULT_NUM_TX_QUEUES;
1592}
1593
1594static unsigned int team_get_num_rx_queues(void)
1595{
1596 return TEAM_DEFAULT_NUM_RX_QUEUES;
1597}
1598
1546static struct rtnl_link_ops team_link_ops __read_mostly = { 1599static struct rtnl_link_ops team_link_ops __read_mostly = {
1547 .kind = DRV_NAME, 1600 .kind = DRV_NAME,
1548 .priv_size = sizeof(struct team), 1601 .priv_size = sizeof(struct team),
1549 .setup = team_setup, 1602 .setup = team_setup,
1550 .newlink = team_newlink, 1603 .newlink = team_newlink,
1551 .validate = team_validate, 1604 .validate = team_validate,
1605 .get_num_tx_queues = team_get_num_tx_queues,
1606 .get_num_rx_queues = team_get_num_rx_queues,
1552}; 1607};
1553 1608
1554 1609
diff --git a/include/linux/if_team.h b/include/linux/if_team.h
index 7fd0cdeb9444..6960fc1841a7 100644
--- a/include/linux/if_team.h
+++ b/include/linux/if_team.h
@@ -14,6 +14,7 @@
14#ifdef __KERNEL__ 14#ifdef __KERNEL__
15 15
16#include <linux/netpoll.h> 16#include <linux/netpoll.h>
17#include <net/sch_generic.h>
17 18
18struct team_pcpu_stats { 19struct team_pcpu_stats {
19 u64 rx_packets; 20 u64 rx_packets;
@@ -98,6 +99,10 @@ static inline void team_netpoll_send_skb(struct team_port *port,
98static inline int team_dev_queue_xmit(struct team *team, struct team_port *port, 99static inline int team_dev_queue_xmit(struct team *team, struct team_port *port,
99 struct sk_buff *skb) 100 struct sk_buff *skb)
100{ 101{
102 BUILD_BUG_ON(sizeof(skb->queue_mapping) !=
103 sizeof(qdisc_skb_cb(skb)->slave_dev_queue_mapping));
104 skb_set_queue_mapping(skb, qdisc_skb_cb(skb)->slave_dev_queue_mapping);
105
101 skb->dev = port->dev; 106 skb->dev = port->dev;
102 if (unlikely(netpoll_tx_running(port->dev))) { 107 if (unlikely(netpoll_tx_running(port->dev))) {
103 team_netpoll_send_skb(port, skb); 108 team_netpoll_send_skb(port, skb);
@@ -236,6 +241,9 @@ extern void team_options_unregister(struct team *team,
236extern int team_mode_register(const struct team_mode *mode); 241extern int team_mode_register(const struct team_mode *mode);
237extern void team_mode_unregister(const struct team_mode *mode); 242extern void team_mode_unregister(const struct team_mode *mode);
238 243
244#define TEAM_DEFAULT_NUM_TX_QUEUES 16
245#define TEAM_DEFAULT_NUM_RX_QUEUES 16
246
239#endif /* __KERNEL__ */ 247#endif /* __KERNEL__ */
240 248
241#define TEAM_STRING_MAX_LEN 32 249#define TEAM_STRING_MAX_LEN 32