Skip to content

Commit 236bb5e

Browse files
Brice Goglindavem330
authored andcommitted
myri10ge: add multiqueue TX
Add multiqueue TX support to myri10ge. [ Removed reference to deprecated CONFIG_NETDEVICES_MULTIQUEUE and NETIF_F_MULTI_QUEUE ] Signed-off-by: Brice Goglin <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c8f2d9b commit 236bb5e

File tree

1 file changed

+118
-34
lines changed

1 file changed

+118
-34
lines changed

drivers/net/myri10ge/myri10ge.c

Lines changed: 118 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ MODULE_LICENSE("Dual BSD/GPL");
102102
#define MYRI10GE_ALLOC_SIZE ((1 << MYRI10GE_ALLOC_ORDER) * PAGE_SIZE)
103103
#define MYRI10GE_MAX_FRAGS_PER_FRAME (MYRI10GE_MAX_ETHER_MTU/MYRI10GE_ALLOC_SIZE + 1)
104104

105+
#define MYRI10GE_MAX_SLICES 32
106+
105107
struct myri10ge_rx_buffer_state {
106108
struct page *page;
107109
int page_offset;
@@ -138,6 +140,8 @@ struct myri10ge_rx_buf {
138140

139141
struct myri10ge_tx_buf {
140142
struct mcp_kreq_ether_send __iomem *lanai; /* lanai ptr for sendq */
143+
__be32 __iomem *send_go; /* "go" doorbell ptr */
144+
__be32 __iomem *send_stop; /* "stop" doorbell ptr */
141145
struct mcp_kreq_ether_send *req_list; /* host shadow of sendq */
142146
char *req_bytes;
143147
struct myri10ge_tx_buffer_state *info;
@@ -149,6 +153,7 @@ struct myri10ge_tx_buf {
149153
int done ____cacheline_aligned; /* transmit slots completed */
150154
int pkt_done; /* packets completed */
151155
int wake_queue;
156+
int queue_active;
152157
};
153158

154159
struct myri10ge_rx_done {
@@ -418,6 +423,12 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd,
418423
return -ENOSYS;
419424
} else if (result == MXGEFW_CMD_ERROR_UNALIGNED) {
420425
return -E2BIG;
426+
} else if (result == MXGEFW_CMD_ERROR_RANGE &&
427+
cmd == MXGEFW_CMD_ENABLE_RSS_QUEUES &&
428+
(data->
429+
data1 & MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES) !=
430+
0) {
431+
return -ERANGE;
421432
} else {
422433
dev_err(&mgp->pdev->dev,
423434
"command %d failed, result = %d\n",
@@ -947,9 +958,24 @@ static int myri10ge_reset(struct myri10ge_priv *mgp)
947958
*/
948959

949960
cmd.data0 = mgp->num_slices;
950-
cmd.data1 = 1; /* use MSI-X */
961+
cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;
962+
if (mgp->dev->real_num_tx_queues > 1)
963+
cmd.data1 |= MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES;
951964
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES,
952965
&cmd, 0);
966+
967+
/* Firmware older than 1.4.32 only supports multiple
968+
* RX queues, so if we get an error, first retry using a
969+
* single TX queue before giving up */
970+
if (status != 0 && mgp->dev->real_num_tx_queues > 1) {
971+
mgp->dev->real_num_tx_queues = 1;
972+
cmd.data0 = mgp->num_slices;
973+
cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;
974+
status = myri10ge_send_cmd(mgp,
975+
MXGEFW_CMD_ENABLE_RSS_QUEUES,
976+
&cmd, 0);
977+
}
978+
953979
if (status != 0) {
954980
dev_err(&mgp->pdev->dev,
955981
"failed to set number of slices\n");
@@ -1317,6 +1343,7 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index)
13171343
{
13181344
struct pci_dev *pdev = ss->mgp->pdev;
13191345
struct myri10ge_tx_buf *tx = &ss->tx;
1346+
struct netdev_queue *dev_queue;
13201347
struct sk_buff *skb;
13211348
int idx, len;
13221349

@@ -1350,11 +1377,31 @@ myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index)
13501377
PCI_DMA_TODEVICE);
13511378
}
13521379
}
1380+
1381+
dev_queue = netdev_get_tx_queue(ss->dev, ss - ss->mgp->ss);
1382+
/*
1383+
* Make a minimal effort to prevent the NIC from polling an
1384+
* idle tx queue. If we can't get the lock we leave the queue
1385+
* active. In this case, either a thread was about to start
1386+
* using the queue anyway, or we lost a race and the NIC will
1387+
* waste some of its resources polling an inactive queue for a
1388+
* while.
1389+
*/
1390+
1391+
if ((ss->mgp->dev->real_num_tx_queues > 1) &&
1392+
__netif_tx_trylock(dev_queue)) {
1393+
if (tx->req == tx->done) {
1394+
tx->queue_active = 0;
1395+
put_be32(htonl(1), tx->send_stop);
1396+
}
1397+
__netif_tx_unlock(dev_queue);
1398+
}
1399+
13531400
/* start the queue if we've stopped it */
1354-
if (netif_queue_stopped(ss->dev)
1401+
if (netif_tx_queue_stopped(dev_queue)
13551402
&& tx->req - tx->done < (tx->mask >> 1)) {
13561403
tx->wake_queue++;
1357-
netif_wake_queue(ss->dev);
1404+
netif_tx_wake_queue(dev_queue);
13581405
}
13591406
}
13601407

@@ -1482,9 +1529,9 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
14821529
u32 send_done_count;
14831530
int i;
14841531

1485-
/* an interrupt on a non-zero slice is implicitly valid
1486-
* since MSI-X irqs are not shared */
1487-
if (ss != mgp->ss) {
1532+
/* an interrupt on a non-zero receive-only slice is implicitly
1533+
* valid since MSI-X irqs are not shared */
1534+
if ((mgp->dev->real_num_tx_queues == 1) && (ss != mgp->ss)) {
14881535
netif_rx_schedule(ss->dev, &ss->napi);
14891536
return (IRQ_HANDLED);
14901537
}
@@ -1526,7 +1573,9 @@ static irqreturn_t myri10ge_intr(int irq, void *arg)
15261573
barrier();
15271574
}
15281575

1529-
myri10ge_check_statblock(mgp);
1576+
/* Only slice 0 updates stats */
1577+
if (ss == mgp->ss)
1578+
myri10ge_check_statblock(mgp);
15301579

15311580
put_be32(htonl(3), ss->irq_claim + 1);
15321581
return (IRQ_HANDLED);
@@ -1884,6 +1933,7 @@ static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss)
18841933
/* ensure req_list entries are aligned to 8 bytes */
18851934
ss->tx.req_list = (struct mcp_kreq_ether_send *)
18861935
ALIGN((unsigned long)ss->tx.req_bytes, 8);
1936+
ss->tx.queue_active = 0;
18871937

