Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/gve/gve_adminq.c
| Show First 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
| 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_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) | 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 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | case GVE_DEV_OPT_ID_DQO_QPL: | ||||
| if (option_length > sizeof(**dev_op_dqo_qpl)) { | if (option_length > sizeof(**dev_op_dqo_qpl)) { | ||||
| device_printf(priv->dev, GVE_DEVICE_OPTION_TOO_BIG_FMT, | device_printf(priv->dev, GVE_DEVICE_OPTION_TOO_BIG_FMT, | ||||
| "DQO QPL"); | "DQO QPL"); | ||||
| } | } | ||||
| *dev_op_dqo_qpl = (void *)(option + 1); | *dev_op_dqo_qpl = (void *)(option + 1); | ||||
| break; | 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: | 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 18 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_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) | 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_gqi_qpl, | ||||
| dev_op_dqo_rda, | dev_op_dqo_rda, | ||||
| dev_op_dqo_qpl, | dev_op_dqo_qpl, | ||||
| dev_op_modify_ring, | |||||
| dev_op_jumbo_frames); | 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, | ||||
| ▲ Show 20 Lines • Show All 198 Lines • ▼ Show 20 Lines | gve_adminq_set_mtu(struct gve_priv *priv, uint32_t mtu) { | ||||
| }; | }; | ||||
| return (gve_adminq_execute_cmd(priv, &cmd)); | return (gve_adminq_execute_cmd(priv, &cmd)); | ||||
| } | } | ||||
| static void | static void | ||||
| gve_enable_supported_features(struct gve_priv *priv, | gve_enable_supported_features(struct gve_priv *priv, | ||||
| uint32_t supported_features_mask, | uint32_t supported_features_mask, | ||||
| const struct gve_device_option_modify_ring *dev_op_modify_ring, | |||||
| const struct gve_device_option_jumbo_frames *dev_op_jumbo_frames) | const struct gve_device_option_jumbo_frames *dev_op_jumbo_frames) | ||||
| { | { | ||||
| if (dev_op_modify_ring && | |||||
| (supported_features_mask & GVE_SUP_MODIFY_RING_MASK)) { | |||||
| if (bootverbose) | |||||
| device_printf(priv->dev, "MODIFY RING device option enabled.\n"); | |||||
| priv->modify_ringsize_enabled = true; | |||||
| priv->max_rx_desc_cnt = be16toh(dev_op_modify_ring->max_ring_size.rx); | |||||
| priv->max_tx_desc_cnt = be16toh(dev_op_modify_ring->max_ring_size.tx); | |||||
| } | |||||
| if (dev_op_jumbo_frames && | if (dev_op_jumbo_frames && | ||||
| (supported_features_mask & GVE_SUP_JUMBO_FRAMES_MASK)) { | (supported_features_mask & GVE_SUP_JUMBO_FRAMES_MASK)) { | ||||
| if (bootverbose) | if (bootverbose) | ||||
| device_printf(priv->dev, "JUMBO FRAMES device option enabled: %u.\n", | device_printf(priv->dev, "JUMBO FRAMES device option enabled: %u.\n", | ||||
| be16toh(dev_op_jumbo_frames->max_mtu)); | be16toh(dev_op_jumbo_frames->max_mtu)); | ||||
| priv->max_mtu = be16toh(dev_op_jumbo_frames->max_mtu); | priv->max_mtu = be16toh(dev_op_jumbo_frames->max_mtu); | ||||
| } | } | ||||
| } | } | ||||
| 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_dqo_qpl *dev_op_dqo_qpl = NULL; | ||||
| struct gve_device_option_modify_ring *dev_op_modify_ring = 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 12 Lines | gve_adminq_describe_device(struct gve_priv *priv) | ||||
| bus_dmamap_sync(desc_mem.tag, desc_mem.map, BUS_DMASYNC_PREWRITE); | bus_dmamap_sync(desc_mem.tag, desc_mem.map, BUS_DMASYNC_PREWRITE); | ||||
| 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); | ||||
| /* Default min in case device options don't have min values */ | |||||
| priv->min_rx_desc_cnt = GVE_DEFAULT_MIN_RX_RING_SIZE; | |||||
| priv->min_tx_desc_cnt = GVE_DEFAULT_MIN_TX_RING_SIZE; | |||||
| rc = gve_process_device_options(priv, desc, | rc = gve_process_device_options(priv, desc, | ||||
| &dev_op_gqi_qpl, | &dev_op_gqi_qpl, | ||||
| &dev_op_dqo_rda, | &dev_op_dqo_rda, | ||||
| &dev_op_dqo_qpl, | &dev_op_dqo_qpl, | ||||
| &dev_op_modify_ring, | |||||
| &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; | ||||
| Show All 31 Lines | gve_adminq_describe_device(struct gve_priv *priv) | ||||
| priv->tx_desc_cnt = be16toh(desc->tx_queue_entries); | priv->tx_desc_cnt = be16toh(desc->tx_queue_entries); | ||||
| priv->rx_desc_cnt = be16toh(desc->rx_queue_entries); | priv->rx_desc_cnt = be16toh(desc->rx_queue_entries); | ||||
| priv->rx_pages_per_qpl = be16toh(desc->rx_pages_per_qpl); | priv->rx_pages_per_qpl = be16toh(desc->rx_pages_per_qpl); | ||||
| priv->max_registered_pages = be64toh(desc->max_registered_pages); | priv->max_registered_pages = be64toh(desc->max_registered_pages); | ||||
| priv->max_mtu = be16toh(desc->mtu); | priv->max_mtu = be16toh(desc->mtu); | ||||
| priv->default_num_queues = be16toh(desc->default_num_queues); | priv->default_num_queues = be16toh(desc->default_num_queues); | ||||
| priv->supported_features = supported_features_mask; | priv->supported_features = supported_features_mask; | ||||
| /* Default max to current in case modify ring size option is disabled */ | |||||
| priv->max_rx_desc_cnt = priv->rx_desc_cnt; | |||||
| priv->max_tx_desc_cnt = priv->tx_desc_cnt; | |||||
| gve_enable_supported_features(priv, supported_features_mask, | gve_enable_supported_features(priv, supported_features_mask, | ||||
| dev_op_jumbo_frames); | dev_op_modify_ring, dev_op_jumbo_frames); | ||||
| for (i = 0; i < ETHER_ADDR_LEN; i++) | for (i = 0; i < ETHER_ADDR_LEN; i++) | ||||
| priv->mac[i] = desc->mac[i]; | priv->mac[i] = desc->mac[i]; | ||||
| free_device_descriptor: | free_device_descriptor: | ||||
| gve_dma_free_coherent(&desc_mem); | gve_dma_free_coherent(&desc_mem); | ||||
| return (rc); | return (rc); | ||||
| ▲ Show 20 Lines • Show All 437 Lines • Show Last 20 Lines | |||||