virtio: Add support for multiqueue
[vpp.git] / src / vnet / devices / virtio / pci.c
1 /*
2  * Copyright (c) 2018 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15
16 #include <fcntl.h>
17 #include <sys/ioctl.h>
18
19 #include <vppinfra/types.h>
20 #include <vlib/vlib.h>
21 #include <vlib/pci/pci.h>
22 #include <vnet/ethernet/ethernet.h>
23 #include <vnet/ip/ip4_packet.h>
24 #include <vnet/ip/ip6_packet.h>
25 #include <vnet/devices/virtio/virtio.h>
26 #include <vnet/devices/virtio/pci.h>
27
28 #define PCI_VENDOR_ID_VIRTIO                            0x1af4
29 #define PCI_DEVICE_ID_VIRTIO_NIC                        0x1000
30 /* Doesn't support modern device */
31 #define PCI_DEVICE_ID_VIRTIO_NIC_MODERN                 0x1041
32
33 #define PCI_CAPABILITY_LIST     0x34
34 #define PCI_CAP_ID_VNDR         0x09
35 #define PCI_CAP_ID_MSIX         0x11
36
37 #define PCI_MSIX_ENABLE 0x8000
38
39 #define PCI_CONFIG_SIZE(vif) ((vif->msix_enabled == VIRTIO_MSIX_ENABLED) ? \
40   24 : 20)
41
42 static pci_device_id_t virtio_pci_device_ids[] = {
43   {
44    .vendor_id = PCI_VENDOR_ID_VIRTIO,
45    .device_id = PCI_DEVICE_ID_VIRTIO_NIC},
46   {
47    .vendor_id = PCI_VENDOR_ID_VIRTIO,
48    .device_id = PCI_DEVICE_ID_VIRTIO_NIC_MODERN},
49   {0},
50 };
51
52 static void
53 virtio_pci_legacy_read_config (vlib_main_t * vm, virtio_if_t * vif, void *dst,
54                                int len, u32 addr)
55 {
56   u32 size = 0;
57   vlib_pci_dev_handle_t h = vif->pci_dev_handle;
58
59   while (len > 0)
60     {
61       if (len >= 4)
62         {
63           size = 4;
64           vlib_pci_read_io_u32 (vm, h, PCI_CONFIG_SIZE (vif) + addr, dst);
65         }
66       else if (len >= 2)
67         {
68           size = 2;
69           vlib_pci_read_io_u16 (vm, h, PCI_CONFIG_SIZE (vif) + addr, dst);
70         }
71       else
72         {
73           size = 1;
74           vlib_pci_read_io_u8 (vm, h, PCI_CONFIG_SIZE (vif) + addr, dst);
75         }
76       dst = (u8 *) dst + size;
77       addr += size;
78       len -= size;
79     }
80 }
81
82 static void
83 virtio_pci_legacy_write_config (vlib_main_t * vm, virtio_if_t * vif,
84                                 void *src, int len, u32 addr)
85 {
86   u32 size = 0;
87   vlib_pci_dev_handle_t h = vif->pci_dev_handle;
88
89   while (len > 0)
90     {
91       if (len >= 4)
92         {
93           size = 4;
94           vlib_pci_write_io_u32 (vm, h, PCI_CONFIG_SIZE (vif) + addr, src);
95         }
96       else if (len >= 2)
97         {
98           size = 2;
99           vlib_pci_write_io_u16 (vm, h, PCI_CONFIG_SIZE (vif) + addr, src);
100         }
101       else
102         {
103           size = 1;
104           vlib_pci_write_io_u8 (vm, h, PCI_CONFIG_SIZE (vif) + addr, src);
105         }
106       src = (u8 *) src + size;
107       addr += size;
108       len -= size;
109     }
110 }
111
112 static u64
113 virtio_pci_legacy_get_features (vlib_main_t * vm, virtio_if_t * vif)
114 {
115   u32 features;
116   vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_HOST_FEATURES,
117                         &features);
118   return features;
119 }
120
121 static u32
122 virtio_pci_legacy_set_features (vlib_main_t * vm, virtio_if_t * vif,
123                                 u64 features)
124 {
125   if ((features >> 32) != 0)
126     {
127       clib_warning ("only 32 bit features are allowed for legacy virtio!");
128     }
129   u32 feature = 0, guest_features = (u32) features;
130   vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
131                          &guest_features);
132   vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
133                         &feature);
134   return feature;
135 }
136
137 static u8
138 virtio_pci_legacy_get_status (vlib_main_t * vm, virtio_if_t * vif)
139 {
140   u8 status = 0;
141   vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_STATUS, &status);
142   return status;
143 }
144
145 static void
146 virtio_pci_legacy_set_status (vlib_main_t * vm, virtio_if_t * vif, u8 status)
147 {
148   if (status != VIRTIO_CONFIG_STATUS_RESET)
149     status |= virtio_pci_legacy_get_status (vm, vif);
150   vlib_pci_write_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_STATUS, &status);
151 }
152
153 static u8
154 virtio_pci_legacy_reset (vlib_main_t * vm, virtio_if_t * vif)
155 {
156   virtio_pci_legacy_set_status (vm, vif, VIRTIO_CONFIG_STATUS_RESET);
157   return virtio_pci_legacy_get_status (vm, vif);
158 }
159
160 static u8
161 virtio_pci_legacy_get_isr (vlib_main_t * vm, virtio_if_t * vif)
162 {
163   u8 isr = 0;
164   vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_ISR, &isr);
165   return isr;
166 }
167
168 static u16
169 virtio_pci_legacy_get_queue_num (vlib_main_t * vm, virtio_if_t * vif,
170                                  u16 queue_id)
171 {
172   u16 queue_num = 0;
173   vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
174                          &queue_id);
175   vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NUM,
176                         &queue_num);
177   return queue_num;
178 }
179
180
181 static void
182 virtio_pci_legacy_setup_queue (vlib_main_t * vm, virtio_if_t * vif,
183                                u16 queue_id, void *p)
184 {
185   u64 addr = vlib_physmem_get_pa (vm, p) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT;
186   vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
187                          &queue_id);
188   vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN,
189                          (u32 *) & addr);
190 }
191
192 static void
193 virtio_pci_legacy_del_queue (vlib_main_t * vm, virtio_if_t * vif,
194                              u16 queue_id)
195 {
196   u32 src = 0;
197   vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
198                          &queue_id);
199   vlib_pci_write_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN, &src);
200 }
201
202 inline void
203 virtio_pci_legacy_notify_queue (vlib_main_t * vm, virtio_if_t * vif,
204                                 u16 queue_id)
205 {
206   vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NOTIFY,
207                          &queue_id);
208 }
209
210 /* Enable one vector (0) for Link State Intrerrupt */
211 static u16
212 virtio_pci_legacy_set_config_irq (vlib_main_t * vm, virtio_if_t * vif,
213                                   u16 vec)
214 {
215   vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_CONFIG_VECTOR,
216                          &vec);
217   vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_CONFIG_VECTOR,
218                         &vec);
219   return vec;
220 }
221
222 static u16
223 virtio_pci_legacy_set_queue_irq (vlib_main_t * vm, virtio_if_t * vif, u16 vec,
224                                  u16 queue_id)
225 {
226   vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
227                          &queue_id);
228   vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_QUEUE_VECTOR,
229                          &vec);
230   vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_QUEUE_VECTOR,
231                         &vec);
232   return vec;
233 }
234
235 static u32
236 virtio_pci_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hw,
237                         u32 flags)
238 {
239   return 0;
240 }
241
242 static clib_error_t *
243 virtio_pci_get_max_virtqueue_pairs (vlib_main_t * vm, virtio_if_t * vif)
244 {
245   virtio_main_t *vim = &virtio_main;
246   virtio_net_config_t config;
247   clib_error_t *error = 0;
248   u16 max_queue_pairs = 1;
249
250   if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MQ))
251     {
252       virtio_pci_legacy_read_config (vm, vif, &config.max_virtqueue_pairs,
253                                      sizeof (config.max_virtqueue_pairs), 8);
254       max_queue_pairs = config.max_virtqueue_pairs;
255     }
256
257   virtio_log_debug (vim, vif, "max queue pair is %x", max_queue_pairs);
258   if (max_queue_pairs < 1 || max_queue_pairs > 0x8000)
259     clib_error_return (error, "max queue pair is %x", max_queue_pairs);
260
261   vif->max_queue_pairs = max_queue_pairs;
262   return error;
263 }
264
265 static void
266 virtio_pci_set_mac (vlib_main_t * vm, virtio_if_t * vif)
267 {
268   virtio_pci_legacy_write_config (vm, vif, vif->mac_addr,
269                                   sizeof (vif->mac_addr), 0);
270 }
271
272 static u32
273 virtio_pci_get_mac (vlib_main_t * vm, virtio_if_t * vif)
274 {
275   if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MAC))
276     {
277       virtio_pci_legacy_read_config (vm, vif, vif->mac_addr,
278                                      sizeof (vif->mac_addr), 0);
279       return 0;
280     }
281   return 1;
282 }
283
284 static u16
285 virtio_pci_is_link_up (vlib_main_t * vm, virtio_if_t * vif)
286 {
287   /*
288    * Minimal driver: assumes link is up
289    */
290   u16 status = 1;
291   if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_STATUS))
292     virtio_pci_legacy_read_config (vm, vif, &status, sizeof (status),   /* mac */
293                                    6);
294   return status;
295 }
296
297 static void
298 virtio_pci_irq_0_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h, u16 line)
299 {
300   vnet_main_t *vnm = vnet_get_main ();
301   virtio_main_t *vim = &virtio_main;
302   uword pd = vlib_pci_get_private_data (vm, h);
303   virtio_if_t *vif = pool_elt_at_index (vim->interfaces, pd);
304   u16 qid = line;
305
306   vnet_device_input_set_interrupt_pending (vnm, vif->hw_if_index, qid);
307 }
308
309 static void
310 virtio_pci_irq_1_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h, u16 line)
311 {
312   vnet_main_t *vnm = vnet_get_main ();
313   virtio_main_t *vim = &virtio_main;
314   uword pd = vlib_pci_get_private_data (vm, h);
315   virtio_if_t *vif = pool_elt_at_index (vim->interfaces, pd);
316
317   if (virtio_pci_is_link_up (vm, vif) & VIRTIO_NET_S_LINK_UP)
318     {
319       vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
320       vnet_hw_interface_set_flags (vnm, vif->hw_if_index,
321                                    VNET_HW_INTERFACE_FLAG_LINK_UP);
322     }
323   else
324     {
325       vif->flags &= ~VIRTIO_IF_FLAG_ADMIN_UP;
326       vnet_hw_interface_set_flags (vnm, vif->hw_if_index, 0);
327     }
328 }
329
330 static void
331 virtio_pci_irq_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h)
332 {
333   virtio_main_t *vim = &virtio_main;
334   uword pd = vlib_pci_get_private_data (vm, h);
335   virtio_if_t *vif = pool_elt_at_index (vim->interfaces, pd);
336   u8 isr = 0;
337   u16 line = 0;
338
339   isr = virtio_pci_legacy_get_isr (vm, vif);
340
341   /*
342    * If the lower bit is set: look through the used rings of
343    * all virtqueues for the device, to see if any progress has
344    * been made by the device which requires servicing.
345    */
346   if (isr & VIRTIO_PCI_ISR_INTR)
347     virtio_pci_irq_0_handler (vm, h, line);
348
349   if (isr & VIRTIO_PCI_ISR_CONFIG)
350     virtio_pci_irq_1_handler (vm, h, line);
351 }
352
353 inline void
354 device_status (vlib_main_t * vm, virtio_if_t * vif)
355 {
356   struct status_struct
357   {
358     u8 bit;
359     char *str;
360   };
361   struct status_struct *status_entry;
362   static struct status_struct status_array[] = {
363 #define _(s,b) { .str = #s, .bit = b, },
364     foreach_virtio_config_status_flags
365 #undef _
366     {.str = NULL}
367   };
368
369   vlib_cli_output (vm, "  status 0x%x", vif->status);
370
371   status_entry = (struct status_struct *) &status_array;
372   while (status_entry->str)
373     {
374       if (vif->status & status_entry->bit)
375         vlib_cli_output (vm, "    %s (%x)", status_entry->str,
376                          status_entry->bit);
377       status_entry++;
378     }
379 }
380
381 inline void
382 debug_device_config_space (vlib_main_t * vm, virtio_if_t * vif)
383 {
384   u32 data_u32;
385   u16 data_u16;
386   u8 data_u8;
387   vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_HOST_FEATURES,
388                         &data_u32);
389   vlib_cli_output (vm, "remote features 0x%lx", data_u32);
390   vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_GUEST_FEATURES,
391                         &data_u32);
392   vlib_cli_output (vm, "guest features 0x%lx", data_u32);
393   vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_PFN,
394                         &data_u32);
395   vlib_cli_output (vm, "queue address 0x%lx", data_u32);
396   vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NUM,
397                         &data_u16);
398   vlib_cli_output (vm, "queue size 0x%x", data_u16);
399   vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
400                         &data_u16);
401   vlib_cli_output (vm, "queue select 0x%x", data_u16);
402   vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_NOTIFY,
403                         &data_u16);
404   vlib_cli_output (vm, "queue notify 0x%x", data_u16);
405   vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_STATUS, &data_u8);
406   vlib_cli_output (vm, "status 0x%x", data_u8);
407   vlib_pci_read_io_u8 (vm, vif->pci_dev_handle, VIRTIO_PCI_ISR, &data_u8);
408   vlib_cli_output (vm, "isr 0x%x", data_u8);
409
410   if (vif->msix_enabled == VIRTIO_MSIX_ENABLED)
411     {
412       vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_CONFIG_VECTOR,
413                             &data_u16);
414       vlib_cli_output (vm, "config vector 0x%x", data_u16);
415       u16 queue_id = 0;
416       vlib_pci_write_io_u16 (vm, vif->pci_dev_handle, VIRTIO_PCI_QUEUE_SEL,
417                              &queue_id);
418       vlib_pci_read_io_u16 (vm, vif->pci_dev_handle, VIRTIO_MSI_QUEUE_VECTOR,
419                             &data_u16);
420       vlib_cli_output (vm, "queue vector for queue (0) 0x%x", data_u16);
421     }
422
423   u8 mac[6];
424   virtio_pci_legacy_read_config (vm, vif, mac, sizeof (mac), 0);
425   vlib_cli_output (vm, "mac %U", format_ethernet_address, mac);
426   virtio_pci_legacy_read_config (vm, vif, &data_u16, sizeof (u16),      /* offset to status */
427                                  6);
428   vlib_cli_output (vm, "link up/down status 0x%x", data_u16);
429   virtio_pci_legacy_read_config (vm, vif, &data_u16, sizeof (u16),
430                                  /* offset to max_virtqueue */ 8);
431   vlib_cli_output (vm, "num of virtqueue 0x%x", data_u16);
432   virtio_pci_legacy_read_config (vm, vif, &data_u16, sizeof (u16),      /* offset to mtu */
433                                  10);
434   vlib_cli_output (vm, "mtu 0x%x", data_u16);
435
436   u32 i = PCI_CONFIG_SIZE (vif) + 12, a = 4;
437   i += a;
438   i &= ~a;
439   for (; i < 64; i += 4)
440     {
441       u32 data = 0;
442       vlib_pci_read_io_u32 (vm, vif->pci_dev_handle, i, &data);
443       vlib_cli_output (vm, "0x%lx", data);
444     }
445 }
446
447 struct virtio_ctrl_mq_status_hdr
448 {
449   struct virtio_net_ctrl_hdr ctrl;
450   struct virtio_net_ctrl_mq num_mqs;
451   virtio_net_ctrl_ack status;
452 };
453
454 static int
455 virtio_pci_enable_multiqueue (vlib_main_t * vm, virtio_if_t * vif,
456                               u16 num_queues)
457 {
458   virtio_main_t *vim = &virtio_main;
459   virtio_vring_t *vring = vif->cxq_vring;
460   u32 buffer_index;
461   vlib_buffer_t *b;
462   u16 used, next, avail;
463   u16 sz = vring->size;
464   u16 mask = sz - 1;
465   struct virtio_ctrl_mq_status_hdr mq_hdr, result;
466   virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
467
468   mq_hdr.ctrl.class = VIRTIO_NET_CTRL_MQ;
469   mq_hdr.ctrl.cmd = VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET;
470   mq_hdr.status = VIRTIO_NET_ERR;
471   mq_hdr.num_mqs.virtqueue_pairs = num_queues;
472
473   used = vring->desc_in_use;
474   next = vring->desc_next;
475   avail = vring->avail->idx;
476   struct vring_desc *d = &vring->desc[next];
477
478   if (vlib_buffer_alloc (vm, &buffer_index, 1))
479     b = vlib_get_buffer (vm, buffer_index);
480   else
481     return VIRTIO_NET_ERR;
482   /*
483    * current_data may not be initialized with 0 and may contain
484    * previous offset.
485    */
486   b->current_data = 0;
487   clib_memcpy (vlib_buffer_get_current (b), &mq_hdr,
488                sizeof (struct virtio_ctrl_mq_status_hdr));
489   d->flags = VRING_DESC_F_NEXT;
490   d->addr = vlib_buffer_get_current_pa (vm, b);
491   d->len = sizeof (struct virtio_net_ctrl_hdr);
492   vring->avail->ring[avail & mask] = next;
493   avail++;
494   next = (next + 1) & mask;
495   d->next = next;
496   used++;
497
498   d = &vring->desc[next];
499   d->flags = VRING_DESC_F_NEXT;
500   d->addr = vlib_buffer_get_current_pa (vm, b) +
501     STRUCT_OFFSET_OF (struct virtio_ctrl_mq_status_hdr, num_mqs);
502   d->len = sizeof (struct virtio_net_ctrl_mq);
503   next = (next + 1) & mask;
504   d->next = next;
505   used++;
506
507   d = &vring->desc[next];
508   d->flags = VRING_DESC_F_WRITE;
509   d->addr = vlib_buffer_get_current_pa (vm, b) +
510     STRUCT_OFFSET_OF (struct virtio_ctrl_mq_status_hdr, status);
511   d->len = sizeof (mq_hdr.status);
512   next = (next + 1) & mask;
513   used++;
514
515   CLIB_MEMORY_STORE_BARRIER ();
516   vring->avail->idx = avail;
517   vring->desc_next = next;
518   vring->desc_in_use = used;
519
520   if ((vring->used->flags & VIRTIO_RING_FLAG_MASK_INT) == 0)
521     {
522       virtio_kick (vm, vring, vif);
523     }
524
525   clib_memset (&result, 0, sizeof (result));
526   u16 last = vring->last_used_idx, n_left = 0;
527   n_left = vring->used->idx - last;
528
529   while (n_left)
530     {
531       struct vring_used_elem *e = &vring->used->ring[last & mask];
532       u16 slot = e->id;
533
534       d = &vring->desc[slot];
535       while (d->flags & VRING_DESC_F_NEXT)
536         {
537           used--;
538           slot = d->next;
539           d = &vring->desc[slot];
540         }
541       used--;
542       last++;
543       n_left--;
544     }
545   vring->desc_in_use = used;
546   vring->last_used_idx = last;
547
548   CLIB_MEMORY_BARRIER ();
549   clib_memcpy (&result, vlib_buffer_get_current (b),
550                sizeof (struct virtio_ctrl_mq_status_hdr));
551
552   virtio_log_debug (vim, vif, "multi-queue enable status on Ctrl queue : %u",
553                     result.status);
554   status = result.status;
555   vlib_buffer_free (vm, &buffer_index, 1);
556   return status;
557 }
558
559 static u8
560 virtio_pci_queue_size_valid (u16 qsz)
561 {
562   if (qsz < 64 || qsz > 4096)
563     return 0;
564   if ((qsz % 64) != 0)
565     return 0;
566   return 1;
567 }
568
569 clib_error_t *
570 virtio_pci_control_vring_init (vlib_main_t * vm, virtio_if_t * vif,
571                                u16 queue_num)
572 {
573   clib_error_t *error = 0;
574   virtio_main_t *vim = &virtio_main;
575   u16 queue_size = 0;
576   virtio_vring_t *vring;
577   struct vring vr;
578   u32 i = 0;
579   void *ptr = NULL;
580
581   queue_size = virtio_pci_legacy_get_queue_num (vm, vif, queue_num);
582   if (!virtio_pci_queue_size_valid (queue_size))
583     clib_warning ("queue size is not valid");
584
585   if (!is_pow2 (queue_size))
586     return clib_error_return (0, "ring size must be power of 2");
587
588   if (queue_size > 32768)
589     return clib_error_return (0, "ring size must be 32768 or lower");
590
591   if (queue_size == 0)
592     queue_size = 256;
593
594   vec_validate_aligned (vif->cxq_vring, 0, CLIB_CACHE_LINE_BYTES);
595   vring = vec_elt_at_index (vif->cxq_vring, 0);
596   i = vring_size (queue_size, VIRTIO_PCI_VRING_ALIGN);
597   i = round_pow2 (i, VIRTIO_PCI_VRING_ALIGN);
598   ptr =
599     vlib_physmem_alloc_aligned_on_numa (vm, i, VIRTIO_PCI_VRING_ALIGN,
600                                         vif->numa_node);
601   if (!ptr)
602     return vlib_physmem_last_error (vm);
603   clib_memset (ptr, 0, i);
604   vring_init (&vr, queue_size, ptr, VIRTIO_PCI_VRING_ALIGN);
605   vring->desc = vr.desc;
606   vring->avail = vr.avail;
607   vring->used = vr.used;
608   vring->queue_id = queue_num;
609   vring->avail->flags = VIRTIO_RING_FLAG_MASK_INT;
610
611   ASSERT (vring->buffers == 0);
612
613   vring->size = queue_size;
614   virtio_log_debug (vim, vif, "control-queue: number %u, size %u", queue_num,
615                     queue_size);
616   virtio_pci_legacy_setup_queue (vm, vif, queue_num, ptr);
617   vring->kick_fd = -1;
618
619   return error;
620 }
621
622 clib_error_t *
623 virtio_pci_vring_init (vlib_main_t * vm, virtio_if_t * vif, u16 queue_num)
624 {
625   clib_error_t *error = 0;
626   virtio_main_t *vim = &virtio_main;
627   vlib_thread_main_t *vtm = vlib_get_thread_main ();
628   u16 queue_size = 0;
629   virtio_vring_t *vring;
630   struct vring vr;
631   u32 i = 0;
632   void *ptr = NULL;
633
634   queue_size = virtio_pci_legacy_get_queue_num (vm, vif, queue_num);
635   if (!virtio_pci_queue_size_valid (queue_size))
636     clib_warning ("queue size is not valid");
637
638   if (!is_pow2 (queue_size))
639     return clib_error_return (0, "ring size must be power of 2");
640
641   if (queue_size > 32768)
642     return clib_error_return (0, "ring size must be 32768 or lower");
643
644   if (queue_size == 0)
645     queue_size = 256;
646
647   if (queue_num % 2)
648     {
649       if (TX_QUEUE_ACCESS (queue_num) > vtm->n_vlib_mains)
650         return error;
651       vec_validate_aligned (vif->txq_vrings, TX_QUEUE_ACCESS (queue_num),
652                             CLIB_CACHE_LINE_BYTES);
653       vring = vec_elt_at_index (vif->txq_vrings, TX_QUEUE_ACCESS (queue_num));
654       clib_spinlock_init (&vring->lockp);
655     }
656   else
657     {
658       vec_validate_aligned (vif->rxq_vrings, RX_QUEUE_ACCESS (queue_num),
659                             CLIB_CACHE_LINE_BYTES);
660       vring = vec_elt_at_index (vif->rxq_vrings, RX_QUEUE_ACCESS (queue_num));
661     }
662   i = vring_size (queue_size, VIRTIO_PCI_VRING_ALIGN);
663   i = round_pow2 (i, VIRTIO_PCI_VRING_ALIGN);
664   ptr =
665     vlib_physmem_alloc_aligned_on_numa (vm, i, VIRTIO_PCI_VRING_ALIGN,
666                                         vif->numa_node);
667   if (!ptr)
668     return vlib_physmem_last_error (vm);
669   clib_memset (ptr, 0, i);
670   vring_init (&vr, queue_size, ptr, VIRTIO_PCI_VRING_ALIGN);
671   vring->desc = vr.desc;
672   vring->avail = vr.avail;
673   vring->used = vr.used;
674   vring->queue_id = queue_num;
675   vring->avail->flags = VIRTIO_RING_FLAG_MASK_INT;
676
677   ASSERT (vring->buffers == 0);
678   vec_validate_aligned (vring->buffers, queue_size, CLIB_CACHE_LINE_BYTES);
679   ASSERT (vring->indirect_buffers == 0);
680   vec_validate_aligned (vring->indirect_buffers, queue_size,
681                         CLIB_CACHE_LINE_BYTES);
682   if (queue_num % 2)
683     {
684       u32 n_alloc = 0;
685       do
686         {
687           if (n_alloc < queue_size)
688             n_alloc =
689               vlib_buffer_alloc (vm, vring->indirect_buffers + n_alloc,
690                                  queue_size - n_alloc);
691         }
692       while (n_alloc != queue_size);
693       vif->num_txqs++;
694       virtio_log_debug (vim, vif, "tx-queue: number %u, size %u", queue_num,
695                         queue_size);
696     }
697   else
698     {
699       vif->num_rxqs++;
700       virtio_log_debug (vim, vif, "rx-queue: number %u, size %u", queue_num,
701                         queue_size);
702     }
703   vring->size = queue_size;
704   virtio_pci_legacy_setup_queue (vm, vif, queue_num, ptr);
705   vring->kick_fd = -1;
706
707   return error;
708 }
709
710 static void
711 virtio_negotiate_features (vlib_main_t * vm, virtio_if_t * vif,
712                            u64 req_features)
713 {
714   /*
715    * if features are not requested
716    * default: all supported features
717    */
718   u64 supported_features = VIRTIO_FEATURE (VIRTIO_NET_F_MTU)
719     | VIRTIO_FEATURE (VIRTIO_NET_F_MAC)
720     | VIRTIO_FEATURE (VIRTIO_NET_F_MRG_RXBUF)
721     | VIRTIO_FEATURE (VIRTIO_NET_F_STATUS)
722     | VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ)
723     | VIRTIO_FEATURE (VIRTIO_NET_F_MQ)
724     | VIRTIO_FEATURE (VIRTIO_F_NOTIFY_ON_EMPTY)
725     | VIRTIO_FEATURE (VIRTIO_F_ANY_LAYOUT)
726     | VIRTIO_FEATURE (VIRTIO_RING_F_INDIRECT_DESC);
727
728   if (req_features == 0)
729     {
730       req_features = supported_features;
731     }
732
733   vif->features = req_features & vif->remote_features & supported_features;
734
735   if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MTU))
736     {
737       virtio_net_config_t config;
738       virtio_pci_legacy_read_config (vm, vif, &config.mtu,
739                                      sizeof (config.mtu), 10);
740       if (config.mtu < 64)
741         vif->features &= ~VIRTIO_FEATURE (VIRTIO_NET_F_MTU);
742     }
743
744   vif->features = virtio_pci_legacy_set_features (vm, vif, vif->features);
745 }
746
747 void
748 virtio_pci_read_device_feature (vlib_main_t * vm, virtio_if_t * vif)
749 {
750   vif->remote_features = virtio_pci_legacy_get_features (vm, vif);
751 }
752
753 int
754 virtio_pci_reset_device (vlib_main_t * vm, virtio_if_t * vif)
755 {
756   u8 status = 0;
757
758   /*
759    * Reset the device
760    */
761   status = virtio_pci_legacy_reset (vm, vif);
762
763   /*
764    * Set the Acknowledge status bit
765    */
766   virtio_pci_legacy_set_status (vm, vif, VIRTIO_CONFIG_STATUS_ACK);
767
768   /*
769    * Set the Driver status bit
770    */
771   virtio_pci_legacy_set_status (vm, vif, VIRTIO_CONFIG_STATUS_DRIVER);
772
773   /*
774    * Read the status and verify it
775    */
776   status = virtio_pci_legacy_get_status (vm, vif);
777   if (!
778       ((status & VIRTIO_CONFIG_STATUS_ACK)
779        && (status & VIRTIO_CONFIG_STATUS_DRIVER)))
780     return -1;
781   vif->status = status;
782
783   return 0;
784 }
785
786 clib_error_t *
787 virtio_pci_read_caps (vlib_main_t * vm, virtio_if_t * vif)
788 {
789   clib_error_t *error = 0;
790   virtio_main_t *vim = &virtio_main;
791   struct virtio_pci_cap cap;
792   u8 pos, common_cfg = 0, notify_base = 0, dev_cfg = 0, isr = 0, pci_cfg = 0;
793   vlib_pci_dev_handle_t h = vif->pci_dev_handle;
794
795   if ((error = vlib_pci_read_config_u8 (vm, h, PCI_CAPABILITY_LIST, &pos)))
796     {
797       virtio_log_error (vim, vif, "error in reading capabilty list position");
798       clib_error_return (error, "error in reading capabilty list position");
799     }
800   while (pos)
801     {
802       if ((error =
803            vlib_pci_read_write_config (vm, h, VLIB_READ, pos, &cap,
804                                        sizeof (cap))))
805         {
806           virtio_log_error (vim, vif, "%s [%2x]",
807                             "error in reading the capability at", pos);
808           clib_error_return (error,
809                              "error in reading the capability at [%2x]", pos);
810         }
811
812       if (cap.cap_vndr == PCI_CAP_ID_MSIX)
813         {
814           u16 flags, table_size, table_size_mask = 0x07FF;
815
816           if ((error =
817                vlib_pci_read_write_config (vm, h, VLIB_READ, pos + 2, &flags,
818                                            sizeof (flags))))
819             clib_error_return (error,
820                                "error in reading the capability at [%2x]",
821                                pos + 2);
822
823           table_size = flags & table_size_mask;
824           virtio_log_debug (vim, vif, "flags:0x%x %s 0x%x", flags,
825                             "msix interrupt vector table-size", table_size);
826
827           if (flags & PCI_MSIX_ENABLE)
828             {
829               virtio_log_debug (vim, vif, "msix interrupt enabled");
830               vif->msix_enabled = VIRTIO_MSIX_ENABLED;
831             }
832           else
833             {
834               virtio_log_debug (vim, vif, "msix interrupt disabled");
835               vif->msix_enabled = VIRTIO_MSIX_DISABLED;
836             }
837         }
838
839       if (cap.cap_vndr != PCI_CAP_ID_VNDR)
840         {
841           virtio_log_debug (vim, vif, "[%2x] %s %2x ", pos,
842                             "skipping non VNDR cap id:", cap.cap_vndr);
843           goto next;
844         }
845
846       virtio_log_debug (vim, vif,
847                         "[%4x] cfg type: %u, bar: %u, offset: %04x, len: %u",
848                         pos, cap.cfg_type, cap.bar, cap.offset, cap.length);
849       switch (cap.cfg_type)
850         {
851         case VIRTIO_PCI_CAP_COMMON_CFG:
852           common_cfg = 1;
853           break;
854         case VIRTIO_PCI_CAP_NOTIFY_CFG:
855           notify_base = 1;
856           break;
857         case VIRTIO_PCI_CAP_DEVICE_CFG:
858           dev_cfg = 1;
859           break;
860         case VIRTIO_PCI_CAP_ISR_CFG:
861           isr = 1;
862           break;
863         case VIRTIO_PCI_CAP_PCI_CFG:
864           if (cap.bar == 0)
865             pci_cfg = 1;
866           break;
867         }
868     next:
869       pos = cap.cap_next;
870     }
871
872   if (common_cfg == 0 || notify_base == 0 || dev_cfg == 0 || isr == 0)
873     {
874       virtio_log_debug (vim, vif, "legacy virtio pci device found");
875       return error;
876     }
877
878   if (!pci_cfg)
879     clib_error_return (error, "modern virtio pci device found");
880
881   virtio_log_debug (vim, vif, "transitional virtio pci device found");
882   return error;
883 }
884
885 static clib_error_t *
886 virtio_pci_device_init (vlib_main_t * vm, virtio_if_t * vif,
887                         virtio_pci_create_if_args_t * args)
888 {
889   clib_error_t *error = 0;
890   virtio_main_t *vim = &virtio_main;
891   u8 status = 0;
892
893   if ((error = virtio_pci_read_caps (vm, vif)))
894     clib_error_return (error, "Device is not supported");
895
896   if (virtio_pci_reset_device (vm, vif) < 0)
897     {
898       virtio_log_error (vim, vif, "Failed to reset the device");
899       clib_error_return (error, "Failed to reset the device");
900     }
901   /*
902    * read device features and negotiate (user) requested features
903    */
904   virtio_pci_read_device_feature (vm, vif);
905   virtio_negotiate_features (vm, vif, args->features);
906
907   /*
908    * After FEATURE_OK, driver should not accept new feature bits
909    */
910   virtio_pci_legacy_set_status (vm, vif, VIRTIO_CONFIG_STATUS_FEATURES_OK);
911   status = virtio_pci_legacy_get_status (vm, vif);
912   if (!(status & VIRTIO_CONFIG_STATUS_FEATURES_OK))
913     {
914       virtio_log_error (vim, vif,
915                         "error encountered: Device doesn't support requested features");
916       clib_error_return (error, "Device doesn't support requested features");
917     }
918   vif->status = status;
919
920   /*
921    * get or set the mac address
922    */
923   if (virtio_pci_get_mac (vm, vif))
924     {
925       f64 now = vlib_time_now (vm);
926       u32 rnd;
927       rnd = (u32) (now * 1e6);
928       rnd = random_u32 (&rnd);
929
930       memcpy (vif->mac_addr + 2, &rnd, sizeof (rnd));
931       vif->mac_addr[0] = 2;
932       vif->mac_addr[1] = 0xfe;
933       virtio_pci_set_mac (vm, vif);
934     }
935
936   virtio_set_net_hdr_size (vif);
937
938   /*
939    * Initialize the virtqueues
940    */
941   if ((error = virtio_pci_get_max_virtqueue_pairs (vm, vif)))
942     goto error;
943
944   for (int i = 0; i < vif->max_queue_pairs; i++)
945     {
946       if ((error = virtio_pci_vring_init (vm, vif, RX_QUEUE (i))))
947         virtio_log_warning (vim, vif, "%s (%u) %s", "error in rxq-queue",
948                             RX_QUEUE (i), "initialization");
949
950       if ((error = virtio_pci_vring_init (vm, vif, TX_QUEUE (i))))
951         virtio_log_warning (vim, vif, "%s (%u) %s", "error in txq-queue",
952                             TX_QUEUE (i), "initialization");
953     }
954
955   if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
956     {
957       if ((error =
958            virtio_pci_control_vring_init (vm, vif, vif->max_queue_pairs * 2)))
959         {
960           virtio_log_warning (vim, vif, "%s (%u) %s",
961                               "error in control-queue",
962                               vif->max_queue_pairs * 2, "initialization");
963           if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MQ))
964             vif->features &= ~VIRTIO_FEATURE (VIRTIO_NET_F_MQ);
965         }
966     }
967   else
968     {
969       virtio_log_debug (vim, vif, "control queue is not available");
970       vif->cxq_vring = NULL;
971     }
972
973   /*
974    * set the msix interrupts
975    */
976   if (vif->msix_enabled == VIRTIO_MSIX_ENABLED)
977     {
978       if (virtio_pci_legacy_set_config_irq (vm, vif, 1) ==
979           VIRTIO_MSI_NO_VECTOR)
980         virtio_log_warning (vim, vif, "config vector 1 is not set");
981       if (virtio_pci_legacy_set_queue_irq (vm, vif, 0, 0) ==
982           VIRTIO_MSI_NO_VECTOR)
983         virtio_log_warning (vim, vif, "queue vector 0 is not set");
984     }
985
986   /*
987    * set the driver status OK
988    */
989   virtio_pci_legacy_set_status (vm, vif, VIRTIO_CONFIG_STATUS_DRIVER_OK);
990   vif->status = virtio_pci_legacy_get_status (vm, vif);
991 error:
992   return error;
993 }
994
995 void
996 virtio_pci_create_if (vlib_main_t * vm, virtio_pci_create_if_args_t * args)
997 {
998   vnet_main_t *vnm = vnet_get_main ();
999   virtio_main_t *vim = &virtio_main;
1000   virtio_if_t *vif;
1001   vlib_pci_dev_handle_t h;
1002   clib_error_t *error = 0;
1003
1004   if (args->rxq_size == 0)
1005     args->rxq_size = VIRTIO_NUM_RX_DESC;
1006   if (args->txq_size == 0)
1007     args->txq_size = VIRTIO_NUM_TX_DESC;
1008
1009   if (!virtio_pci_queue_size_valid (args->rxq_size) ||
1010       !virtio_pci_queue_size_valid (args->txq_size))
1011     {
1012       args->rv = VNET_API_ERROR_INVALID_VALUE;
1013       args->error =
1014         clib_error_return (error,
1015                            "queue size must be <= 4096, >= 64, "
1016                            "and multiples of 64");
1017       vlib_log (VLIB_LOG_LEVEL_ERR, vim->log_default, "%U: %s",
1018                 format_vlib_pci_addr, &args->addr,
1019                 "queue size must be <= 4096, >= 64, and multiples of 64");
1020       return;
1021     }
1022
1023   /* *INDENT-OFF* */
1024   pool_foreach (vif, vim->interfaces, ({
1025     if (vif->pci_addr.as_u32 == args->addr)
1026       {
1027         args->rv = VNET_API_ERROR_INVALID_VALUE;
1028         args->error =
1029           clib_error_return (error, "PCI address in use");
1030           vlib_log (VLIB_LOG_LEVEL_ERR, vim->log_default, "%U: %s",
1031                 format_vlib_pci_addr, &args->addr,
1032                 " PCI address in use");
1033         return;
1034       }
1035   }));
1036   /* *INDENT-ON* */
1037
1038   pool_get (vim->interfaces, vif);
1039   vif->dev_instance = vif - vim->interfaces;
1040   vif->per_interface_next_index = ~0;
1041   vif->pci_addr.as_u32 = args->addr;
1042
1043   if ((error =
1044        vlib_pci_device_open (vm, (vlib_pci_addr_t *) & vif->pci_addr,
1045                              virtio_pci_device_ids, &h)))
1046     {
1047       pool_put (vim->interfaces, vif);
1048       args->rv = VNET_API_ERROR_INVALID_INTERFACE;
1049       args->error =
1050         clib_error_return (error, "pci-addr %U", format_vlib_pci_addr,
1051                            &vif->pci_addr);
1052       vlib_log (VLIB_LOG_LEVEL_ERR, vim->log_default, "%U: %s",
1053                 format_vlib_pci_addr, &vif->pci_addr,
1054                 "error encountered on pci device open");
1055       return;
1056     }
1057   vif->pci_dev_handle = h;
1058   vlib_pci_set_private_data (vm, h, vif->dev_instance);
1059   vif->numa_node = vlib_pci_get_numa_node (vm, h);
1060
1061   if ((error = vlib_pci_bus_master_enable (vm, h)))
1062     {
1063       virtio_log_error (vim, vif,
1064                         "error encountered on pci bus master enable");
1065       goto error;
1066     }
1067
1068   if ((error = vlib_pci_io_region (vm, h, 0)))
1069     {
1070       virtio_log_error (vim, vif, "error encountered on pci io region");
1071       goto error;
1072     }
1073
1074   if (vlib_pci_get_num_msix_interrupts (vm, h) > 1)
1075     {
1076       if ((error = vlib_pci_register_msix_handler (vm, h, 0, 1,
1077                                                    &virtio_pci_irq_0_handler)))
1078         {
1079           virtio_log_error (vim, vif,
1080                             "error encountered on pci register msix handler 0");
1081           goto error;
1082         }
1083       if ((error = vlib_pci_register_msix_handler (vm, h, 1, 1,
1084                                                    &virtio_pci_irq_1_handler)))
1085         {
1086           virtio_log_error (vim, vif,
1087                             "error encountered on pci register msix handler 1");
1088           goto error;
1089         }
1090
1091       if ((error = vlib_pci_enable_msix_irq (vm, h, 0, 2)))
1092         {
1093           virtio_log_error (vim, vif,
1094                             "error encountered on pci enable msix irq");
1095           goto error;
1096         }
1097       vif->support_int_mode = 1;
1098       virtio_log_debug (vim, vif, "device supports msix interrupts");
1099     }
1100   else if (vlib_pci_get_num_msix_interrupts (vm, h) == 1)
1101     {
1102       /*
1103        * if msix table-size is 1, fall back to intX.
1104        */
1105       if ((error =
1106            vlib_pci_register_intx_handler (vm, h, &virtio_pci_irq_handler)))
1107         {
1108           virtio_log_error (vim, vif,
1109                             "error encountered on pci register interrupt handler");
1110           goto error;
1111         }
1112       vif->support_int_mode = 1;
1113       virtio_log_debug (vim, vif, "pci register interrupt handler");
1114     }
1115   else
1116     {
1117       /*
1118        * WARN: intX is showing some weird behaviour.
1119        * Please don't use interrupt mode with UIO driver.
1120        */
1121       vif->support_int_mode = 0;
1122       virtio_log_debug (vim, vif, "driver is configured in poll mode only");
1123     }
1124
1125   if ((error = vlib_pci_intr_enable (vm, h)))
1126     {
1127       virtio_log_error (vim, vif,
1128                         "error encountered on pci interrupt enable");
1129       goto error;
1130     }
1131
1132   if ((error = virtio_pci_device_init (vm, vif, args)))
1133     {
1134       virtio_log_error (vim, vif, "error encountered on device init");
1135       goto error;
1136     }
1137
1138   vif->type = VIRTIO_IF_TYPE_PCI;
1139   /* create interface */
1140   error = ethernet_register_interface (vnm, virtio_device_class.index,
1141                                        vif->dev_instance, vif->mac_addr,
1142                                        &vif->hw_if_index,
1143                                        virtio_pci_flag_change);
1144
1145   if (error)
1146     {
1147       virtio_log_error (vim, vif,
1148                         "error encountered on ethernet register interface");
1149       goto error;
1150     }
1151
1152   vnet_sw_interface_t *sw = vnet_get_hw_sw_interface (vnm, vif->hw_if_index);
1153   vif->sw_if_index = sw->sw_if_index;
1154   args->sw_if_index = sw->sw_if_index;
1155
1156   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, vif->hw_if_index);
1157   hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE;
1158   vnet_hw_interface_set_input_node (vnm, vif->hw_if_index,
1159                                     virtio_input_node.index);
1160   u32 i = 0;
1161   vec_foreach_index (i, vif->rxq_vrings)
1162   {
1163     vnet_hw_interface_assign_rx_thread (vnm, vif->hw_if_index, i, ~0);
1164     virtio_vring_set_numa_node (vm, vif, RX_QUEUE (i));
1165     /* Set default rx mode to POLLING */
1166     vnet_hw_interface_set_rx_mode (vnm, vif->hw_if_index, i,
1167                                    VNET_HW_INTERFACE_RX_MODE_POLLING);
1168   }
1169   if (virtio_pci_is_link_up (vm, vif) & VIRTIO_NET_S_LINK_UP)
1170     {
1171       vif->flags |= VIRTIO_IF_FLAG_ADMIN_UP;
1172       vnet_hw_interface_set_flags (vnm, vif->hw_if_index,
1173                                    VNET_HW_INTERFACE_FLAG_LINK_UP);
1174     }
1175   else
1176     vnet_hw_interface_set_flags (vnm, vif->hw_if_index, 0);
1177
1178   if ((vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ)) &&
1179       (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_MQ)))
1180     {
1181       if (virtio_pci_enable_multiqueue (vm, vif, vif->max_queue_pairs))
1182         virtio_log_warning (vim, vif, "multiqueue is not set");
1183     }
1184   return;
1185
1186 error:
1187   virtio_pci_delete_if (vm, vif);
1188   args->rv = VNET_API_ERROR_INVALID_INTERFACE;
1189   args->error = error;
1190 }
1191
1192 int
1193 virtio_pci_delete_if (vlib_main_t * vm, virtio_if_t * vif)
1194 {
1195   vnet_main_t *vnm = vnet_get_main ();
1196   virtio_main_t *vim = &virtio_main;
1197   u32 i = 0;
1198
1199   if (vif->type != VIRTIO_IF_TYPE_PCI)
1200     return VNET_API_ERROR_INVALID_INTERFACE;
1201
1202   vlib_pci_intr_disable (vm, vif->pci_dev_handle);
1203
1204   for (i = 0; i < vif->max_queue_pairs; i++)
1205     {
1206       virtio_pci_legacy_del_queue (vm, vif, RX_QUEUE (i));
1207       virtio_pci_legacy_del_queue (vm, vif, TX_QUEUE (i));
1208     }
1209
1210   if (vif->features & VIRTIO_FEATURE (VIRTIO_NET_F_CTRL_VQ))
1211     virtio_pci_legacy_del_queue (vm, vif, vif->max_queue_pairs * 2);
1212
1213   virtio_pci_legacy_reset (vm, vif);
1214
1215   if (vif->hw_if_index)
1216     {
1217       vnet_hw_interface_set_flags (vnm, vif->hw_if_index, 0);
1218       vec_foreach_index (i, vif->rxq_vrings)
1219       {
1220         vnet_hw_interface_unassign_rx_thread (vnm, vif->hw_if_index, i);
1221       }
1222       ethernet_delete_interface (vnm, vif->hw_if_index);
1223     }
1224
1225   vlib_pci_device_close (vm, vif->pci_dev_handle);
1226
1227   vec_foreach_index (i, vif->rxq_vrings)
1228   {
1229     virtio_vring_t *vring = vec_elt_at_index (vif->rxq_vrings, i);
1230     if (vring->kick_fd != -1)
1231       close (vring->kick_fd);
1232     if (vring->used)
1233       {
1234         virtio_free_rx_buffers (vm, vring);
1235       }
1236     vec_free (vring->buffers);
1237     vec_free (vring->indirect_buffers);
1238     vlib_physmem_free (vm, vring->desc);
1239   }
1240
1241   vec_foreach_index (i, vif->txq_vrings)
1242   {
1243     virtio_vring_t *vring = vec_elt_at_index (vif->txq_vrings, i);
1244     if (vring->kick_fd != -1)
1245       close (vring->kick_fd);
1246     if (vring->used)
1247       {
1248         virtio_free_used_desc (vm, vring);
1249       }
1250     if (vring->queue_id % 2)
1251       {
1252         vlib_buffer_free_no_next (vm, vring->indirect_buffers, vring->size);
1253       }
1254     vec_free (vring->buffers);
1255     vec_free (vring->indirect_buffers);
1256     vlib_physmem_free (vm, vring->desc);
1257   }
1258
1259   if (vif->cxq_vring != NULL)
1260     {
1261       u16 last = vif->cxq_vring->last_used_idx;
1262       u16 n_left = vif->cxq_vring->used->idx - last;
1263       while (n_left)
1264         {
1265           last++;
1266           n_left--;
1267         }
1268
1269       vif->cxq_vring->last_used_idx = last;
1270       vlib_physmem_free (vm, vif->cxq_vring->desc);
1271     }
1272
1273   vec_free (vif->rxq_vrings);
1274   vec_free (vif->txq_vrings);
1275   vec_free (vif->cxq_vring);
1276
1277   if (vif->fd != -1)
1278     vif->fd = -1;
1279   if (vif->tap_fd != -1)
1280     vif->tap_fd = -1;
1281   clib_error_free (vif->error);
1282   memset (vif, 0, sizeof (*vif));
1283   pool_put (vim->interfaces, vif);
1284
1285   return 0;
1286 }
1287
1288 /*
1289  * fd.io coding-style-patch-verification: ON
1290  *
1291  * Local Variables:
1292  * eval: (c-set-style "gnu")
1293  * End:
1294  */