diff options
Diffstat (limited to 'src/plugins/avf')
-rw-r--r-- | src/plugins/avf/cli.c | 2 | ||||
-rw-r--r-- | src/plugins/avf/device.c | 56 | ||||
-rw-r--r-- | src/plugins/avf/virtchnl.h | 13 |
3 files changed, 68 insertions, 3 deletions
diff --git a/src/plugins/avf/cli.c b/src/plugins/avf/cli.c index 3ccf45aaf7e..bf4415177be 100644 --- a/src/plugins/avf/cli.c +++ b/src/plugins/avf/cli.c @@ -104,7 +104,7 @@ avf_delete_command_fn (vlib_main_t * vm, unformat_input_t * input, hw = vnet_get_sup_hw_interface (vnm, sw_if_index); if (hw == NULL || avf_device_class.index != hw->dev_class_index) - return clib_error_return (0, "not a AVF interface"); + return clib_error_return (0, "not an AVF interface"); ad = pool_elt_at_index (am->devices, hw->dev_instance); diff --git a/src/plugins/avf/device.c b/src/plugins/avf/device.c index 83a3d9cdb10..29dcb99bb4a 100644 --- a/src/plugins/avf/device.c +++ b/src/plugins/avf/device.c @@ -661,6 +661,46 @@ retry: } clib_error_t * +avf_request_queues (vlib_main_t * vm, avf_device_t * ad, u16 num_queue_pairs) +{ + virtchnl_vf_res_request_t res_req = { 0 }; + clib_error_t *error; + u32 rstat; + int n_retry = 20; + + res_req.num_queue_pairs = num_queue_pairs; + + error = avf_send_to_pf (vm, ad, VIRTCHNL_OP_REQUEST_QUEUES, &res_req, + sizeof (virtchnl_vf_res_request_t), &res_req, + sizeof (virtchnl_vf_res_request_t)); + + /* + * if PF respondes, the request failed + * else PF initializes restart and avf_send_to_pf returns an error + */ + if (!error) + { + return clib_error_return (0, "requested more than %u queue pairs", + res_req.num_queue_pairs); + } + +retry: + vlib_process_suspend (vm, 10e-3); + rstat = avf_get_u32 (ad->bar0, AVFGEN_RSTAT); + + if ((rstat == VIRTCHNL_VFR_COMPLETED) || (rstat == VIRTCHNL_VFR_VFACTIVE)) + goto done; + + if (--n_retry == 0) + return clib_error_return (0, "reset failed (timeout)"); + + goto retry; + +done: + return NULL; +} + +clib_error_t * avf_device_init (vlib_main_t * vm, avf_device_t * ad, avf_create_if_args_t * args) { @@ -672,8 +712,15 @@ avf_device_init (vlib_main_t * vm, avf_device_t * ad, avf_adminq_init (vm, ad); - if ((error = avf_device_reset (vm, ad))) - return error; + /* request more queues only if we need them */ + if ((error = avf_request_queues (vm, ad, tm->n_vlib_mains))) + { + /* we failed to get more queues, but still we want to proceed */ + clib_error_free (error); + + if ((error = avf_device_reset (vm, ad))) + return error; + } avf_adminq_init (vm, ad); @@ -768,6 +815,11 @@ avf_process_one_device (vlib_main_t * vm, avf_device_t * ad, int is_irq) ASSERT (ad->error == 0); + /* do not process device in reset state */ + r = avf_get_u32 (ad->bar0, AVFGEN_RSTAT); + if (r != VIRTCHNL_VFR_VFACTIVE) + return; + r = avf_get_u32 (ad->bar0, AVF_ARQLEN); if ((r & 0xf0000000) != (1ULL << 31)) { diff --git a/src/plugins/avf/virtchnl.h b/src/plugins/avf/virtchnl.h index f016110b53e..c501ddd3733 100644 --- a/src/plugins/avf/virtchnl.h +++ b/src/plugins/avf/virtchnl.h @@ -132,6 +132,13 @@ typedef enum VIRTCHNL_VSI_SRIOV = 6, } virtchnl_vsi_type_t; +typedef enum +{ + VIRTCHNL_VFR_INPROGRESS = 0, + VIRTCHNL_VFR_COMPLETED, + VIRTCHNL_VFR_VFACTIVE, +} virtchnl_vfr_states_t; + typedef struct { u16 vsi_id; @@ -355,6 +362,12 @@ typedef struct STATIC_ASSERT_SIZEOF (virtchnl_rss_lut_t, 6); +/* VIRTCHNL_OP_REQUEST_QUEUES */ +typedef struct +{ + u16 num_queue_pairs; +} virtchnl_vf_res_request_t; + #endif /* AVF_VIRTCHNL_H */ /* |