Commit 255489f5 authored by Shailend Chand's avatar Shailend Chand Committed by David S. Miller

gve: Add a jumbo-frame device option.

A widely deployed driver has a bug that will cause the driver not
to load when a max_mtu > 2048 is present in the device descriptor.

To avoid this bug while still enabling jumbo frames, we present a lower
max_mtu in the device descriptor and pass the actual max_mtu in
a separate device option.

The driver supports 2 different queue formats. To enable features
on one queue format, but not the other, a supported_features mask
was added to the device options in the device descriptor.
Signed-off-by: default avatarShailend Chand <shailend@google.com>
Signed-off-by: default avatarJeroen de Borst <jeroendb@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 37149e93
...@@ -38,7 +38,8 @@ void gve_parse_device_option(struct gve_priv *priv, ...@@ -38,7 +38,8 @@ void gve_parse_device_option(struct gve_priv *priv,
struct gve_device_option *option, struct gve_device_option *option,
struct gve_device_option_gqi_rda **dev_op_gqi_rda, struct gve_device_option_gqi_rda **dev_op_gqi_rda,
struct gve_device_option_gqi_qpl **dev_op_gqi_qpl, struct gve_device_option_gqi_qpl **dev_op_gqi_qpl,
struct gve_device_option_dqo_rda **dev_op_dqo_rda) struct gve_device_option_dqo_rda **dev_op_dqo_rda,
struct gve_device_option_jumbo_frames **dev_op_jumbo_frames)
{ {
u32 req_feat_mask = be32_to_cpu(option->required_features_mask); u32 req_feat_mask = be32_to_cpu(option->required_features_mask);
u16 option_length = be16_to_cpu(option->option_length); u16 option_length = be16_to_cpu(option->option_length);
...@@ -111,6 +112,24 @@ void gve_parse_device_option(struct gve_priv *priv, ...@@ -111,6 +112,24 @@ void gve_parse_device_option(struct gve_priv *priv,
} }
*dev_op_dqo_rda = (void *)(option + 1); *dev_op_dqo_rda = (void *)(option + 1);
break; break;
case GVE_DEV_OPT_ID_JUMBO_FRAMES:
if (option_length < sizeof(**dev_op_jumbo_frames) ||
req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES) {
dev_warn(&priv->pdev->dev, GVE_DEVICE_OPTION_ERROR_FMT,
"Jumbo Frames",
(int)sizeof(**dev_op_jumbo_frames),
GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES,
option_length, req_feat_mask);
break;
}
if (option_length > sizeof(**dev_op_jumbo_frames)) {
dev_warn(&priv->pdev->dev,
GVE_DEVICE_OPTION_TOO_BIG_FMT,
"Jumbo Frames");
}
*dev_op_jumbo_frames = (void *)(option + 1);
break;
default: default:
/* If we don't recognize the option just continue /* If we don't recognize the option just continue
* without doing anything. * without doing anything.
...@@ -126,7 +145,8 @@ gve_process_device_options(struct gve_priv *priv, ...@@ -126,7 +145,8 @@ gve_process_device_options(struct gve_priv *priv,
struct gve_device_descriptor *descriptor, struct gve_device_descriptor *descriptor,
struct gve_device_option_gqi_rda **dev_op_gqi_rda, struct gve_device_option_gqi_rda **dev_op_gqi_rda,
struct gve_device_option_gqi_qpl **dev_op_gqi_qpl, struct gve_device_option_gqi_qpl **dev_op_gqi_qpl,
struct gve_device_option_dqo_rda **dev_op_dqo_rda) struct gve_device_option_dqo_rda **dev_op_dqo_rda,
struct gve_device_option_jumbo_frames **dev_op_jumbo_frames)
{ {
const int num_options = be16_to_cpu(descriptor->num_device_options); const int num_options = be16_to_cpu(descriptor->num_device_options);
struct gve_device_option *dev_opt; struct gve_device_option *dev_opt;
...@@ -146,7 +166,7 @@ gve_process_device_options(struct gve_priv *priv, ...@@ -146,7 +166,7 @@ gve_process_device_options(struct gve_priv *priv,
gve_parse_device_option(priv, descriptor, dev_opt, gve_parse_device_option(priv, descriptor, dev_opt,
dev_op_gqi_rda, dev_op_gqi_qpl, dev_op_gqi_rda, dev_op_gqi_qpl,
dev_op_dqo_rda); dev_op_dqo_rda, dev_op_jumbo_frames);
dev_opt = next_opt; dev_opt = next_opt;
} }
...@@ -661,12 +681,31 @@ gve_set_desc_cnt_dqo(struct gve_priv *priv, ...@@ -661,12 +681,31 @@ gve_set_desc_cnt_dqo(struct gve_priv *priv,
return 0; return 0;
} }
static void gve_enable_supported_features(struct gve_priv *priv,
u32 supported_features_mask,
const struct gve_device_option_jumbo_frames
*dev_op_jumbo_frames)
{
/* Before control reaches this point, the page-size-capped max MTU from
* the gve_device_descriptor field has already been stored in
* priv->dev->max_mtu. We overwrite it with the true max MTU below.
*/
if (dev_op_jumbo_frames &&
(supported_features_mask & GVE_SUP_JUMBO_FRAMES_MASK)) {
dev_info(&priv->pdev->dev,
"JUMBO FRAMES device option enabled.\n");
priv->dev->max_mtu = be16_to_cpu(dev_op_jumbo_frames->max_mtu);
}
}
int gve_adminq_describe_device(struct gve_priv *priv) int gve_adminq_describe_device(struct gve_priv *priv)
{ {
struct gve_device_option_jumbo_frames *dev_op_jumbo_frames = NULL;
struct gve_device_option_gqi_rda *dev_op_gqi_rda = NULL; struct gve_device_option_gqi_rda *dev_op_gqi_rda = NULL;
struct gve_device_option_gqi_qpl *dev_op_gqi_qpl = NULL; struct gve_device_option_gqi_qpl *dev_op_gqi_qpl = NULL;
struct gve_device_option_dqo_rda *dev_op_dqo_rda = NULL; struct gve_device_option_dqo_rda *dev_op_dqo_rda = NULL;
struct gve_device_descriptor *descriptor; struct gve_device_descriptor *descriptor;
u32 supported_features_mask = 0;
union gve_adminq_command cmd; union gve_adminq_command cmd;
dma_addr_t descriptor_bus; dma_addr_t descriptor_bus;
int err = 0; int err = 0;
...@@ -690,7 +729,8 @@ int gve_adminq_describe_device(struct gve_priv *priv) ...@@ -690,7 +729,8 @@ int gve_adminq_describe_device(struct gve_priv *priv)
goto free_device_descriptor; goto free_device_descriptor;
err = gve_process_device_options(priv, descriptor, &dev_op_gqi_rda, err = gve_process_device_options(priv, descriptor, &dev_op_gqi_rda,
&dev_op_gqi_qpl, &dev_op_dqo_rda); &dev_op_gqi_qpl, &dev_op_dqo_rda,
&dev_op_jumbo_frames);
if (err) if (err)
goto free_device_descriptor; goto free_device_descriptor;
...@@ -705,12 +745,19 @@ int gve_adminq_describe_device(struct gve_priv *priv) ...@@ -705,12 +745,19 @@ int gve_adminq_describe_device(struct gve_priv *priv)
priv->queue_format = GVE_DQO_RDA_FORMAT; priv->queue_format = GVE_DQO_RDA_FORMAT;
dev_info(&priv->pdev->dev, dev_info(&priv->pdev->dev,
"Driver is running with DQO RDA queue format.\n"); "Driver is running with DQO RDA queue format.\n");
supported_features_mask =
be32_to_cpu(dev_op_dqo_rda->supported_features_mask);
} else if (dev_op_gqi_rda) { } else if (dev_op_gqi_rda) {
priv->queue_format = GVE_GQI_RDA_FORMAT; priv->queue_format = GVE_GQI_RDA_FORMAT;
dev_info(&priv->pdev->dev, dev_info(&priv->pdev->dev,
"Driver is running with GQI RDA queue format.\n"); "Driver is running with GQI RDA queue format.\n");
supported_features_mask =
be32_to_cpu(dev_op_gqi_rda->supported_features_mask);
} else { } else {
priv->queue_format = GVE_GQI_QPL_FORMAT; priv->queue_format = GVE_GQI_QPL_FORMAT;
if (dev_op_gqi_qpl)
supported_features_mask =
be32_to_cpu(dev_op_gqi_qpl->supported_features_mask);
dev_info(&priv->pdev->dev, dev_info(&priv->pdev->dev,
"Driver is running with GQI QPL queue format.\n"); "Driver is running with GQI QPL queue format.\n");
} }
...@@ -747,6 +794,9 @@ int gve_adminq_describe_device(struct gve_priv *priv) ...@@ -747,6 +794,9 @@ int gve_adminq_describe_device(struct gve_priv *priv)
} }
priv->default_num_queues = be16_to_cpu(descriptor->default_num_queues); priv->default_num_queues = be16_to_cpu(descriptor->default_num_queues);
gve_enable_supported_features(priv, supported_features_mask,
dev_op_jumbo_frames);
free_device_descriptor: free_device_descriptor:
dma_free_coherent(&priv->pdev->dev, PAGE_SIZE, descriptor, dma_free_coherent(&priv->pdev->dev, PAGE_SIZE, descriptor,
descriptor_bus); descriptor_bus);
......
...@@ -108,6 +108,14 @@ struct gve_device_option_dqo_rda { ...@@ -108,6 +108,14 @@ struct gve_device_option_dqo_rda {
static_assert(sizeof(struct gve_device_option_dqo_rda) == 8); static_assert(sizeof(struct gve_device_option_dqo_rda) == 8);
struct gve_device_option_jumbo_frames {
__be32 supported_features_mask;
__be16 max_mtu;
u8 padding[2];
};
static_assert(sizeof(struct gve_device_option_jumbo_frames) == 8);
/* Terminology: /* Terminology:
* *
* RDA - Raw DMA Addressing - Buffers associated with SKBs are directly DMA * RDA - Raw DMA Addressing - Buffers associated with SKBs are directly DMA
...@@ -121,6 +129,7 @@ enum gve_dev_opt_id { ...@@ -121,6 +129,7 @@ enum gve_dev_opt_id {
GVE_DEV_OPT_ID_GQI_RDA = 0x2, GVE_DEV_OPT_ID_GQI_RDA = 0x2,
GVE_DEV_OPT_ID_GQI_QPL = 0x3, GVE_DEV_OPT_ID_GQI_QPL = 0x3,
GVE_DEV_OPT_ID_DQO_RDA = 0x4, GVE_DEV_OPT_ID_DQO_RDA = 0x4,
GVE_DEV_OPT_ID_JUMBO_FRAMES = 0x8,
}; };
enum gve_dev_opt_req_feat_mask { enum gve_dev_opt_req_feat_mask {
...@@ -128,6 +137,11 @@ enum gve_dev_opt_req_feat_mask { ...@@ -128,6 +137,11 @@ enum gve_dev_opt_req_feat_mask {
GVE_DEV_OPT_REQ_FEAT_MASK_GQI_RDA = 0x0, GVE_DEV_OPT_REQ_FEAT_MASK_GQI_RDA = 0x0,
GVE_DEV_OPT_REQ_FEAT_MASK_GQI_QPL = 0x0, GVE_DEV_OPT_REQ_FEAT_MASK_GQI_QPL = 0x0,
GVE_DEV_OPT_REQ_FEAT_MASK_DQO_RDA = 0x0, GVE_DEV_OPT_REQ_FEAT_MASK_DQO_RDA = 0x0,
GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES = 0x0,
};
enum gve_sup_feature_mask {
GVE_SUP_JUMBO_FRAMES_MASK = 1 << 2,
}; };
#define GVE_DEV_OPT_LEN_GQI_RAW_ADDRESSING 0x0 #define GVE_DEV_OPT_LEN_GQI_RAW_ADDRESSING 0x0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment