X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fplugins%2Favf%2Fdevice.c;h=914c32cab4b3f95c538d3f47437bcdc5ad1633c0;hb=b7b929931a07fbb27b43d5cd105f366c3e29807e;hp=a08a952dd04aec2024d9c3695b47903e6b962165;hpb=02ff5f7ce08a13477ffaae5c413a0de6aac68afd;p=vpp.git diff --git a/src/plugins/avf/device.c b/src/plugins/avf/device.c index a08a952dd04..914c32cab4b 100644 --- a/src/plugins/avf/device.c +++ b/src/plugins/avf/device.c @@ -213,7 +213,7 @@ avf_cmd_rx_ctl_reg_write (vlib_main_t * vm, avf_device_t * ad, u32 reg, } clib_error_t * -avf_rxq_init (vlib_main_t * vm, avf_device_t * ad, u16 qid) +avf_rxq_init (vlib_main_t * vm, avf_device_t * ad, u16 qid, u16 rxq_size) { avf_main_t *am = &avf_main; avf_rxq_t *rxq; @@ -222,12 +222,12 @@ avf_rxq_init (vlib_main_t * vm, avf_device_t * ad, u16 qid) vec_validate_aligned (ad->rxqs, qid, CLIB_CACHE_LINE_BYTES); rxq = vec_elt_at_index (ad->rxqs, qid); - rxq->size = AVF_RXQ_SZ; + rxq->size = rxq_size; rxq->next = 0; rxq->descs = vlib_physmem_alloc_aligned (vm, am->physmem_region, &error, rxq->size * sizeof (avf_rx_desc_t), 2 * CLIB_CACHE_LINE_BYTES); - memset (rxq->descs, 0, rxq->size * sizeof (avf_rx_desc_t)); + clib_memset ((void *) rxq->descs, 0, rxq->size * sizeof (avf_rx_desc_t)); vec_validate_aligned (rxq->bufs, rxq->size, CLIB_CACHE_LINE_BYTES); rxq->qrx_tail = ad->bar0 + AVF_QRX_TAIL (qid); @@ -236,25 +236,24 @@ avf_rxq_init (vlib_main_t * vm, avf_device_t * ad, u16 qid) if (n_alloc == 0) return clib_error_return (0, "buffer allocation error"); - rxq->n_bufs = n_alloc; + rxq->n_enqueued = n_alloc; avf_rx_desc_t *d = rxq->descs; for (i = 0; i < n_alloc; i++) { + vlib_buffer_t *b = vlib_get_buffer (vm, rxq->bufs[i]); if (ad->flags & AVF_DEVICE_F_IOVA) - { - vlib_buffer_t *b = vlib_get_buffer (vm, rxq->bufs[i]); - d->qword[0] = pointer_to_uword (b->data); - } + d->qword[0] = vlib_buffer_get_va (b); else - d->qword[0] = - vlib_get_buffer_data_physical_address (vm, rxq->bufs[i]); + d->qword[0] = vlib_buffer_get_pa (vm, b); d++; } + + ad->n_rx_queues = clib_min (ad->num_queue_pairs, qid + 1); return 0; } clib_error_t * -avf_txq_init (vlib_main_t * vm, avf_device_t * ad, u16 qid) +avf_txq_init (vlib_main_t * vm, avf_device_t * ad, u16 qid, u16 txq_size) { avf_main_t *am = &avf_main; avf_txq_t *txq; @@ -272,13 +271,15 @@ avf_txq_init (vlib_main_t * vm, avf_device_t * ad, u16 qid) vec_validate_aligned (ad->txqs, qid, CLIB_CACHE_LINE_BYTES); txq = vec_elt_at_index (ad->txqs, qid); - txq->size = AVF_TXQ_SZ; + txq->size = txq_size; txq->next = 0; txq->descs = vlib_physmem_alloc_aligned (vm, am->physmem_region, &error, txq->size * sizeof (avf_tx_desc_t), 2 * CLIB_CACHE_LINE_BYTES); vec_validate_aligned (txq->bufs, txq->size, CLIB_CACHE_LINE_BYTES); txq->qtx_tail = ad->bar0 + AVF_QTX_TAIL (qid); + + ad->n_tx_queues = clib_min (ad->num_queue_pairs, qid + 1); return 0; } @@ -294,7 +295,7 @@ avf_arq_slot_init (avf_device_t * ad, u16 slot) avf_aq_desc_t *d; u64 pa = ad->arq_bufs_pa + slot * AVF_MBOX_BUF_SZ; d = &ad->arq[slot]; - memset (d, 0, sizeof (avf_aq_desc_t)); + clib_memset (d, 0, sizeof (avf_aq_desc_t)); d->flags = AVF_AQ_F_BUF; d->datalen = AVF_MBOX_BUF_SZ; d->addr_hi = (u32) (pa >> 32); @@ -317,18 +318,18 @@ avf_adminq_init (vlib_main_t * vm, avf_device_t * ad) int i; /* VF MailBox Transmit */ - memset (ad->atq, 0, sizeof (avf_aq_desc_t) * AVF_MBOX_LEN); + clib_memset (ad->atq, 0, sizeof (avf_aq_desc_t) * AVF_MBOX_LEN); ad->atq_bufs_pa = avf_dma_addr (vm, ad, ad->atq_bufs); pa = avf_dma_addr (vm, ad, ad->atq); avf_reg_write (ad, AVF_ATQT, 0); /* Tail */ avf_reg_write (ad, AVF_ATQH, 0); /* Head */ - avf_reg_write (ad, AVF_ATQLEN, AVF_MBOX_LEN | (1 << 31)); /* len & ena */ + avf_reg_write (ad, AVF_ATQLEN, AVF_MBOX_LEN | (1ULL << 31)); /* len & ena */ avf_reg_write (ad, AVF_ATQBAL, (u32) pa); /* Base Address Low */ avf_reg_write (ad, AVF_ATQBAH, (u32) (pa >> 32)); /* Base Address High */ /* VF MailBox Receive */ - memset (ad->arq, 0, sizeof (avf_aq_desc_t) * AVF_MBOX_LEN); + clib_memset (ad->arq, 0, sizeof (avf_aq_desc_t) * AVF_MBOX_LEN); ad->arq_bufs_pa = avf_dma_addr (vm, ad, ad->arq_bufs); for (i = 0; i < AVF_MBOX_LEN; i++) @@ -338,7 +339,7 @@ avf_adminq_init (vlib_main_t * vm, avf_device_t * ad) avf_reg_write (ad, AVF_ARQH, 0); /* Head */ avf_reg_write (ad, AVF_ARQT, 0); /* Head */ - avf_reg_write (ad, AVF_ARQLEN, AVF_MBOX_LEN | (1 << 31)); /* len & ena */ + avf_reg_write (ad, AVF_ARQLEN, AVF_MBOX_LEN | (1ULL << 31)); /* len & ena */ avf_reg_write (ad, AVF_ARQBAL, (u32) pa); /* Base Address Low */ avf_reg_write (ad, AVF_ARQBAH, (u32) (pa >> 32)); /* Base Address High */ avf_reg_write (ad, AVF_ARQT, AVF_MBOX_LEN - 1); /* Tail */ @@ -398,8 +399,11 @@ retry: if (d->v_opcode != op) { - err = clib_error_return (0, "unexpected message receiver [v_opcode = %u" - "expected %u]", d->v_opcode, op); + err = + clib_error_return (0, + "unexpected message receiver [v_opcode = %u, " + "expected %u, v_retval %d]", d->v_opcode, op, + d->v_retval); goto done; } @@ -490,18 +494,41 @@ clib_error_t * avf_op_config_rss_lut (vlib_main_t * vm, avf_device_t * ad) { int msg_len = sizeof (virtchnl_rss_lut_t) + ad->rss_lut_size - 1; + int i; u8 msg[msg_len]; virtchnl_rss_lut_t *rl; - memset (msg, 0, msg_len); + clib_memset (msg, 0, msg_len); rl = (virtchnl_rss_lut_t *) msg; rl->vsi_id = ad->vsi_id; rl->lut_entries = ad->rss_lut_size; + for (i = 0; i < ad->rss_lut_size; i++) + rl->lut[i] = i % ad->n_rx_queues; return avf_send_to_pf (vm, ad, VIRTCHNL_OP_CONFIG_RSS_LUT, msg, msg_len, 0, 0); } +clib_error_t * +avf_op_config_rss_key (vlib_main_t * vm, avf_device_t * ad) +{ + int msg_len = sizeof (virtchnl_rss_key_t) + ad->rss_key_size - 1; + int i; + u8 msg[msg_len]; + virtchnl_rss_key_t *rk; + + clib_memset (msg, 0, msg_len); + rk = (virtchnl_rss_key_t *) msg; + rk->vsi_id = ad->vsi_id; + rk->key_len = ad->rss_key_size; + u32 seed = random_default_seed (); + for (i = 0; i < ad->rss_key_size; i++) + rk->key[i] = (u8) random_u32 (&seed); + + return avf_send_to_pf (vm, ad, VIRTCHNL_OP_CONFIG_RSS_KEY, msg, msg_len, 0, + 0); +} + clib_error_t * avf_op_disable_vlan_stripping (vlib_main_t * vm, avf_device_t * ad) { @@ -531,7 +558,7 @@ avf_op_config_vsi_queues (vlib_main_t * vm, avf_device_t * ad) u8 msg[msg_len]; virtchnl_vsi_queue_config_info_t *ci; - memset (msg, 0, msg_len); + clib_memset (msg, 0, msg_len); ci = (virtchnl_vsi_queue_config_info_t *) msg; ci->vsi_id = ad->vsi_id; ci->num_queue_pairs = n_qp; @@ -549,7 +576,7 @@ avf_op_config_vsi_queues (vlib_main_t * vm, avf_device_t * ad) avf_rxq_t *q = vec_elt_at_index (ad->rxqs, i); rxq->ring_len = q->size; rxq->databuffer_size = VLIB_BUFFER_DEFAULT_FREE_LIST_BYTES; - rxq->dma_ring_addr = avf_dma_addr (vm, ad, q->descs); + rxq->dma_ring_addr = avf_dma_addr (vm, ad, (void *) q->descs); avf_reg_write (ad, AVF_QRX_TAIL (i), q->size - 1); } @@ -559,7 +586,7 @@ avf_op_config_vsi_queues (vlib_main_t * vm, avf_device_t * ad) { txq->queue_id = i; txq->ring_len = q->size; - txq->dma_ring_addr = avf_dma_addr (vm, ad, q->descs); + txq->dma_ring_addr = avf_dma_addr (vm, ad, (void *) q->descs); } } @@ -576,7 +603,7 @@ avf_op_config_irq_map (vlib_main_t * vm, avf_device_t * ad) u8 msg[msg_len]; virtchnl_irq_map_info_t *imi; - memset (msg, 0, msg_len); + clib_memset (msg, 0, msg_len); imi = (virtchnl_irq_map_info_t *) msg; imi->num_vectors = count; @@ -597,7 +624,7 @@ avf_op_add_eth_addr (vlib_main_t * vm, avf_device_t * ad, u8 count, u8 * macs) virtchnl_ether_addr_list_t *al; int i; - memset (msg, 0, msg_len); + clib_memset (msg, 0, msg_len); al = (virtchnl_ether_addr_list_t *) msg; al->vsi_id = ad->vsi_id; al->num_elements = count; @@ -611,11 +638,15 @@ clib_error_t * avf_op_enable_queues (vlib_main_t * vm, avf_device_t * ad, u32 rx, u32 tx) { virtchnl_queue_select_t qs = { 0 }; + int i; qs.vsi_id = ad->vsi_id; qs.rx_queues = rx; qs.tx_queues = tx; - avf_rxq_t *rxq = vec_elt_at_index (ad->rxqs, 0); - avf_reg_write (ad, AVF_QRX_TAIL (0), rxq->n_bufs); + for (i = 0; i < ad->n_rx_queues; i++) + { + avf_rxq_t *rxq = vec_elt_at_index (ad->rxqs, i); + avf_reg_write (ad, AVF_QRX_TAIL (i), rxq->n_enqueued); + } return avf_send_to_pf (vm, ad, VIRTCHNL_OP_ENABLE_QUEUES, &qs, sizeof (virtchnl_queue_select_t), 0, 0); } @@ -658,7 +689,48 @@ retry: } clib_error_t * -avf_device_init (vlib_main_t * vm, avf_device_t * ad) +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_main_t * am, avf_device_t * ad, + avf_create_if_args_t * args) { virtchnl_version_info_t ver = { 0 }; virtchnl_vf_resource_t res = { 0 }; @@ -668,8 +740,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); @@ -712,20 +791,37 @@ avf_device_init (vlib_main_t * vm, avf_device_t * ad) if ((error = avf_config_promisc_mode (vm, ad))) return error; - if ((ad->feature_bitmap & VIRTCHNL_VF_OFFLOAD_RSS_PF) && - (error = avf_op_config_rss_lut (vm, ad))) - return error; - /* * Init Queues */ - if ((error = avf_rxq_init (vm, ad, 0))) - return error; + if (args->rxq_num == 0) + { + args->rxq_num = 1; + } + else if (args->rxq_num > ad->num_queue_pairs) + { + args->rxq_num = ad->num_queue_pairs; + vlib_log_warn (am->log_class, "Requested more rx queues than" + "queue pairs available. Using %u rx queues.", + args->rxq_num); + } + + for (i = 0; i < args->rxq_num; i++) + if ((error = avf_rxq_init (vm, ad, i, args->rxq_size))) + return error; for (i = 0; i < tm->n_vlib_mains; i++) - if ((error = avf_txq_init (vm, ad, i))) + if ((error = avf_txq_init (vm, ad, i, args->txq_size))) return error; + if ((ad->feature_bitmap & VIRTCHNL_VF_OFFLOAD_RSS_PF) && + (error = avf_op_config_rss_lut (vm, ad))) + return error; + + if ((ad->feature_bitmap & VIRTCHNL_VF_OFFLOAD_RSS_PF) && + (error = avf_op_config_rss_key (vm, ad))) + return error; + if ((error = avf_op_config_vsi_queues (vm, ad))) return error; @@ -733,15 +829,16 @@ avf_device_init (vlib_main_t * vm, avf_device_t * ad) return error; avf_irq_0_enable (ad); - avf_irq_n_enable (ad, 0); + for (i = 0; i < ad->n_rx_queues; i++) + avf_irq_n_enable (ad, i); if ((error = avf_op_add_eth_addr (vm, ad, 1, ad->hwaddr))) return error; - if ((error = avf_op_enable_queues (vm, ad, 1, 0))) + if ((error = avf_op_enable_queues (vm, ad, ad->n_rx_queues, 0))) return error; - if ((error = avf_op_enable_queues (vm, ad, 0, 1))) + if ((error = avf_op_enable_queues (vm, ad, 0, ad->n_tx_queues))) return error; ad->flags |= AVF_DEVICE_F_INITIALIZED; @@ -764,15 +861,20 @@ 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) != (1 << 31)) + if ((r & 0xf0000000) != (1ULL << 31)) { ad->error = clib_error_return (0, "arq not enabled, arqlen = 0x%x", r); goto error; } r = avf_get_u32 (ad->bar0, AVF_ATQLEN); - if ((r & 0xf0000000) != (1 << 31)) + if ((r & 0xf0000000) != (1ULL << 31)) { ad->error = clib_error_return (0, "atq not enabled, atqlen = 0x%x", r); goto error; @@ -934,11 +1036,10 @@ VLIB_REGISTER_NODE (avf_process_node, static) = { /* *INDENT-ON* */ static void -avf_irq_0_handler (vlib_pci_dev_handle_t h, u16 line) +avf_irq_0_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h, u16 line) { - vlib_main_t *vm = vlib_get_main (); avf_main_t *am = &avf_main; - uword pd = vlib_pci_get_private_data (h); + uword pd = vlib_pci_get_private_data (vm, h); avf_device_t *ad = pool_elt_at_index (am->devices, pd); u32 icr0; @@ -973,12 +1074,14 @@ avf_irq_0_handler (vlib_pci_dev_handle_t h, u16 line) } static void -avf_irq_n_handler (vlib_pci_dev_handle_t h, u16 line) +avf_irq_n_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h, u16 line) { - vlib_main_t *vm = vlib_get_main (); + vnet_main_t *vnm = vnet_get_main (); avf_main_t *am = &avf_main; - uword pd = vlib_pci_get_private_data (h); + uword pd = vlib_pci_get_private_data (vm, h); avf_device_t *ad = pool_elt_at_index (am->devices, pd); + u16 qid; + int i; if (ad->flags & AVF_DEVICE_F_ELOG) { @@ -1000,7 +1103,11 @@ avf_irq_n_handler (vlib_pci_dev_handle_t h, u16 line) ed->line = line; } - avf_irq_n_enable (ad, 0); + qid = line - 1; + if (vec_len (ad->rxqs) > qid && ad->rxqs[qid].int_mode != 0) + vnet_device_input_set_interrupt_pending (vnm, ad->hw_if_index, qid); + for (i = 0; i < vec_len (ad->rxqs); i++) + avf_irq_n_enable (ad, i); } void @@ -1017,7 +1124,7 @@ avf_delete_if (vlib_main_t * vm, avf_device_t * ad) ethernet_delete_interface (vnm, ad->hw_if_index); } - vlib_pci_device_close (ad->pci_dev_handle); + vlib_pci_device_close (vm, ad->pci_dev_handle); vlib_physmem_free (vm, am->physmem_region, ad->atq); vlib_physmem_free (vm, am->physmem_region, ad->arq); @@ -1028,10 +1135,10 @@ avf_delete_if (vlib_main_t * vm, avf_device_t * ad) vec_foreach_index (i, ad->rxqs) { avf_rxq_t *rxq = vec_elt_at_index (ad->rxqs, i); - vlib_physmem_free (vm, am->physmem_region, rxq->descs); - if (rxq->n_bufs) + vlib_physmem_free (vm, am->physmem_region, (void *) rxq->descs); + if (rxq->n_enqueued) vlib_buffer_free_from_ring (vm, rxq->bufs, rxq->next, rxq->size, - rxq->n_bufs); + rxq->n_enqueued); vec_free (rxq->bufs); } /* *INDENT-ON* */ @@ -1041,12 +1148,12 @@ avf_delete_if (vlib_main_t * vm, avf_device_t * ad) vec_foreach_index (i, ad->txqs) { avf_txq_t *txq = vec_elt_at_index (ad->txqs, i); - vlib_physmem_free (vm, am->physmem_region, txq->descs); - if (txq->n_bufs) + vlib_physmem_free (vm, am->physmem_region, (void *) txq->descs); + if (txq->n_enqueued) { - u16 first = (txq->next - txq->n_bufs) & (txq->size -1); + u16 first = (txq->next - txq->n_enqueued) & (txq->size -1); vlib_buffer_free_from_ring (vm, txq->bufs, first, txq->size, - txq->n_bufs); + txq->n_enqueued); } vec_free (txq->bufs); } @@ -1054,7 +1161,7 @@ avf_delete_if (vlib_main_t * vm, avf_device_t * ad) vec_free (ad->txqs); clib_error_free (ad->error); - memset (ad, 0, sizeof (*ad)); + clib_memset (ad, 0, sizeof (*ad)); pool_put (am->devices, ad); } @@ -1066,6 +1173,20 @@ avf_create_if (vlib_main_t * vm, avf_create_if_args_t * args) avf_device_t *ad; vlib_pci_dev_handle_t h; clib_error_t *error = 0; + int i; + + /* check input args */ + args->rxq_size = (args->rxq_size == 0) ? AVF_RXQ_SZ : args->rxq_size; + args->txq_size = (args->txq_size == 0) ? AVF_TXQ_SZ : args->txq_size; + + if ((args->rxq_size & (args->rxq_size - 1)) + || (args->txq_size & (args->txq_size - 1))) + { + args->rv = VNET_API_ERROR_INVALID_VALUE; + args->error = + clib_error_return (error, "queue size must be a power of two"); + return; + } pool_get (am->devices, ad); ad->dev_instance = ad - am->devices; @@ -1074,7 +1195,8 @@ avf_create_if (vlib_main_t * vm, avf_create_if_args_t * args) if (args->enable_elog) ad->flags |= AVF_DEVICE_F_ELOG; - if ((error = vlib_pci_device_open (&args->addr, avf_pci_device_ids, &h))) + if ((error = vlib_pci_device_open (vm, &args->addr, avf_pci_device_ids, + &h))) { pool_put (am->devices, ad); args->rv = VNET_API_ERROR_INVALID_INTERFACE; @@ -1085,21 +1207,23 @@ avf_create_if (vlib_main_t * vm, avf_create_if_args_t * args) } ad->pci_dev_handle = h; - vlib_pci_set_private_data (h, ad->dev_instance); + vlib_pci_set_private_data (vm, h, ad->dev_instance); - if ((error = vlib_pci_bus_master_enable (h))) + if ((error = vlib_pci_bus_master_enable (vm, h))) goto error; - if ((error = vlib_pci_map_region (h, 0, &ad->bar0))) + if ((error = vlib_pci_map_region (vm, h, 0, &ad->bar0))) goto error; - if ((error = vlib_pci_register_msix_handler (h, 0, 1, &avf_irq_0_handler))) + if ((error = vlib_pci_register_msix_handler (vm, h, 0, 1, + &avf_irq_0_handler))) goto error; - if ((error = vlib_pci_register_msix_handler (h, 1, 1, &avf_irq_n_handler))) + if ((error = vlib_pci_register_msix_handler (vm, h, 1, 1, + &avf_irq_n_handler))) goto error; - if ((error = vlib_pci_enable_msix_irq (h, 0, 2))) + if ((error = vlib_pci_enable_msix_irq (vm, h, 0, 2))) goto error; if (am->physmem_region_alloc == 0) @@ -1135,13 +1259,13 @@ avf_create_if (vlib_main_t * vm, avf_create_if_args_t * args) if (error) goto error; - if ((error = vlib_pci_intr_enable (h))) + if ((error = vlib_pci_intr_enable (vm, h))) goto error; /* FIXME detect */ ad->flags |= AVF_DEVICE_F_IOVA; - if ((error = avf_device_init (vm, ad))) + if ((error = avf_device_init (vm, am, ad, args))) goto error; /* create interface */ @@ -1153,11 +1277,16 @@ avf_create_if (vlib_main_t * vm, avf_create_if_args_t * args) goto error; vnet_sw_interface_t *sw = vnet_get_hw_sw_interface (vnm, ad->hw_if_index); - ad->sw_if_index = sw->sw_if_index; + args->sw_if_index = ad->sw_if_index = sw->sw_if_index; + vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, ad->hw_if_index); + hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE; vnet_hw_interface_set_input_node (vnm, ad->hw_if_index, avf_input_node.index); + for (i = 0; i < ad->n_rx_queues; i++) + vnet_hw_interface_assign_rx_thread (vnm, ad->hw_if_index, i, ~0); + if (pool_elts (am->devices) == 1) vlib_process_signal_event (vm, avf_process_node.index, AVF_PROCESS_EVENT_START, 0); @@ -1188,7 +1317,6 @@ avf_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags) vnet_hw_interface_set_flags (vnm, ad->hw_if_index, VNET_HW_INTERFACE_FLAG_LINK_UP); ad->flags |= AVF_DEVICE_F_ADMIN_UP; - vnet_hw_interface_assign_rx_thread (vnm, ad->hw_if_index, 0, ~0); } else { @@ -1198,14 +1326,59 @@ avf_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags) return 0; } +static clib_error_t * +avf_interface_rx_mode_change (vnet_main_t * vnm, u32 hw_if_index, u32 qid, + vnet_hw_interface_rx_mode mode) +{ + avf_main_t *am = &avf_main; + vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index); + avf_device_t *ad = pool_elt_at_index (am->devices, hw->dev_instance); + avf_rxq_t *rxq = vec_elt_at_index (ad->rxqs, qid); + + if (mode == VNET_HW_INTERFACE_RX_MODE_POLLING) + rxq->int_mode = 0; + else + rxq->int_mode = 1; + + return 0; +} + +static void +avf_set_interface_next_node (vnet_main_t * vnm, u32 hw_if_index, + u32 node_index) +{ + avf_main_t *am = &avf_main; + vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index); + avf_device_t *ad = pool_elt_at_index (am->devices, hw->dev_instance); + + /* Shut off redirection */ + if (node_index == ~0) + { + ad->per_interface_next_index = node_index; + return; + } + + ad->per_interface_next_index = + vlib_node_add_next (vlib_get_main (), avf_input_node.index, node_index); +} + +static char *avf_tx_func_error_strings[] = { +#define _(n,s) s, + foreach_avf_tx_func_error +#undef _ +}; + /* *INDENT-OFF* */ VNET_DEVICE_CLASS (avf_device_class,) = { .name = "Adaptive Virtual Function (AVF) interface", - .tx_function = avf_interface_tx, .format_device = format_avf_device, .format_device_name = format_avf_device_name, .admin_up_down_function = avf_interface_admin_up_down, + .rx_mode_change_function = avf_interface_rx_mode_change, + .rx_redirect_to_node = avf_set_interface_next_node, + .tx_function_n_errors = AVF_TX_N_ERROR, + .tx_function_error_strings = avf_tx_func_error_strings, }; /* *INDENT-ON* */