void gve_parse_device_option()

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);
	}
}