in gve_adminq.c [56:178]
void gve_parse_device_option(struct gve_priv *priv,
struct gve_device_descriptor *device_descriptor,
struct gve_device_option *option,
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_qpl **dev_op_dqo_qpl,
struct gve_device_option_modify_ring **dev_op_modify_ring,
struct gve_device_option_jumbo_frames **dev_op_jumbo_frames)
{
uint32_t req_feat_mask = be32toh(option->required_features_mask);
uint16_t option_length = be16toh(option->option_length);
uint16_t option_id = be16toh(option->option_id);
/*
* If the length or feature mask doesn't match, continue without
* enabling the feature.
*/
switch (option_id) {
case GVE_DEV_OPT_ID_GQI_QPL:
if (option_length < sizeof(**dev_op_gqi_qpl) ||
req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_GQI_QPL) {
device_printf(priv->dev, GVE_DEVICE_OPTION_ERROR_FMT,
"GQI QPL", (int)sizeof(**dev_op_gqi_qpl),
GVE_DEV_OPT_REQ_FEAT_MASK_GQI_QPL,
option_length, req_feat_mask);
break;
}
if (option_length > sizeof(**dev_op_gqi_qpl)) {
device_printf(priv->dev, GVE_DEVICE_OPTION_TOO_BIG_FMT,
"GQI QPL");
}
*dev_op_gqi_qpl = (void *)(option + 1);
break;
case GVE_DEV_OPT_ID_DQO_RDA:
if (option_length < sizeof(**dev_op_dqo_rda) ||
req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_DQO_RDA) {
device_printf(priv->dev, GVE_DEVICE_OPTION_ERROR_FMT,
"DQO RDA", (int)sizeof(**dev_op_dqo_rda),
GVE_DEV_OPT_REQ_FEAT_MASK_DQO_RDA,
option_length, req_feat_mask);
break;
}
if (option_length > sizeof(**dev_op_dqo_rda)) {
device_printf(priv->dev, GVE_DEVICE_OPTION_TOO_BIG_FMT,
"DQO RDA");
}
*dev_op_dqo_rda = (void *)(option + 1);
break;
case GVE_DEV_OPT_ID_DQO_QPL:
if (option_length < sizeof(**dev_op_dqo_qpl) ||
req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_DQO_QPL) {
device_printf(priv->dev, GVE_DEVICE_OPTION_ERROR_FMT,
"DQO QPL", (int)sizeof(**dev_op_dqo_qpl),
GVE_DEV_OPT_REQ_FEAT_MASK_DQO_QPL,
option_length, req_feat_mask);
break;
}
if (option_length > sizeof(**dev_op_dqo_qpl)) {
device_printf(priv->dev, GVE_DEVICE_OPTION_TOO_BIG_FMT,
"DQO QPL");
}
*dev_op_dqo_qpl = (void *)(option + 1);
break;
case GVE_DEV_OPT_ID_MODIFY_RING:
if (option_length < (sizeof(**dev_op_modify_ring) -
sizeof(struct gve_ring_size_bound)) ||
req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING) {
device_printf(priv->dev, GVE_DEVICE_OPTION_ERROR_FMT,
"Modify Ring", (int)sizeof(**dev_op_modify_ring),
GVE_DEV_OPT_REQ_FEAT_MASK_MODIFY_RING,
option_length, req_feat_mask);
break;
}
if (option_length > sizeof(**dev_op_modify_ring)) {
device_printf(priv->dev, GVE_DEVICE_OPTION_TOO_BIG_FMT,
"Modify Ring");
}
*dev_op_modify_ring = (void *)(option + 1);
/* Min ring size included; set the minimum ring size. */
if (option_length == sizeof(**dev_op_modify_ring)) {
priv->min_rx_desc_cnt = max(
be16toh((*dev_op_modify_ring)->min_ring_size.rx),
GVE_DEFAULT_MIN_RX_RING_SIZE);
priv->min_tx_desc_cnt = max(
be16toh((*dev_op_modify_ring)->min_ring_size.tx),
GVE_DEFAULT_MIN_TX_RING_SIZE);
}
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) {
device_printf(priv->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)) {
device_printf(priv->dev,
GVE_DEVICE_OPTION_TOO_BIG_FMT, "Jumbo Frames");
}
*dev_op_jumbo_frames = (void *)(option + 1);
break;
default:
/*
* If we don't recognize the option just continue
* without doing anything.
*/
device_printf(priv->dev, "Unrecognized device option 0x%hx not enabled.\n",
option_id);
}
}