Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/gve/gve_adminq.c
Show First 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | #define GVE_DEVICE_OPTION_TOO_BIG_FMT "Length of %s option larger than expected." \ | ||||
" Possible older version of guest driver.\n" | " Possible older version of guest driver.\n" | ||||
static | static | ||||
void gve_parse_device_option(struct gve_priv *priv, | void gve_parse_device_option(struct gve_priv *priv, | ||||
struct gve_device_descriptor *device_descriptor, | struct gve_device_descriptor *device_descriptor, | ||||
struct gve_device_option *option, | struct gve_device_option *option, | ||||
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_dqo_qpl **dev_op_dqo_qpl, | |||||
struct gve_device_option_jumbo_frames **dev_op_jumbo_frames) | struct gve_device_option_jumbo_frames **dev_op_jumbo_frames) | ||||
{ | { | ||||
uint32_t req_feat_mask = be32toh(option->required_features_mask); | uint32_t req_feat_mask = be32toh(option->required_features_mask); | ||||
uint16_t option_length = be16toh(option->option_length); | uint16_t option_length = be16toh(option->option_length); | ||||
uint16_t option_id = be16toh(option->option_id); | uint16_t option_id = be16toh(option->option_id); | ||||
/* | /* | ||||
* If the length or feature mask doesn't match, continue without | * If the length or feature mask doesn't match, continue without | ||||
Show All 29 Lines | case GVE_DEV_OPT_ID_DQO_RDA: | ||||
if (option_length > sizeof(**dev_op_dqo_rda)) { | if (option_length > sizeof(**dev_op_dqo_rda)) { | ||||
device_printf(priv->dev, GVE_DEVICE_OPTION_TOO_BIG_FMT, | device_printf(priv->dev, GVE_DEVICE_OPTION_TOO_BIG_FMT, | ||||
"DQO RDA"); | "DQO RDA"); | ||||
} | } | ||||
*dev_op_dqo_rda = (void *)(option + 1); | *dev_op_dqo_rda = (void *)(option + 1); | ||||
break; | 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_JUMBO_FRAMES: | case GVE_DEV_OPT_ID_JUMBO_FRAMES: | ||||
if (option_length < sizeof(**dev_op_jumbo_frames) || | if (option_length < sizeof(**dev_op_jumbo_frames) || | ||||
req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES) { | req_feat_mask != GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES) { | ||||
device_printf(priv->dev, GVE_DEVICE_OPTION_ERROR_FMT, | device_printf(priv->dev, GVE_DEVICE_OPTION_ERROR_FMT, | ||||
"Jumbo Frames", (int)sizeof(**dev_op_jumbo_frames), | "Jumbo Frames", (int)sizeof(**dev_op_jumbo_frames), | ||||
GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES, | GVE_DEV_OPT_REQ_FEAT_MASK_JUMBO_FRAMES, | ||||
option_length, req_feat_mask); | option_length, req_feat_mask); | ||||
break; | break; | ||||
Show All 17 Lines | |||||
} | } | ||||
/* Process all device options for a given describe device call. */ | /* Process all device options for a given describe device call. */ | ||||
static int | static int | ||||
gve_process_device_options(struct gve_priv *priv, | gve_process_device_options(struct gve_priv *priv, | ||||
struct gve_device_descriptor *descriptor, | struct gve_device_descriptor *descriptor, | ||||
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_dqo_qpl **dev_op_dqo_qpl, | |||||
struct gve_device_option_jumbo_frames **dev_op_jumbo_frames) | struct gve_device_option_jumbo_frames **dev_op_jumbo_frames) | ||||
{ | { | ||||
char *desc_end = (char *)descriptor + be16toh(descriptor->total_length); | char *desc_end = (char *)descriptor + be16toh(descriptor->total_length); | ||||
const int num_options = be16toh(descriptor->num_device_options); | const int num_options = be16toh(descriptor->num_device_options); | ||||
struct gve_device_option *dev_opt; | struct gve_device_option *dev_opt; | ||||
int i; | int i; | ||||
/* The options struct directly follows the device descriptor. */ | /* The options struct directly follows the device descriptor. */ | ||||
dev_opt = (void *)(descriptor + 1); | dev_opt = (void *)(descriptor + 1); | ||||
for (i = 0; i < num_options; i++) { | for (i = 0; i < num_options; i++) { | ||||
if ((char *)(dev_opt + 1) > desc_end || | if ((char *)(dev_opt + 1) > desc_end || | ||||
(char *)(dev_opt + 1) + be16toh(dev_opt->option_length) > desc_end) { | (char *)(dev_opt + 1) + be16toh(dev_opt->option_length) > desc_end) { | ||||
device_printf(priv->dev, | device_printf(priv->dev, | ||||
"options exceed device descriptor's total length.\n"); | "options exceed device descriptor's total length.\n"); | ||||
return (EINVAL); | return (EINVAL); | ||||
} | } | ||||
gve_parse_device_option(priv, descriptor, dev_opt, | gve_parse_device_option(priv, descriptor, dev_opt, | ||||
dev_op_gqi_qpl, dev_op_dqo_rda, dev_op_jumbo_frames); | dev_op_gqi_qpl, | ||||
dev_op_dqo_rda, | |||||
dev_op_dqo_qpl, | |||||
dev_op_jumbo_frames); | |||||
dev_opt = (void *)((char *)(dev_opt + 1) + be16toh(dev_opt->option_length)); | dev_opt = (void *)((char *)(dev_opt + 1) + be16toh(dev_opt->option_length)); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
static int gve_adminq_execute_cmd(struct gve_priv *priv, | static int gve_adminq_execute_cmd(struct gve_priv *priv, | ||||
struct gve_adminq_command *cmd); | struct gve_adminq_command *cmd); | ||||
▲ Show 20 Lines • Show All 216 Lines • ▼ Show 20 Lines | |||||
int | int | ||||
gve_adminq_describe_device(struct gve_priv *priv) | gve_adminq_describe_device(struct gve_priv *priv) | ||||
{ | { | ||||
struct gve_adminq_command aq_cmd = (struct gve_adminq_command){}; | struct gve_adminq_command aq_cmd = (struct gve_adminq_command){}; | ||||
struct gve_device_descriptor *desc; | struct gve_device_descriptor *desc; | ||||
struct gve_dma_handle desc_mem; | struct gve_dma_handle desc_mem; | ||||
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_option_dqo_qpl *dev_op_dqo_qpl = NULL; | |||||
struct gve_device_option_jumbo_frames *dev_op_jumbo_frames = NULL; | struct gve_device_option_jumbo_frames *dev_op_jumbo_frames = NULL; | ||||
uint32_t supported_features_mask = 0; | uint32_t supported_features_mask = 0; | ||||
int rc; | int rc; | ||||
int i; | int i; | ||||
rc = gve_dma_alloc_coherent(priv, ADMINQ_SIZE, ADMINQ_SIZE, &desc_mem); | rc = gve_dma_alloc_coherent(priv, ADMINQ_SIZE, ADMINQ_SIZE, &desc_mem); | ||||
if (rc != 0) { | if (rc != 0) { | ||||
device_printf(priv->dev, "Failed to alloc DMA mem for DescribeDevice.\n"); | device_printf(priv->dev, "Failed to alloc DMA mem for DescribeDevice.\n"); | ||||
Show All 13 Lines | gve_adminq_describe_device(struct gve_priv *priv) | ||||
rc = gve_adminq_execute_cmd(priv, &aq_cmd); | rc = gve_adminq_execute_cmd(priv, &aq_cmd); | ||||
if (rc != 0) | if (rc != 0) | ||||
goto free_device_descriptor; | goto free_device_descriptor; | ||||
bus_dmamap_sync(desc_mem.tag, desc_mem.map, BUS_DMASYNC_POSTREAD); | bus_dmamap_sync(desc_mem.tag, desc_mem.map, BUS_DMASYNC_POSTREAD); | ||||
rc = gve_process_device_options(priv, desc, | rc = gve_process_device_options(priv, desc, | ||||
&dev_op_gqi_qpl, &dev_op_dqo_rda, | &dev_op_gqi_qpl, | ||||
&dev_op_dqo_rda, | |||||
&dev_op_dqo_qpl, | |||||
&dev_op_jumbo_frames); | &dev_op_jumbo_frames); | ||||
if (rc != 0) | if (rc != 0) | ||||
goto free_device_descriptor; | goto free_device_descriptor; | ||||
if (dev_op_dqo_rda != NULL) { | if (dev_op_dqo_rda != NULL) { | ||||
snprintf(gve_queue_format, sizeof(gve_queue_format), | snprintf(gve_queue_format, sizeof(gve_queue_format), | ||||
"%s", "DQO RDA"); | "%s", "DQO RDA"); | ||||
priv->queue_format = GVE_DQO_RDA_FORMAT; | priv->queue_format = GVE_DQO_RDA_FORMAT; | ||||
supported_features_mask = be32toh( | supported_features_mask = be32toh( | ||||
dev_op_dqo_rda->supported_features_mask); | dev_op_dqo_rda->supported_features_mask); | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(priv->dev, | device_printf(priv->dev, | ||||
"Driver is running with DQO RDA queue format.\n"); | "Driver is running with DQO RDA queue format.\n"); | ||||
} else if (dev_op_dqo_qpl != NULL) { | |||||
snprintf(gve_queue_format, sizeof(gve_queue_format), | |||||
"%s", "DQO QPL"); | |||||
priv->queue_format = GVE_DQO_QPL_FORMAT; | |||||
supported_features_mask = be32toh( | |||||
dev_op_dqo_qpl->supported_features_mask); | |||||
if (bootverbose) | |||||
device_printf(priv->dev, | |||||
"Driver is running with DQO QPL queue format.\n"); | |||||
} else if (dev_op_gqi_qpl != NULL) { | } else if (dev_op_gqi_qpl != NULL) { | ||||
snprintf(gve_queue_format, sizeof(gve_queue_format), | snprintf(gve_queue_format, sizeof(gve_queue_format), | ||||
"%s", "GQI QPL"); | "%s", "GQI QPL"); | ||||
priv->queue_format = GVE_GQI_QPL_FORMAT; | priv->queue_format = GVE_GQI_QPL_FORMAT; | ||||
supported_features_mask = be32toh( | supported_features_mask = be32toh( | ||||
dev_op_gqi_qpl->supported_features_mask); | dev_op_gqi_qpl->supported_features_mask); | ||||
if (bootverbose) | if (bootverbose) | ||||
device_printf(priv->dev, | device_printf(priv->dev, | ||||
▲ Show 20 Lines • Show All 464 Lines • Show Last 20 Lines |