18881938
bytes = rx_ring_entries * sizeof(*ss->rx_small.shadow);
18891939
ss->rx_small.shadow = kzalloc(bytes, GFP_KERNEL);
@@ -2201,11 +2251,14 @@ static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)
22012251
int status;
22022252

22032253
ss = &mgp->ss[slice];
2204-
cmd.data0 = 0; /* single slice for now */
2205-
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0);
2206-
ss->tx.lanai = (struct mcp_kreq_ether_send __iomem *)
2207-
(mgp->sram + cmd.data0);
2208-
2254+
status = 0;
2255+
if (slice == 0 || (mgp->dev->real_num_tx_queues > 1)) {
2256+
cmd.data0 = slice;
2257+
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET,
2258+
&cmd, 0);
2259+
ss->tx.lanai = (struct mcp_kreq_ether_send __iomem *)
2260+
(mgp->sram + cmd.data0);
2261+
}
22092262
cmd.data0 = slice;
22102263
status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET,
22112264
&cmd, 0);
@@ -2217,6 +2270,10 @@ static int myri10ge_get_txrx(struct myri10ge_priv *mgp, int slice)
22172270
ss->rx_big.lanai = (struct mcp_kreq_ether_recv __iomem *)
22182271
(mgp->sram + cmd.data0);
22192272

2273+
ss->tx.send_go = (__iomem __be32 *)
2274+
(mgp->sram + MXGEFW_ETH_SEND_GO + 64 * slice);
2275+
ss->tx.send_stop = (__iomem __be32 *)
2276+
(mgp->sram + MXGEFW_ETH_SEND_STOP + 64 * slice);
22202277
return status;
22212278

