Skip to content

Commit 5e8c5ad

Browse files
baileyforrestdavem330
authored andcommitted
gve: DQO: Add core netdev features
Add napi netdev device registration, interrupt handling and initial tx and rx polling stubs. The stubs will be filled in follow-on patches. Also: - LRO feature advertisement and handling - Also update ethtool logic Signed-off-by: Bailey Forrest <[email protected]> Reviewed-by: Willem de Bruijn <[email protected]> Reviewed-by: Catherine Sullivan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1f6228e commit 5e8c5ad

File tree

8 files changed

+260
-25
lines changed

8 files changed

+260
-25
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Makefile for the Google virtual Ethernet (gve) driver
22

33
obj-$(CONFIG_GVE) += gve.o
4-
gve-objs := gve_main.o gve_tx.o gve_rx.o gve_ethtool.o gve_adminq.o gve_utils.o
4+
gve-objs := gve_main.o gve_tx.o gve_tx_dqo.o gve_rx.o gve_rx_dqo.o gve_ethtool.o gve_adminq.o gve_utils.o

drivers/net/ethernet/google/gve/gve.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
/* PTYPEs are always 10 bits. */
4646
#define GVE_NUM_PTYPES 1024
4747

48+
#define GVE_RX_BUFFER_SIZE_DQO 2048
49+
4850
/* Each slot in the desc ring has a 1:1 mapping to a slot in the data ring */
4951
struct gve_rx_desc_queue {
5052
struct gve_rx_desc *desc_ring; /* the descriptor ring */

drivers/net/ethernet/google/gve/gve_adminq.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -714,6 +714,8 @@ int gve_adminq_describe_device(struct gve_priv *priv)
714714
if (gve_is_gqi(priv)) {
715715
err = gve_set_desc_cnt(priv, descriptor);
716716
} else {
717+
/* DQO supports LRO. */
718+
priv->dev->hw_features |= NETIF_F_LRO;
717719
err = gve_set_desc_cnt_dqo(priv, descriptor, dev_op_dqo_rda);
718720
}
719721
if (err)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* SPDX-License-Identifier: (GPL-2.0 OR MIT)
2+
* Google virtual Ethernet (gve) driver
3+
*
4+
* Copyright (C) 2015-2021 Google, Inc.
5+
*/
6+
7+
#ifndef _GVE_DQO_H_
8+
#define _GVE_DQO_H_
9+
10+
#include "gve_adminq.h"
11+
12+
#define GVE_ITR_ENABLE_BIT_DQO BIT(0)
13+
#define GVE_ITR_CLEAR_PBA_BIT_DQO BIT(1)
14+
#define GVE_ITR_NO_UPDATE_DQO (3 << 3)
15+
16+
#define GVE_TX_IRQ_RATELIMIT_US_DQO 50
17+
#define GVE_RX_IRQ_RATELIMIT_US_DQO 20
18+
19+
netdev_tx_t gve_tx_dqo(struct sk_buff *skb, struct net_device *dev);
20+
bool gve_tx_poll_dqo(struct gve_notify_block *block, bool do_clean);
21+
int gve_rx_poll_dqo(struct gve_notify_block *block, int budget);
22+
23+
static inline void
24+
gve_write_irq_doorbell_dqo(const struct gve_priv *priv,
25+
const struct gve_notify_block *block, u32 val)
26+
{
27+
u32 index = be32_to_cpu(block->irq_db_index);
28+
29+
iowrite32(val, &priv->db_bar2[index]);
30+
}
31+
32+
#endif /* _GVE_DQO_H_ */

drivers/net/ethernet/google/gve/gve_ethtool.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,16 @@ gve_get_ethtool_stats(struct net_device *netdev,
311311
for (ring = 0; ring < priv->tx_cfg.num_queues; ring++) {
312312
struct gve_tx_ring *tx = &priv->tx[ring];
313313

314-
data[i++] = tx->req;
315-
data[i++] = tx->done;
314+
if (gve_is_gqi(priv)) {
315+
data[i++] = tx->req;
316+
data[i++] = tx->done;
317+
} else {
318+
/* DQO doesn't currently support
319+
* posted/completed descriptor counts;
320+
*/
321+
data[i++] = 0;
322+
data[i++] = 0;
323+
}
316324
do {
317325
start =
318326
u64_stats_fetch_begin(&priv->tx[ring].statss);

drivers/net/ethernet/google/gve/gve_main.c

Lines changed: 166 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/workqueue.h>
1515
#include <net/sch_generic.h>
1616
#include "gve.h"
17+
#include "gve_dqo.h"
1718
#include "gve_adminq.h"
1819
#include "gve_register.h"
1920

@@ -26,6 +27,16 @@
2627
const char gve_version_str[] = GVE_VERSION;
2728
static const char gve_version_prefix[] = GVE_VERSION_PREFIX;
2829

30+
static netdev_tx_t gve_start_xmit(struct sk_buff *skb, struct net_device *dev)
31+
{
32+
struct gve_priv *priv = netdev_priv(dev);
33+
34+
if (gve_is_gqi(priv))
35+
return gve_tx(skb, dev);
36+
else
37+
return gve_tx_dqo(skb, dev);
38+
}
39+
2940
static void gve_get_stats(struct net_device *dev, struct rtnl_link_stats64 *s)
3041
{
3142
struct gve_priv *priv = netdev_priv(dev);
@@ -155,6 +166,15 @@ static irqreturn_t gve_intr(int irq, void *arg)
155166
return IRQ_HANDLED;
156167
}
157168

169+
static irqreturn_t gve_intr_dqo(int irq, void *arg)
170+
{
171+
struct gve_notify_block *block = arg;
172+
173+
/* Interrupts are automatically masked */
174+
napi_schedule_irqoff(&block->napi);
175+
return IRQ_HANDLED;
176+
}
177+
158178
static int gve_napi_poll(struct napi_struct *napi, int budget)
159179
{
160180
struct gve_notify_block *block;
@@ -191,6 +211,54 @@ static int gve_napi_poll(struct napi_struct *napi, int budget)
191211
return 0;
192212
}
193213

214+
static int gve_napi_poll_dqo(struct napi_struct *napi, int budget)
215+
{
216+
struct gve_notify_block *block =
217+
container_of(napi, struct gve_notify_block, napi);
218+
struct gve_priv *priv = block->priv;
219+
bool reschedule = false;
220+
int work_done = 0;
221+
222+
/* Clear PCI MSI-X Pending Bit Array (PBA)
223+
*
224+
* This bit is set if an interrupt event occurs while the vector is
225+
* masked. If this bit is set and we reenable the interrupt, it will
226+
* fire again. Since we're just about to poll the queue state, we don't
227+
* need it to fire again.
228+
*
229+
* Under high softirq load, it's possible that the interrupt condition
230+
* is triggered twice before we got the chance to process it.
231+
*/
232+
gve_write_irq_doorbell_dqo(priv, block,
233+
GVE_ITR_NO_UPDATE_DQO | GVE_ITR_CLEAR_PBA_BIT_DQO);
234+
235+
if (block->tx)
236+
reschedule |= gve_tx_poll_dqo(block, /*do_clean=*/true);
237+
238+
if (block->rx) {
239+
work_done = gve_rx_poll_dqo(block, budget);
240+
reschedule |= work_done == budget;
241+
}
242+
243+
if (reschedule)
244+
return budget;
245+
246+
if (likely(napi_complete_done(napi, work_done))) {
247+
/* Enable interrupts again.
248+
*
249+
* We don't need to repoll afterwards because HW supports the
250+
* PCI MSI-X PBA feature.
251+
*
252+
* Another interrupt would be triggered if a new event came in
253+
* since the last one.
254+
*/
255+
gve_write_irq_doorbell_dqo(priv, block,
256+
GVE_ITR_NO_UPDATE_DQO | GVE_ITR_ENABLE_BIT_DQO);
257+
}
258+
259+
return work_done;
260+
}
261+
194262
static int gve_alloc_notify_blocks(struct gve_priv *priv)
195263
{
196264
int num_vecs_requested = priv->num_ntfy_blks + 1;
@@ -264,7 +332,8 @@ static int gve_alloc_notify_blocks(struct gve_priv *priv)
264332
name, i);
265333
block->priv = priv;
266334
err = request_irq(priv->msix_vectors[msix_idx].vector,
267-
gve_intr, 0, block->name, block);
335+
gve_is_gqi(priv) ? gve_intr : gve_intr_dqo,
336+
0, block->name, block);
268337
if (err) {
269338
dev_err(&priv->pdev->dev,
270339
"Failed to receive msix vector %d\n", i);
@@ -417,11 +486,12 @@ static void gve_teardown_device_resources(struct gve_priv *priv)
417486
gve_clear_device_resources_ok(priv);
418487
}
419488

420-
static void gve_add_napi(struct gve_priv *priv, int ntfy_idx)
489+
static void gve_add_napi(struct gve_priv *priv, int ntfy_idx,
490+
int (*gve_poll)(struct napi_struct *, int))
421491
{
422492
struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx];
423493

424-
netif_napi_add(priv->dev, &block->napi, gve_napi_poll,
494+
netif_napi_add(priv->dev, &block->napi, gve_poll,
425495
NAPI_POLL_WEIGHT);
426496
}
427497

@@ -512,11 +582,33 @@ static int gve_create_rings(struct gve_priv *priv)
512582
return 0;
513583
}
514584

585+
static void add_napi_init_sync_stats(struct gve_priv *priv,
586+
int (*napi_poll)(struct napi_struct *napi,
587+
int budget))
588+
{
589+
int i;
590+
591+
/* Add tx napi & init sync stats*/
592+
for (i = 0; i < priv->tx_cfg.num_queues; i++) {
593+
int ntfy_idx = gve_tx_idx_to_ntfy(priv, i);
594+
595+
u64_stats_init(&priv->tx[i].statss);
596+
priv->tx[i].ntfy_id = ntfy_idx;
597+
gve_add_napi(priv, ntfy_idx, napi_poll);
598+
}
599+
/* Add rx napi & init sync stats*/
600+
for (i = 0; i < priv->rx_cfg.num_queues; i++) {
601+
int ntfy_idx = gve_rx_idx_to_ntfy(priv, i);
602+
603+
u64_stats_init(&priv->rx[i].statss);
604+
priv->rx[i].ntfy_id = ntfy_idx;
605+
gve_add_napi(priv, ntfy_idx, napi_poll);
606+
}
607+
}
608+
515609
static int gve_alloc_rings(struct gve_priv *priv)
516610
{
517-
int ntfy_idx;
518611
int err;
519-
int i;
520612

521613
/* Setup tx rings */
522614
priv->tx = kvzalloc(priv->tx_cfg.num_queues * sizeof(*priv->tx),
@@ -536,18 +628,11 @@ static int gve_alloc_rings(struct gve_priv *priv)
536628
err = gve_rx_alloc_rings(priv);
537629
if (err)
538630
goto free_rx;
539-
/* Add tx napi & init sync stats*/
540-
for (i = 0; i < priv->tx_cfg.num_queues; i++) {
541-
u64_stats_init(&priv->tx[i].statss);
542-
ntfy_idx = gve_tx_idx_to_ntfy(priv, i);
543-
gve_add_napi(priv, ntfy_idx);
544-
}
545-
/* Add rx napi & init sync stats*/
546-
for (i = 0; i < priv->rx_cfg.num_queues; i++) {
547-
u64_stats_init(&priv->rx[i].statss);
548-
ntfy_idx = gve_rx_idx_to_ntfy(priv, i);
549-
gve_add_napi(priv, ntfy_idx);
550-
}
631+
632+
if (gve_is_gqi(priv))
633+
add_napi_init_sync_stats(priv, gve_napi_poll);
634+
else
635+
add_napi_init_sync_stats(priv, gve_napi_poll_dqo);
551636

552637
return 0;
553638

@@ -798,9 +883,17 @@ static int gve_open(struct net_device *dev)
798883
err = gve_register_qpls(priv);
799884
if (err)
800885
goto reset;
886+
887+
if (!gve_is_gqi(priv)) {
888+
/* Hard code this for now. This may be tuned in the future for
889+
* performance.
890+
*/
891+
priv->data_buffer_size_dqo = GVE_RX_BUFFER_SIZE_DQO;
892+
}
801893
err = gve_create_rings(priv);
802894
if (err)
803895
goto reset;
896+
804897
gve_set_device_rings_ok(priv);
805898

806899
if (gve_get_report_stats(priv))
@@ -970,12 +1063,49 @@ static void gve_tx_timeout(struct net_device *dev, unsigned int txqueue)
9701063
priv->tx_timeo_cnt++;
9711064
}
9721065

1066+
static int gve_set_features(struct net_device *netdev,
1067+
netdev_features_t features)
1068+
{
1069+
const netdev_features_t orig_features = netdev->features;
1070+
struct gve_priv *priv = netdev_priv(netdev);
1071+
int err;
1072+
1073+
if ((netdev->features & NETIF_F_LRO) != (features & NETIF_F_LRO)) {
1074+
netdev->features ^= NETIF_F_LRO;
1075+
if (netif_carrier_ok(netdev)) {
1076+
/* To make this process as simple as possible we
1077+
* teardown the device, set the new configuration,
1078+
* and then bring the device up again.
1079+
*/
1080+
err = gve_close(netdev);
1081+
/* We have already tried to reset in close, just fail
1082+
* at this point.
1083+
*/
1084+
if (err)
1085+
goto err;
1086+
1087+
err = gve_open(netdev);
1088+
if (err)
1089+
goto err;
1090+
}
1091+
}
1092+
1093+
return 0;
1094+
err:
1095+
/* Reverts the change on error. */
1096+
netdev->features = orig_features;
1097+
netif_err(priv, drv, netdev,
1098+
"Set features failed! !!! DISABLING ALL QUEUES !!!\n");
1099+
return err;
1100+
}
1101+
9731102
static const struct net_device_ops gve_netdev_ops = {
974-
.ndo_start_xmit = gve_tx,
1103+
.ndo_start_xmit = gve_start_xmit,
9751104
.ndo_open = gve_open,
9761105
.ndo_stop = gve_close,
9771106
.ndo_get_stats64 = gve_get_stats,
9781107
.ndo_tx_timeout = gve_tx_timeout,
1108+
.ndo_set_features = gve_set_features,
9791109
};
9801110

9811111
static void gve_handle_status(struct gve_priv *priv, u32 status)
@@ -1019,6 +1149,15 @@ void gve_handle_report_stats(struct gve_priv *priv)
10191149
/* tx stats */
10201150
if (priv->tx) {
10211151
for (idx = 0; idx < priv->tx_cfg.num_queues; idx++) {
1152+
u32 last_completion = 0;
1153+
u32 tx_frames = 0;
1154+
1155+
/* DQO doesn't currently support these metrics. */
1156+
if (gve_is_gqi(priv)) {
1157+
last_completion = priv->tx[idx].done;
1158+
tx_frames = priv->tx[idx].req;
1159+
}
1160+
10221161
do {
10231162
start = u64_stats_fetch_begin(&priv->tx[idx].statss);
10241163
tx_bytes = priv->tx[idx].bytes_done;
@@ -1035,7 +1174,7 @@ void gve_handle_report_stats(struct gve_priv *priv)
10351174
};
10361175
stats[stats_idx++] = (struct stats) {
10371176
.stat_name = cpu_to_be32(TX_FRAMES_SENT),
1038-
.value = cpu_to_be64(priv->tx[idx].req),
1177+
.value = cpu_to_be64(tx_frames),
10391178
.queue_id = cpu_to_be32(idx),
10401179
};
10411180
stats[stats_idx++] = (struct stats) {
@@ -1045,7 +1184,7 @@ void gve_handle_report_stats(struct gve_priv *priv)
10451184
};
10461185
stats[stats_idx++] = (struct stats) {
10471186
.stat_name = cpu_to_be32(TX_LAST_COMPLETION_PROCESSED),
1048-
.value = cpu_to_be64(priv->tx[idx].done),
1187+
.value = cpu_to_be64(last_completion),
10491188
.queue_id = cpu_to_be32(idx),
10501189
};
10511190
}
@@ -1121,7 +1260,7 @@ static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
11211260
"Could not get device information: err=%d\n", err);
11221261
goto err;
11231262
}
1124-
if (priv->dev->max_mtu > PAGE_SIZE) {
1263+
if (gve_is_gqi(priv) && priv->dev->max_mtu > PAGE_SIZE) {
11251264
priv->dev->max_mtu = PAGE_SIZE;
11261265
err = gve_adminq_set_mtu(priv, priv->dev->mtu);
11271266
if (err) {
@@ -1332,7 +1471,12 @@ static int gve_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
13321471
pci_set_drvdata(pdev, dev);
13331472
dev->ethtool_ops = &gve_ethtool_ops;
13341473
dev->netdev_ops = &gve_netdev_ops;
1335-
/* advertise features */
1474+
1475+
/* Set default and supported features.
1476+
*
1477+
* Features might be set in other locations as well (such as
1478+
* `gve_adminq_describe_device`).
1479+
*/
13361480
dev->hw_features = NETIF_F_HIGHDMA;
13371481
dev->hw_features |= NETIF_F_SG;
13381482
dev->hw_features |= NETIF_F_HW_CSUM;

0 commit comments

Comments
 (0)