gve: Add tx|rx-coalesce-usec for DQO
Adding ethtool support for changing rx-coalesce-usec and tx-coalesce-usec when using the DQO queue format. Signed-off-by: Tao Liu <xliutaox@google.com> Signed-off-by: Jeroen de Borst <jeroendb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2c9198356d
commit
6081ac2013
drivers/net/ethernet/google/gve
|
@ -584,6 +584,10 @@ struct gve_priv {
|
|||
int data_buffer_size_dqo;
|
||||
|
||||
enum gve_queue_format queue_format;
|
||||
|
||||
/* Interrupt coalescing settings */
|
||||
u32 tx_coalesce_usecs;
|
||||
u32 rx_coalesce_usecs;
|
||||
};
|
||||
|
||||
enum gve_service_task_flags_bit {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#define GVE_TX_IRQ_RATELIMIT_US_DQO 50
|
||||
#define GVE_RX_IRQ_RATELIMIT_US_DQO 20
|
||||
#define GVE_MAX_ITR_INTERVAL_DQO (GVE_ITR_INTERVAL_DQO_MASK * 2)
|
||||
|
||||
/* Timeout in seconds to wait for a reinjection completion after receiving
|
||||
* its corresponding miss completion.
|
||||
|
@ -54,17 +55,17 @@ gve_tx_put_doorbell_dqo(const struct gve_priv *priv,
|
|||
}
|
||||
|
||||
/* Builds register value to write to DQO IRQ doorbell to enable with specified
|
||||
* ratelimit.
|
||||
* ITR interval.
|
||||
*/
|
||||
static inline u32 gve_set_itr_ratelimit_dqo(u32 ratelimit_us)
|
||||
static inline u32 gve_setup_itr_interval_dqo(u32 interval_us)
|
||||
{
|
||||
u32 result = GVE_ITR_ENABLE_BIT_DQO;
|
||||
|
||||
/* Interval has 2us granularity. */
|
||||
ratelimit_us >>= 1;
|
||||
interval_us >>= 1;
|
||||
|
||||
ratelimit_us &= GVE_ITR_INTERVAL_DQO_MASK;
|
||||
result |= (ratelimit_us << GVE_ITR_INTERVAL_DQO_SHIFT);
|
||||
interval_us &= GVE_ITR_INTERVAL_DQO_MASK;
|
||||
result |= (interval_us << GVE_ITR_INTERVAL_DQO_SHIFT);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -78,4 +79,15 @@ gve_write_irq_doorbell_dqo(const struct gve_priv *priv,
|
|||
iowrite32(val, &priv->db_bar2[index]);
|
||||
}
|
||||
|
||||
/* Sets interrupt throttling interval and enables interrupt
|
||||
* by writing to IRQ doorbell.
|
||||
*/
|
||||
static inline void
|
||||
gve_set_itr_coalesce_usecs_dqo(struct gve_priv *priv,
|
||||
struct gve_notify_block *block,
|
||||
u32 usecs)
|
||||
{
|
||||
gve_write_irq_doorbell_dqo(priv, block,
|
||||
gve_setup_itr_interval_dqo(usecs));
|
||||
}
|
||||
#endif /* _GVE_DQO_H_ */
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <linux/rtnetlink.h>
|
||||
#include "gve.h"
|
||||
#include "gve_adminq.h"
|
||||
#include "gve_dqo.h"
|
||||
|
||||
static void gve_get_drvinfo(struct net_device *netdev,
|
||||
struct ethtool_drvinfo *info)
|
||||
|
@ -540,7 +541,65 @@ static int gve_get_link_ksettings(struct net_device *netdev,
|
|||
return err;
|
||||
}
|
||||
|
||||
static int gve_get_coalesce(struct net_device *netdev,
|
||||
struct ethtool_coalesce *ec,
|
||||
struct kernel_ethtool_coalesce *kernel_ec,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct gve_priv *priv = netdev_priv(netdev);
|
||||
|
||||
if (gve_is_gqi(priv))
|
||||
return -EOPNOTSUPP;
|
||||
ec->tx_coalesce_usecs = priv->tx_coalesce_usecs;
|
||||
ec->rx_coalesce_usecs = priv->rx_coalesce_usecs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int gve_set_coalesce(struct net_device *netdev,
|
||||
struct ethtool_coalesce *ec,
|
||||
struct kernel_ethtool_coalesce *kernel_ec,
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct gve_priv *priv = netdev_priv(netdev);
|
||||
u32 tx_usecs_orig = priv->tx_coalesce_usecs;
|
||||
u32 rx_usecs_orig = priv->rx_coalesce_usecs;
|
||||
int idx;
|
||||
|
||||
if (gve_is_gqi(priv))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (ec->tx_coalesce_usecs > GVE_MAX_ITR_INTERVAL_DQO ||
|
||||
ec->rx_coalesce_usecs > GVE_MAX_ITR_INTERVAL_DQO)
|
||||
return -EINVAL;
|
||||
priv->tx_coalesce_usecs = ec->tx_coalesce_usecs;
|
||||
priv->rx_coalesce_usecs = ec->rx_coalesce_usecs;
|
||||
|
||||
if (tx_usecs_orig != priv->tx_coalesce_usecs) {
|
||||
for (idx = 0; idx < priv->tx_cfg.num_queues; idx++) {
|
||||
int ntfy_idx = gve_tx_idx_to_ntfy(priv, idx);
|
||||
struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx];
|
||||
|
||||
gve_set_itr_coalesce_usecs_dqo(priv, block,
|
||||
priv->tx_coalesce_usecs);
|
||||
}
|
||||
}
|
||||
|
||||
if (rx_usecs_orig != priv->rx_coalesce_usecs) {
|
||||
for (idx = 0; idx < priv->rx_cfg.num_queues; idx++) {
|
||||
int ntfy_idx = gve_rx_idx_to_ntfy(priv, idx);
|
||||
struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx];
|
||||
|
||||
gve_set_itr_coalesce_usecs_dqo(priv, block,
|
||||
priv->rx_coalesce_usecs);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct ethtool_ops gve_ethtool_ops = {
|
||||
.supported_coalesce_params = ETHTOOL_COALESCE_USECS,
|
||||
.get_drvinfo = gve_get_drvinfo,
|
||||
.get_strings = gve_get_strings,
|
||||
.get_sset_count = gve_get_sset_count,
|
||||
|
@ -550,6 +609,8 @@ const struct ethtool_ops gve_ethtool_ops = {
|
|||
.set_channels = gve_set_channels,
|
||||
.get_channels = gve_get_channels,
|
||||
.get_link = ethtool_op_get_link,
|
||||
.get_coalesce = gve_get_coalesce,
|
||||
.set_coalesce = gve_set_coalesce,
|
||||
.get_ringparam = gve_get_ringparam,
|
||||
.reset = gve_user_reset,
|
||||
.get_tunable = gve_get_tunable,
|
||||
|
|
|
@ -1113,9 +1113,8 @@ static void gve_turnup(struct gve_priv *priv)
|
|||
if (gve_is_gqi(priv)) {
|
||||
iowrite32be(0, gve_irq_doorbell(priv, block));
|
||||
} else {
|
||||
u32 val = gve_set_itr_ratelimit_dqo(GVE_TX_IRQ_RATELIMIT_US_DQO);
|
||||
|
||||
gve_write_irq_doorbell_dqo(priv, block, val);
|
||||
gve_set_itr_coalesce_usecs_dqo(priv, block,
|
||||
priv->tx_coalesce_usecs);
|
||||
}
|
||||
}
|
||||
for (idx = 0; idx < priv->rx_cfg.num_queues; idx++) {
|
||||
|
@ -1126,9 +1125,8 @@ static void gve_turnup(struct gve_priv *priv)
|
|||
if (gve_is_gqi(priv)) {
|
||||
iowrite32be(0, gve_irq_doorbell(priv, block));
|
||||
} else {
|
||||
u32 val = gve_set_itr_ratelimit_dqo(GVE_RX_IRQ_RATELIMIT_US_DQO);
|
||||
|
||||
gve_write_irq_doorbell_dqo(priv, block, val);
|
||||
gve_set_itr_coalesce_usecs_dqo(priv, block,
|
||||
priv->rx_coalesce_usecs);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1425,6 +1423,11 @@ static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
|
|||
dev_info(&priv->pdev->dev, "Max TX queues %d, Max RX queues %d\n",
|
||||
priv->tx_cfg.max_queues, priv->rx_cfg.max_queues);
|
||||
|
||||
if (!gve_is_gqi(priv)) {
|
||||
priv->tx_coalesce_usecs = GVE_TX_IRQ_RATELIMIT_US_DQO;
|
||||
priv->rx_coalesce_usecs = GVE_RX_IRQ_RATELIMIT_US_DQO;
|
||||
}
|
||||
|
||||
setup_device:
|
||||
err = gve_setup_device_resources(priv);
|
||||
if (!err)
|
||||
|
|
Loading…
Reference in New Issue