22222279
}
@@ -2230,7 +2287,7 @@ static int myri10ge_set_stats(struct myri10ge_priv *mgp, int slice)
22302287
ss = &mgp->ss[slice];
22312288
cmd.data0 = MYRI10GE_LOWPART_TO_U32(ss->fw_stats_bus);
22322289
cmd.data1 = MYRI10GE_HIGHPART_TO_U32(ss->fw_stats_bus);
2233-
cmd.data2 = sizeof(struct mcp_irq_data);
2290+
cmd.data2 = sizeof(struct mcp_irq_data) | (slice << 16);
22342291
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd, 0);
22352292
if (status == -ENOSYS) {
22362293
dma_addr_t bus = ss->fw_stats_bus;
@@ -2271,7 +2328,9 @@ static int myri10ge_open(struct net_device *dev)
22712328

22722329
if (mgp->num_slices > 1) {
22732330
cmd.data0 = mgp->num_slices;
2274-
cmd.data1 = 1; /* use MSI-X */
2331+
cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE;
2332+
if (mgp->dev->real_num_tx_queues > 1)
2333+
cmd.data1 |= MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES;
22752334
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES,
22762335
&cmd, 0);
22772336
if (status != 0) {
@@ -2292,6 +2351,7 @@ static int myri10ge_open(struct net_device *dev)
22922351
printk(KERN_ERR
22932352
"myri10ge: %s: failed to setup rss tables\n",
22942353
dev->name);
2354+
goto abort_with_nothing;
22952355
}
22962356

22972357
/* just enable an identity mapping */
@@ -2362,7 +2422,11 @@ static int myri10ge_open(struct net_device *dev)
23622422
status = myri10ge_allocate_rings(ss);
23632423
if (status != 0)
23642424
goto abort_with_rings;
2365-
if (slice == 0)
2425+
2426+
/* only firmware which supports multiple TX queues
2427+
* supports setting up the tx stats on non-zero
2428+
* slices */
2429+
if (slice == 0 || mgp->dev->real_num_tx_queues > 1)
23662430
status = myri10ge_set_stats(mgp, slice);
23672431
if (status) {
23682432
printk(KERN_ERR
@@ -2428,7 +2492,8 @@ static int myri10ge_open(struct net_device *dev)
24282492
mgp->running = MYRI10GE_ETH_RUNNING;
24292493
mgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout * HZ;
24302494
add_timer(&mgp->watchdog_timer);
2431-
netif_wake_queue(dev);
2495+
netif_tx_wake_all_queues(dev);
2496+
24322497
return 0;
24332498

24342499
abort_with_rings:
@@ -2461,7 +2526,8 @@ static int myri10ge_close(struct net_device *dev)
24612526
napi_disable(&mgp->ss[i].napi);
24622527
}
24632528
netif_carrier_off(dev);
2464-
netif_stop_queue(dev);
2529+
2530+
netif_tx_stop_all_queues(dev);
24652531
old_down_cnt = mgp->down_cnt;
24662532
mb();
24672533
status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd, 0);
@@ -2566,18 +2632,23 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev)
25662632
struct mcp_kreq_ether_send *req;
25672633
struct myri10ge_tx_buf *tx;
25682634
struct skb_frag_struct *frag;
2635+
struct netdev_queue *netdev_queue;
25692636
dma_addr_t bus;
25702637
u32 low;
25712638
__be32 high_swapped;
25722639
unsigned int len;
25732640
int idx, last_idx, avail, frag_cnt, frag_idx, count, mss, max_segments;
2574-
u16 pseudo_hdr_offset, cksum_offset;
2641+
u16 pseudo_hdr_offset, cksum_offset, queue;
25752642
int cum_len, seglen, boundary, rdma_count;
25762643
u8 flags, odd_flag;
25772644

2578-
/* always transmit through slot 0 */
2579-
ss = mgp->ss;
2645+
queue = skb_get_queue_mapping(skb);
2646+
queue &= (mgp->num_slices - 1);
2647+
2648+
ss = &mgp->ss[queue];
2649+
netdev_queue = netdev_get_tx_queue(mgp->dev, queue);
25802650
tx = &ss->tx;
2651+
25812652
again:
25822653
req = tx->req_list;
25832654
avail = tx->mask - 1 - (tx->req - tx->done);
@@ -2593,7 +2664,7 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev)
25932664
if ((unlikely(avail < max_segments))) {
25942665
/* we are out of transmit resources */
25952666
tx->stop_queue++;
2596-
netif_stop_queue(dev);
2667+
netif_tx_stop_queue(netdev_queue);
25972668
return 1;
25982669
}
25992670

@@ -2786,10 +2857,16 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev)
27862857
idx = ((count - 1) + tx->req) & tx->mask;
27872858
tx->info[idx].last = 1;
27882859
myri10ge_submit_req(tx, tx->req_list, count);
2860+
/* if using multiple tx queues, make sure NIC polls the
2861+
* current slice */
2862+
if ((mgp->dev->real_num_tx_queues > 1) && tx->queue_active == 0) {
2863+
tx->queue_active = 1;
2864+
put_be32(htonl(1), tx->send_go);
2865+
}
27892866
tx->pkt_start++;
27902867
if ((avail - count) < MXGEFW_MAX_SEND_DESC) {
27912868
tx->stop_queue++;
2792-
netif_stop_queue(dev);
2869+
netif_tx_stop_queue(netdev_queue);
27932870
}
27942871
dev->trans_start = jiffies;
27952872
return 0;
@@ -3367,20 +3444,21 @@ static void myri10ge_watchdog(struct work_struct *work)
33673444
for (i = 0; i < mgp->num_slices; i++) {
33683445
tx = &mgp->ss[i].tx;
33693446
printk(KERN_INFO
3370-
"myri10ge: %s: (%d): %d %d %d %d %d\n",
3371-
mgp->dev->name, i, tx->req, tx->done,
3372-
tx->pkt_start, tx->pkt_done,
3447+
"myri10ge: %s: (%d): %d %d %d %d %d %d\n",
3448+
mgp->dev->name, i, tx->queue_active, tx->req,
3449+
tx->done, tx->pkt_start, tx->pkt_done,
33733450
(int)ntohl(mgp->ss[i].fw_stats->
33743451
send_done_count));
33753452
msleep(2000);
33763453
printk(KERN_INFO
3377-
"myri10ge: %s: (%d): %d %d %d %d %d\n",
3378-
mgp->dev->name, i, tx->req, tx->done,
3379-
tx->pkt_start, tx->pkt_done,
3454+
"myri10ge: %s: (%d): %d %d %d %d %d %d\n",
3455+
mgp->dev->name, i, tx->queue_active, tx->req,
3456+
tx->done, tx->pkt_start, tx->pkt_done,
33803457
(int)ntohl(mgp->ss[i].fw_stats->
33813458
send_done_count));
33823459
}
33833460
}
3461+
33843462
rtnl_lock();
33853463
myri10ge_close(mgp->dev);
33863464
status = myri10ge_load_firmware(mgp, 1);
@@ -3435,10 +3513,14 @@ static void myri10ge_watchdog_timer(unsigned long arg)
34353513
/* nic seems like it might be stuck.. */
34363514
if (rx_pause_cnt != mgp->watchdog_pause) {
34373515
if (net_ratelimit())
3438-
printk(KERN_WARNING "myri10ge %s:"
3516+
printk(KERN_WARNING
3517+
"myri10ge %s slice %d:"
34393518
"TX paused, check link partner\n",
3440-
mgp->dev->name);
3519+
mgp->dev->name, i);
34413520
} else {
3521+
printk(KERN_WARNING
3522+
"myri10ge %s slice %d stuck:",
3523+
mgp->dev->name, i);
34423524
reset_needed = 1;
34433525
}
34443526
}
@@ -3653,7 +3735,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
36533735
int status = -ENXIO;
36543736
int dac_enabled;
36553737

3656-
netdev = alloc_etherdev(sizeof(*mgp));
3738+
netdev = alloc_etherdev_mq(sizeof(*mgp), MYRI10GE_MAX_SLICES);
36573739
if (netdev == NULL) {
36583740
dev_err(dev, "Could not allocate ethernet device\n");
36593741
return -ENOMEM;
@@ -3758,7 +3840,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
37583840
dev_err(&pdev->dev, "failed to alloc slice state\n");
37593841
goto abort_with_firmware;
37603842
}
3761-
3843+
netdev->real_num_tx_queues = mgp->num_slices;
37623844
status = myri10ge_reset(mgp);
37633845
if (status != 0) {
37643846
dev_err(&pdev->dev, "failed reset\n");
@@ -3782,6 +3864,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
37823864
netdev->set_multicast_list = myri10ge_set_multicast_list;
37833865
netdev->set_mac_address = myri10ge_set_mac_address;
37843866
netdev->features = mgp->features;
3867+
37853868
if (dac_enabled)
37863869
netdev->features |= NETIF_F_HIGHDMA;
37873870

@@ -3937,8 +4020,7 @@ static __init int myri10ge_init_module(void)
39374020
printk(KERN_INFO "%s: Version %s\n", myri10ge_driver.name,
39384021
MYRI10GE_VERSION_STR);
39394022

3940-
if (myri10ge_rss_hash > MXGEFW_RSS_HASH_TYPE_SRC_PORT ||
3941-
myri10ge_rss_hash < MXGEFW_RSS_HASH_TYPE_IPV4) {
4023+
if (myri10ge_rss_hash > MXGEFW_RSS_HASH_TYPE_MAX) {
39424024
printk(KERN_ERR
39434025
"%s: Illegal rssh hash type %d, defaulting to source port\n",
39444026
myri10ge_driver.name, myri10ge_rss_hash);
@@ -3947,6 +4029,8 @@ static __init int myri10ge_init_module(void)
39474029
#if (defined CONFIG_DCA) || (defined CONFIG_DCA_MODULE)
39484030
dca_register_notify(&myri10ge_dca_notifier);
39494031
#endif
4032+
if (myri10ge_max_slices > MYRI10GE_MAX_SLICES)
4033+
myri10ge_max_slices = MYRI10GE_MAX_SLICES;
39504034

39514035
return pci_register_driver(&myri10ge_driver);
39524036
}

0 commit comments

Comments
 (0)