misc: move to new pool_foreach macros
[vpp.git] / src / plugins / vmxnet3 / vmxnet3.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 <vppinfra/types.h>
17 #include <vlib/vlib.h>
18 #include <vlib/pci/pci.h>
19 #include <vnet/ethernet/ethernet.h>
20 #include <vnet/plugin/plugin.h>
21 #include <vpp/app/version.h>
22
23 #include <vmxnet3/vmxnet3.h>
24
25 #define PCI_VENDOR_ID_VMWARE                            0x15ad
26 #define PCI_DEVICE_ID_VMWARE_VMXNET3                    0x07b0
27
28 vmxnet3_main_t vmxnet3_main;
29
30 static pci_device_id_t vmxnet3_pci_device_ids[] = {
31   {
32    .vendor_id = PCI_VENDOR_ID_VMWARE,
33    .device_id = PCI_DEVICE_ID_VMWARE_VMXNET3},
34   {0},
35 };
36
37 static clib_error_t *
38 vmxnet3_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index,
39                                  u32 flags)
40 {
41   vnet_hw_interface_t *hi = vnet_get_hw_interface (vnm, hw_if_index);
42   vmxnet3_main_t *vmxm = &vmxnet3_main;
43   vmxnet3_device_t *vd = vec_elt_at_index (vmxm->devices, hi->dev_instance);
44   uword is_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
45
46   if (vd->flags & VMXNET3_DEVICE_F_ERROR)
47     return clib_error_return (0, "device is in error state");
48
49   if (is_up)
50     {
51       vnet_hw_interface_set_flags (vnm, vd->hw_if_index,
52                                    VNET_HW_INTERFACE_FLAG_LINK_UP);
53       vd->flags |= VMXNET3_DEVICE_F_ADMIN_UP;
54     }
55   else
56     {
57       vnet_hw_interface_set_flags (vnm, vd->hw_if_index, 0);
58       vd->flags &= ~VMXNET3_DEVICE_F_ADMIN_UP;
59     }
60   return 0;
61 }
62
63 static clib_error_t *
64 vmxnet3_interface_rx_mode_change (vnet_main_t * vnm, u32 hw_if_index, u32 qid,
65                                   vnet_hw_if_rx_mode mode)
66 {
67   vmxnet3_main_t *vmxm = &vmxnet3_main;
68   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
69   vmxnet3_device_t *vd = pool_elt_at_index (vmxm->devices, hw->dev_instance);
70   vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, qid);
71
72   if (mode == VNET_HW_IF_RX_MODE_POLLING)
73     rxq->int_mode = 0;
74   else
75     rxq->int_mode = 1;
76
77   return 0;
78 }
79
80 static void
81 vmxnet3_set_interface_next_node (vnet_main_t * vnm, u32 hw_if_index,
82                                  u32 node_index)
83 {
84   vmxnet3_main_t *vmxm = &vmxnet3_main;
85   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
86   vmxnet3_device_t *vd = pool_elt_at_index (vmxm->devices, hw->dev_instance);
87
88   /* Shut off redirection */
89   if (node_index == ~0)
90     {
91       vd->per_interface_next_index = node_index;
92       return;
93     }
94
95   vd->per_interface_next_index =
96     vlib_node_add_next (vlib_get_main (), vmxnet3_input_node.index,
97                         node_index);
98 }
99
100 static void
101 vmxnet3_clear_hw_interface_counters (u32 instance)
102 {
103   vmxnet3_main_t *vmxm = &vmxnet3_main;
104   vmxnet3_device_t *vd = pool_elt_at_index (vmxm->devices, instance);
105   vmxnet3_tx_queue *tx = VMXNET3_TX_START (vd);
106   vmxnet3_rx_queue *rx = VMXNET3_RX_START (vd);
107   u16 qid;
108
109   /*
110    * Set the "last_cleared_stats" to the current stats, so that
111    * things appear to clear from a display perspective.
112    */
113   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_GET_STATS);
114
115   vec_foreach_index (qid, vd->txqs)
116   {
117     vmxnet3_tx_stats *txs = vec_elt_at_index (vd->tx_stats, qid);
118     clib_memcpy (txs, &tx->stats, sizeof (*txs));
119     tx++;
120   }
121   vec_foreach_index (qid, vd->rxqs)
122   {
123     vmxnet3_rx_stats *rxs = vec_elt_at_index (vd->rx_stats, qid);
124     clib_memcpy (rxs, &rx->stats, sizeof (*rxs));
125     rx++;
126   }
127 }
128
129 static char *vmxnet3_tx_func_error_strings[] = {
130 #define _(n,s) s,
131   foreach_vmxnet3_tx_func_error
132 #undef _
133 };
134
135 /* *INDENT-OFF* */
136 VNET_DEVICE_CLASS (vmxnet3_device_class,) =
137 {
138   .name = "VMXNET3 interface",
139   .format_device = format_vmxnet3_device,
140   .format_device_name = format_vmxnet3_device_name,
141   .admin_up_down_function = vmxnet3_interface_admin_up_down,
142   .clear_counters = vmxnet3_clear_hw_interface_counters,
143   .rx_mode_change_function = vmxnet3_interface_rx_mode_change,
144   .rx_redirect_to_node = vmxnet3_set_interface_next_node,
145   .tx_function_n_errors = VMXNET3_TX_N_ERROR,
146   .tx_function_error_strings = vmxnet3_tx_func_error_strings,
147 };
148 /* *INDENT-ON* */
149
150 static u32
151 vmxnet3_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hw, u32 flags)
152 {
153   return 0;
154 }
155
156 static void
157 vmxnet3_write_mac (vmxnet3_device_t * vd)
158 {
159   u32 val;
160
161   memcpy (&val, vd->mac_addr, 4);
162   vmxnet3_reg_write (vd, 1, VMXNET3_REG_MACL, val);
163
164   val = 0;
165   memcpy (&val, vd->mac_addr + 4, 2);
166   vmxnet3_reg_write (vd, 1, VMXNET3_REG_MACH, val);
167 }
168
169 static clib_error_t *
170 vmxnet3_provision_driver_shared (vlib_main_t * vm, vmxnet3_device_t * vd)
171 {
172   vmxnet3_shared *shared;
173   u64 shared_dma;
174   u16 qid, rid;
175   vmxnet3_tx_queue *tx = VMXNET3_TX_START (vd);
176   vmxnet3_rx_queue *rx = VMXNET3_RX_START (vd);
177
178   vd->driver_shared =
179     vlib_physmem_alloc_aligned_on_numa (vm, sizeof (*vd->driver_shared), 512,
180                                         vd->numa_node);
181   if (vd->driver_shared == 0)
182     return vlib_physmem_last_error (vm);
183
184   clib_memset (vd->driver_shared, 0, sizeof (*vd->driver_shared));
185
186   vec_foreach_index (qid, vd->txqs)
187   {
188     vmxnet3_txq_t *txq = vec_elt_at_index (vd->txqs, qid);
189
190     tx->cfg.desc_address = vmxnet3_dma_addr (vm, vd, txq->tx_desc);
191     tx->cfg.comp_address = vmxnet3_dma_addr (vm, vd, txq->tx_comp);
192     tx->cfg.num_desc = txq->size;
193     tx->cfg.num_comp = txq->size;
194     tx++;
195   }
196
197   vec_foreach_index (qid, vd->rxqs)
198   {
199     vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, qid);
200
201     for (rid = 0; rid < VMXNET3_RX_RING_SIZE; rid++)
202       {
203         rx->cfg.desc_address[rid] = vmxnet3_dma_addr (vm, vd,
204                                                       rxq->rx_desc[rid]);
205         rx->cfg.num_desc[rid] = rxq->size;
206       }
207     rx->cfg.comp_address = vmxnet3_dma_addr (vm, vd, rxq->rx_comp);
208     rx->cfg.num_comp = rxq->size;
209     rx->cfg.intr_index = qid;
210     rx++;
211   }
212
213   shared = vd->driver_shared;
214   shared->magic = VMXNET3_SHARED_MAGIC;
215   shared->misc.version = VMXNET3_VERSION_MAGIC;
216   if (sizeof (void *) == 4)
217     shared->misc.guest_info = VMXNET3_GOS_BITS_32;
218   else
219     shared->misc.guest_info = VMXNET3_GOS_BITS_64;
220   shared->misc.guest_info |= VMXNET3_GOS_TYPE_LINUX;
221   shared->misc.version_support = VMXNET3_VERSION_SELECT;
222   shared->misc.upt_features = VMXNET3_F_RXCSUM;
223   if (vd->gso_enable)
224     shared->misc.upt_features |= VMXNET3_F_LRO;
225   if (vd->num_rx_queues > 1)
226     {
227       shared->misc.upt_features |= VMXNET3_F_RSS;
228       shared->rss.version = 1;
229       shared->rss.address = vmxnet3_dma_addr (vm, vd, vd->rss);
230       shared->rss.length = sizeof (*vd->rss);
231     }
232   shared->misc.max_num_rx_sg = 0;
233   shared->misc.upt_version_support = VMXNET3_UPT_VERSION_SELECT;
234   shared->misc.queue_desc_address = vmxnet3_dma_addr (vm, vd, vd->queues);
235   shared->misc.queue_desc_len = sizeof (*tx) * vd->num_tx_queues +
236     sizeof (*rx) * vd->num_rx_queues;
237   shared->misc.mtu = VMXNET3_MTU;
238   shared->misc.num_tx_queues = vd->num_tx_queues;
239   shared->misc.num_rx_queues = vd->num_rx_queues;
240   shared->interrupt.num_intrs = vd->num_intrs;
241   shared->interrupt.event_intr_index = vd->num_rx_queues;
242   shared->interrupt.control = VMXNET3_IC_DISABLE_ALL;
243   shared->rx_filter.mode = VMXNET3_RXMODE_UCAST | VMXNET3_RXMODE_BCAST |
244     VMXNET3_RXMODE_ALL_MULTI | VMXNET3_RXMODE_PROMISC;
245   shared_dma = vmxnet3_dma_addr (vm, vd, shared);
246
247   vmxnet3_reg_write (vd, 1, VMXNET3_REG_DSAL, shared_dma);
248   vmxnet3_reg_write (vd, 1, VMXNET3_REG_DSAH, shared_dma >> 32);
249
250   return 0;
251 }
252
253 static inline void
254 vmxnet3_enable_interrupt (vmxnet3_device_t * vd)
255 {
256   int i;
257   vmxnet3_shared *shared = vd->driver_shared;
258
259   shared->interrupt.control &= ~VMXNET3_IC_DISABLE_ALL;
260   for (i = 0; i < vd->num_intrs; i++)
261     vmxnet3_reg_write (vd, 0, VMXNET3_REG_IMR + i * 8, 0);
262 }
263
264 static inline void
265 vmxnet3_disable_interrupt (vmxnet3_device_t * vd)
266 {
267   int i;
268   vmxnet3_shared *shared = vd->driver_shared;
269
270   shared->interrupt.control |= VMXNET3_IC_DISABLE_ALL;
271   for (i = 0; i < vd->num_intrs; i++)
272     vmxnet3_reg_write (vd, 0, VMXNET3_REG_IMR + i * 8, 1);
273 }
274
275 static clib_error_t *
276 vmxnet3_rxq_init (vlib_main_t * vm, vmxnet3_device_t * vd, u16 qid, u16 qsz)
277 {
278   vmxnet3_rxq_t *rxq;
279   vmxnet3_rx_stats *rxs;
280   u16 rid;
281
282   vec_validate (vd->rx_stats, qid);
283   rxs = vec_elt_at_index (vd->rx_stats, qid);
284   clib_memset (rxs, 0, sizeof (*rxs));
285
286   vec_validate_aligned (vd->rxqs, qid, CLIB_CACHE_LINE_BYTES);
287   rxq = vec_elt_at_index (vd->rxqs, qid);
288   clib_memset (rxq, 0, sizeof (*rxq));
289   rxq->size = qsz;
290   for (rid = 0; rid < VMXNET3_RX_RING_SIZE; rid++)
291     {
292       rxq->rx_desc[rid] = vlib_physmem_alloc_aligned_on_numa
293         (vm, qsz * sizeof (*rxq->rx_desc[rid]), 512, vd->numa_node);
294
295       if (rxq->rx_desc[rid] == 0)
296         return vlib_physmem_last_error (vm);
297
298       clib_memset (rxq->rx_desc[rid], 0, qsz * sizeof (*rxq->rx_desc[rid]));
299     }
300   rxq->rx_comp =
301     vlib_physmem_alloc_aligned_on_numa (vm, qsz * sizeof (*rxq->rx_comp), 512,
302                                         vd->numa_node);
303   if (rxq->rx_comp == 0)
304     return vlib_physmem_last_error (vm);
305
306   clib_memset (rxq->rx_comp, 0, qsz * sizeof (*rxq->rx_comp));
307   for (rid = 0; rid < VMXNET3_RX_RING_SIZE; rid++)
308     {
309       vmxnet3_rx_ring *ring;
310
311       ring = &rxq->rx_ring[rid];
312       ring->gen = VMXNET3_RXF_GEN;
313       ring->rid = rid;
314       vec_validate_aligned (ring->bufs, rxq->size, CLIB_CACHE_LINE_BYTES);
315     }
316   rxq->rx_comp_ring.gen = VMXNET3_RXCF_GEN;
317
318   return 0;
319 }
320
321 static clib_error_t *
322 vmxnet3_txq_init (vlib_main_t * vm, vmxnet3_device_t * vd, u16 qid, u16 qsz)
323 {
324   vmxnet3_txq_t *txq;
325   vmxnet3_tx_stats *txs;
326   u32 size;
327
328   if (qid >= vd->num_tx_queues)
329     {
330       qid = qid % vd->num_tx_queues;
331       txq = vec_elt_at_index (vd->txqs, qid);
332       if (txq->lock == 0)
333         clib_spinlock_init (&txq->lock);
334       vd->flags |= VMXNET3_DEVICE_F_SHARED_TXQ_LOCK;
335       return 0;
336     }
337
338   vec_validate (vd->tx_stats, qid);
339   txs = vec_elt_at_index (vd->tx_stats, qid);
340   clib_memset (txs, 0, sizeof (*txs));
341
342   vec_validate_aligned (vd->txqs, qid, CLIB_CACHE_LINE_BYTES);
343   txq = vec_elt_at_index (vd->txqs, qid);
344   clib_memset (txq, 0, sizeof (*txq));
345   txq->size = qsz;
346   txq->reg_txprod = qid * 8 + VMXNET3_REG_TXPROD;
347
348   size = qsz * sizeof (*txq->tx_desc);
349   txq->tx_desc =
350     vlib_physmem_alloc_aligned_on_numa (vm, size, 512, vd->numa_node);
351   if (txq->tx_desc == 0)
352     return vlib_physmem_last_error (vm);
353
354   memset (txq->tx_desc, 0, size);
355
356   size = qsz * sizeof (*txq->tx_comp);
357   txq->tx_comp =
358     vlib_physmem_alloc_aligned_on_numa (vm, size, 512, vd->numa_node);
359   if (txq->tx_comp == 0)
360     return vlib_physmem_last_error (vm);
361
362   clib_memset (txq->tx_comp, 0, size);
363   vec_validate_aligned (txq->tx_ring.bufs, txq->size, CLIB_CACHE_LINE_BYTES);
364   txq->tx_ring.gen = VMXNET3_TXF_GEN;
365   txq->tx_comp_ring.gen = VMXNET3_TXCF_GEN;
366
367   return 0;
368 }
369
370 static const u8 vmxnet3_rss_key[VMXNET3_RSS_MAX_KEY_SZ] = {
371   0x3b, 0x56, 0xd1, 0x56, 0x13, 0x4a, 0xe7, 0xac,
372   0xe8, 0x79, 0x09, 0x75, 0xe8, 0x65, 0x79, 0x28,
373   0x35, 0x12, 0xb9, 0x56, 0x7c, 0x76, 0x4b, 0x70,
374   0xd8, 0x56, 0xa3, 0x18, 0x9b, 0x0a, 0xee, 0xf3,
375   0x96, 0xa6, 0x9f, 0x8f, 0x9e, 0x8c, 0x90, 0xc9,
376 };
377
378 static clib_error_t *
379 vmxnet3_rss_init (vlib_main_t * vm, vmxnet3_device_t * vd)
380 {
381   vmxnet3_rss_shared *rss;
382   size_t size = sizeof (*rss);
383   u8 i;
384
385   vd->rss = vlib_physmem_alloc_aligned_on_numa (vm, size, 512, vd->numa_node);
386   if (vd->rss == 0)
387     return vlib_physmem_last_error (vm);
388
389   clib_memset (vd->rss, 0, size);
390   rss = vd->rss;
391   rss->hash_type =
392     VMXNET3_RSS_HASH_TYPE_IPV4 | VMXNET3_RSS_HASH_TYPE_TCP_IPV4 |
393     VMXNET3_RSS_HASH_TYPE_IPV6 | VMXNET3_RSS_HASH_TYPE_TCP_IPV6;
394   rss->hash_func = VMXNET3_RSS_HASH_FUNC_TOEPLITZ;
395   rss->hash_key_sz = VMXNET3_RSS_MAX_KEY_SZ;
396   rss->ind_table_sz = VMXNET3_RSS_MAX_IND_TABLE_SZ;
397   clib_memcpy (rss->hash_key, vmxnet3_rss_key, VMXNET3_RSS_MAX_KEY_SZ);
398   for (i = 0; i < rss->ind_table_sz; i++)
399     rss->ind_table[i] = i % vd->num_rx_queues;
400
401   return 0;
402 }
403
404 static clib_error_t *
405 vmxnet3_device_init (vlib_main_t * vm, vmxnet3_device_t * vd,
406                      vmxnet3_create_if_args_t * args)
407 {
408   clib_error_t *error = 0;
409   u32 ret, i, size;
410   vlib_thread_main_t *tm = vlib_get_thread_main ();
411
412   /* Quiesce the device */
413   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_QUIESCE_DEV);
414   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_CMD);
415   if (ret != 0)
416     {
417       error = clib_error_return (0, "error on quiescing device rc (%u)", ret);
418       return error;
419     }
420
421   /* Reset the device */
422   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_RESET_DEV);
423   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_CMD);
424   if (ret != 0)
425     {
426       error = clib_error_return (0, "error on resetting device rc (%u)", ret);
427       return error;
428     }
429
430   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_VRRS);
431   vd->version = count_leading_zeros (ret);
432   vd->version = uword_bits - vd->version;
433
434   if (vd->version == 0)
435     {
436       error = clib_error_return (0, "unsupported hardware version %u",
437                                  vd->version);
438       return error;
439     }
440
441   /* cap support version to 3 */
442   vmxnet3_reg_write (vd, 1, VMXNET3_REG_VRRS,
443                      1 << (clib_min (3, vd->version) - 1));
444
445   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_UVRS);
446   if (ret & 1)
447     vmxnet3_reg_write (vd, 1, VMXNET3_REG_UVRS, 1);
448   else
449     {
450       error = clib_error_return (0, "unsupported upt version %u", ret);
451       return error;
452     }
453
454   /* GSO is only supported for version >= 3 */
455   if (args->enable_gso)
456     {
457       if (vd->version >= 3)
458         vd->gso_enable = 1;
459       else
460         {
461           error =
462             clib_error_return (0,
463                                "GSO is not supported because hardware version"
464                                " is %u. It must be >= 3", vd->version);
465           return error;
466         }
467     }
468
469   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK);
470   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_CMD);
471   if (ret & 1)
472     {
473       vd->flags |= VMXNET3_DEVICE_F_LINK_UP;
474       vd->link_speed = ret >> 16;
475     }
476   else
477     vd->flags &= ~VMXNET3_DEVICE_F_LINK_UP;
478
479   /* Get the mac address */
480   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_MACL);
481   clib_memcpy (vd->mac_addr, &ret, 4);
482   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_MACH);
483   clib_memcpy (vd->mac_addr + 4, &ret, 2);
484
485   size = sizeof (vmxnet3_rx_queue) * vd->num_rx_queues +
486     sizeof (vmxnet3_tx_queue) * vd->num_tx_queues;
487
488   vd->queues =
489     vlib_physmem_alloc_aligned_on_numa (vm, size, 512, vd->numa_node);
490   if (vd->queues == 0)
491     return vlib_physmem_last_error (vm);
492
493   clib_memset (vd->queues, 0, size);
494
495   if (vd->num_rx_queues > 1)
496     {
497       error = vmxnet3_rss_init (vm, vd);
498       if (error)
499         return error;
500     }
501
502   for (i = 0; i < vd->num_rx_queues; i++)
503     {
504       error = vmxnet3_rxq_init (vm, vd, i, args->rxq_size);
505       if (error)
506         return error;
507     }
508
509   for (i = 0; i < tm->n_vlib_mains; i++)
510     {
511       error = vmxnet3_txq_init (vm, vd, i, args->txq_size);
512       if (error)
513         return error;
514     }
515
516   error = vmxnet3_provision_driver_shared (vm, vd);
517   if (error)
518     return error;
519
520   vmxnet3_write_mac (vd);
521
522   /* Activate device */
523   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_ACTIVATE_DEV);
524   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_CMD);
525   if (ret != 0)
526     {
527       error =
528         clib_error_return (0, "error on activating device rc (%u)", ret);
529       return error;
530     }
531
532   return error;
533 }
534
535 static void
536 vmxnet3_rxq_irq_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h, u16 line)
537 {
538   vnet_main_t *vnm = vnet_get_main ();
539   vmxnet3_main_t *vmxm = &vmxnet3_main;
540   uword pd = vlib_pci_get_private_data (vm, h);
541   vmxnet3_device_t *vd = pool_elt_at_index (vmxm->devices, pd);
542   u16 qid = line;
543
544   if (vec_len (vd->rxqs) > qid && vd->rxqs[qid].int_mode != 0)
545     vnet_device_input_set_interrupt_pending (vnm, vd->hw_if_index, qid);
546 }
547
548 static void
549 vmxnet3_event_irq_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h,
550                            u16 line)
551 {
552   vnet_main_t *vnm = vnet_get_main ();
553   vmxnet3_main_t *vmxm = &vmxnet3_main;
554   uword pd = vlib_pci_get_private_data (vm, h);
555   vmxnet3_device_t *vd = pool_elt_at_index (vmxm->devices, pd);
556   u32 ret;
557
558   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK);
559   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_CMD);
560   if (ret & 1)
561     {
562       vd->flags |= VMXNET3_DEVICE_F_LINK_UP;
563       vd->link_speed = ret >> 16;
564       vnet_hw_interface_set_link_speed (vnm, vd->hw_if_index,
565                                         vd->link_speed * 1000);
566       vnet_hw_interface_set_flags (vnm, vd->hw_if_index,
567                                    VNET_HW_INTERFACE_FLAG_LINK_UP);
568     }
569   else
570     {
571       vd->flags &= ~VMXNET3_DEVICE_F_LINK_UP;
572       vnet_hw_interface_set_flags (vnm, vd->hw_if_index, 0);
573     }
574 }
575
576 static u8
577 vmxnet3_queue_size_valid (u16 qsz)
578 {
579   if (qsz < 64 || qsz > 4096)
580     return 0;
581   if ((qsz % 64) != 0)
582     return 0;
583   return 1;
584 }
585
586 static u8
587 vmxnet3_tx_queue_num_valid (u16 num)
588 {
589   vlib_thread_main_t *tm = vlib_get_thread_main ();
590
591   if ((num > VMXNET3_TXQ_MAX) || (num > tm->n_vlib_mains))
592     return 0;
593   return 1;
594 }
595
596 static u8
597 vmxnet3_rx_queue_num_valid (u16 num)
598 {
599   if (num > VMXNET3_RXQ_MAX)
600     return 0;
601   return 1;
602 }
603
604 void
605 vmxnet3_create_if (vlib_main_t * vm, vmxnet3_create_if_args_t * args)
606 {
607   vnet_main_t *vnm = vnet_get_main ();
608   vmxnet3_main_t *vmxm = &vmxnet3_main;
609   vmxnet3_device_t *vd;
610   vlib_pci_dev_handle_t h;
611   clib_error_t *error = 0;
612   u16 qid;
613   u32 num_intr;
614
615   if (args->txq_num == 0)
616     args->txq_num = 1;
617   if (args->rxq_num == 0)
618     args->rxq_num = 1;
619   if (!vmxnet3_rx_queue_num_valid (args->rxq_num))
620     {
621       args->rv = VNET_API_ERROR_INVALID_VALUE;
622       args->error =
623         clib_error_return (error, "number of rx queues must be <= %u",
624                            VMXNET3_RXQ_MAX);
625       vlib_log (VLIB_LOG_LEVEL_ERR, vmxm->log_default, "%U: %s",
626                 format_vlib_pci_addr, &args->addr,
627                 "number of rx queues must be <= %u", VMXNET3_RXQ_MAX);
628       return;
629     }
630
631   if (!vmxnet3_tx_queue_num_valid (args->txq_num))
632     {
633       args->rv = VNET_API_ERROR_INVALID_VALUE;
634       args->error =
635         clib_error_return (error,
636                            "number of tx queues must be <= %u and <= number of "
637                            "CPU's assigned to VPP", VMXNET3_TXQ_MAX);
638       vlib_log (VLIB_LOG_LEVEL_ERR, vmxm->log_default, "%U: %s",
639                 format_vlib_pci_addr, &args->addr,
640                 "number of tx queues must be <= %u and <= number of "
641                 "CPU's assigned to VPP", VMXNET3_TXQ_MAX);
642       return;
643     }
644   if (args->rxq_size == 0)
645     args->rxq_size = VMXNET3_NUM_RX_DESC;
646   if (args->txq_size == 0)
647     args->txq_size = VMXNET3_NUM_TX_DESC;
648
649   if (!vmxnet3_queue_size_valid (args->rxq_size) ||
650       !vmxnet3_queue_size_valid (args->txq_size))
651     {
652       args->rv = VNET_API_ERROR_INVALID_VALUE;
653       args->error =
654         clib_error_return (error,
655                            "queue size must be <= 4096, >= 64, "
656                            "and multiples of 64");
657       vlib_log (VLIB_LOG_LEVEL_ERR, vmxm->log_default, "%U: %s",
658                 format_vlib_pci_addr, &args->addr,
659                 "queue size must be <= 4096, >= 64, and multiples of 64");
660       return;
661     }
662
663   /* *INDENT-OFF* */
664   pool_foreach (vd, vmxm->devices)  {
665     if (vd->pci_addr.as_u32 == args->addr.as_u32)
666       {
667         args->rv = VNET_API_ERROR_ADDRESS_IN_USE;
668         args->error =
669           clib_error_return (error, "%U: %s", format_vlib_pci_addr,
670                              &args->addr, "pci address in use");
671         vlib_log (VLIB_LOG_LEVEL_ERR, vmxm->log_default, "%U: %s",
672                   format_vlib_pci_addr, &args->addr, "pci address in use");
673         return;
674       }
675   }
676   /* *INDENT-ON* */
677
678   if (args->bind)
679     {
680       error = vlib_pci_bind_to_uio (vm, &args->addr, (char *) "auto");
681       if (error)
682         {
683           args->rv = VNET_API_ERROR_INVALID_INTERFACE;
684           args->error =
685             clib_error_return (error, "%U: %s", format_vlib_pci_addr,
686                                &args->addr,
687                                "error encountered on binding pci device");
688           vlib_log (VLIB_LOG_LEVEL_ERR, vmxm->log_default, "%U: %s",
689                     format_vlib_pci_addr, &args->addr,
690                     "error encountered on binding pci devicee");
691           return;
692         }
693     }
694
695   if ((error =
696        vlib_pci_device_open (vm, &args->addr, vmxnet3_pci_device_ids, &h)))
697     {
698       args->rv = VNET_API_ERROR_INVALID_INTERFACE;
699       args->error =
700         clib_error_return (error, "%U: %s", format_vlib_pci_addr,
701                            &args->addr,
702                            "error encountered on pci device open");
703       vlib_log (VLIB_LOG_LEVEL_ERR, vmxm->log_default, "%U: %s",
704                 format_vlib_pci_addr, &args->addr,
705                 "error encountered on pci device open");
706       return;
707     }
708
709   /*
710    * Do not use vmxnet3_log_error prior to this line since the macro
711    * references vd->pci_dev_handle
712    */
713   pool_get (vmxm->devices, vd);
714   vd->num_tx_queues = args->txq_num;
715   vd->num_rx_queues = args->rxq_num;
716   vd->dev_instance = vd - vmxm->devices;
717   vd->per_interface_next_index = ~0;
718   vd->pci_addr = args->addr;
719
720   if (args->enable_elog)
721     vd->flags |= VMXNET3_DEVICE_F_ELOG;
722
723   vd->pci_dev_handle = h;
724   vd->numa_node = vlib_pci_get_numa_node (vm, h);
725   vd->num_intrs = vd->num_rx_queues + 1;        // +1 for the event interrupt
726
727   vlib_pci_set_private_data (vm, h, vd->dev_instance);
728
729   if ((error = vlib_pci_bus_master_enable (vm, h)))
730     {
731       vmxnet3_log_error (vd, "error encountered on pci bus master enable");
732       goto error;
733     }
734
735   if ((error = vlib_pci_map_region (vm, h, 0, (void **) &vd->bar[0])))
736     {
737       vmxnet3_log_error (vd, "error encountered on pci map region for bar 0");
738       goto error;
739     }
740
741   if ((error = vlib_pci_map_region (vm, h, 1, (void **) &vd->bar[1])))
742     {
743       vmxnet3_log_error (vd, "error encountered on pci map region for bar 1");
744       goto error;
745     }
746
747   num_intr = vlib_pci_get_num_msix_interrupts (vm, h);
748   if (num_intr < vd->num_rx_queues + 1)
749     {
750       vmxnet3_log_error (vd,
751                          "No sufficient interrupt lines (%u) for rx queues",
752                          num_intr);
753       error =
754         clib_error_return (0,
755                            "No sufficient interrupt lines (%u) for rx queues",
756                            num_intr);
757       goto error;
758     }
759   if ((error = vlib_pci_register_msix_handler (vm, h, 0, vd->num_rx_queues,
760                                                &vmxnet3_rxq_irq_handler)))
761     {
762       vmxnet3_log_error (vd,
763                          "error encountered on pci register msix handler 0");
764       goto error;
765     }
766
767   if ((error = vlib_pci_register_msix_handler (vm, h, vd->num_rx_queues, 1,
768                                                &vmxnet3_event_irq_handler)))
769     {
770       vmxnet3_log_error (vd,
771                          "error encountered on pci register msix handler 1");
772       goto error;
773     }
774
775   if ((error = vlib_pci_enable_msix_irq (vm, h, 0, vd->num_rx_queues + 1)))
776     {
777       vmxnet3_log_error (vd, "error encountered on pci enable msix irq");
778       goto error;
779     }
780
781   if ((error = vlib_pci_intr_enable (vm, h)))
782     {
783       vmxnet3_log_error (vd, "error encountered on pci interrupt enable");
784       goto error;
785     }
786
787   if ((error = vmxnet3_device_init (vm, vd, args)))
788     {
789       vmxnet3_log_error (vd, "error encountered on device init");
790       goto error;
791     }
792
793   /* create interface */
794   error = ethernet_register_interface (vnm, vmxnet3_device_class.index,
795                                        vd->dev_instance, vd->mac_addr,
796                                        &vd->hw_if_index, vmxnet3_flag_change);
797
798   if (error)
799     {
800       vmxnet3_log_error (vd,
801                          "error encountered on ethernet register interface");
802       goto error;
803     }
804
805   vnet_sw_interface_t *sw = vnet_get_hw_sw_interface (vnm, vd->hw_if_index);
806   vd->sw_if_index = sw->sw_if_index;
807   args->sw_if_index = sw->sw_if_index;
808
809   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, vd->hw_if_index);
810   hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE;
811   if (vd->gso_enable)
812     hw->flags |= (VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO |
813                   VNET_HW_INTERFACE_FLAG_SUPPORTS_TX_L4_CKSUM_OFFLOAD);
814
815   vnet_hw_interface_set_input_node (vnm, vd->hw_if_index,
816                                     vmxnet3_input_node.index);
817   /* Disable interrupts */
818   vmxnet3_disable_interrupt (vd);
819   vec_foreach_index (qid, vd->rxqs)
820   {
821     vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, qid);
822     u32 thread_index;
823     u32 numa_node;
824
825     vnet_hw_interface_assign_rx_thread (vnm, vd->hw_if_index, qid, ~0);
826     thread_index = vnet_get_device_input_thread_index (vnm, vd->hw_if_index,
827                                                        qid);
828     numa_node = vlib_mains[thread_index]->numa_node;
829     rxq->buffer_pool_index =
830       vlib_buffer_pool_get_default_for_numa (vm, numa_node);
831     vmxnet3_rxq_refill_ring0 (vm, vd, rxq);
832     vmxnet3_rxq_refill_ring1 (vm, vd, rxq);
833   }
834   vd->flags |= VMXNET3_DEVICE_F_INITIALIZED;
835   vmxnet3_enable_interrupt (vd);
836
837   vnet_hw_interface_set_link_speed (vnm, vd->hw_if_index,
838                                     vd->link_speed * 1000);
839   if (vd->flags & VMXNET3_DEVICE_F_LINK_UP)
840     vnet_hw_interface_set_flags (vnm, vd->hw_if_index,
841                                  VNET_HW_INTERFACE_FLAG_LINK_UP);
842   else
843     vnet_hw_interface_set_flags (vnm, vd->hw_if_index, 0);
844   return;
845
846 error:
847   vmxnet3_delete_if (vm, vd);
848   args->rv = VNET_API_ERROR_INVALID_INTERFACE;
849   args->error = error;
850 }
851
852 void
853 vmxnet3_delete_if (vlib_main_t * vm, vmxnet3_device_t * vd)
854 {
855   vnet_main_t *vnm = vnet_get_main ();
856   vmxnet3_main_t *vmxm = &vmxnet3_main;
857   u32 i, bi;
858   u16 desc_idx, qid;
859
860   /* Quiesce the device */
861   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_QUIESCE_DEV);
862
863   /* Reset the device */
864   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_RESET_DEV);
865
866   if (vd->hw_if_index)
867     {
868       vnet_hw_interface_set_flags (vnm, vd->hw_if_index, 0);
869       vec_foreach_index (qid, vd->rxqs)
870         vnet_hw_interface_unassign_rx_thread (vnm, vd->hw_if_index, qid);
871       ethernet_delete_interface (vnm, vd->hw_if_index);
872     }
873
874   vlib_pci_device_close (vm, vd->pci_dev_handle);
875
876   /* *INDENT-OFF* */
877   vec_foreach_index (i, vd->rxqs)
878     {
879       vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, i);
880       u16 mask = rxq->size - 1;
881       u16 rid;
882
883       for (rid = 0; rid < VMXNET3_RX_RING_SIZE; rid++)
884         {
885           vmxnet3_rx_ring *ring;
886
887           ring = &rxq->rx_ring[rid];
888           desc_idx = (ring->consume + 1) & mask;
889           vlib_buffer_free_from_ring (vm, ring->bufs, desc_idx, rxq->size,
890                                       ring->fill);
891           vec_free (ring->bufs);
892           vlib_physmem_free (vm, rxq->rx_desc[rid]);
893         }
894       vlib_physmem_free (vm, rxq->rx_comp);
895     }
896   /* *INDENT-ON* */
897   vec_free (vd->rxqs);
898   vec_free (vd->rx_stats);
899
900   /* *INDENT-OFF* */
901   vec_foreach_index (i, vd->txqs)
902     {
903       vmxnet3_txq_t *txq = vec_elt_at_index (vd->txqs, i);
904       u16 mask = txq->size - 1;
905       u16 end_idx;
906
907       desc_idx = txq->tx_ring.consume;
908       end_idx = txq->tx_ring.produce;
909       while (desc_idx != end_idx)
910         {
911           bi = txq->tx_ring.bufs[desc_idx];
912           vlib_buffer_free_no_next (vm, &bi, 1);
913           desc_idx++;
914           desc_idx &= mask;
915         }
916       clib_spinlock_free (&txq->lock);
917       vec_free (txq->tx_ring.bufs);
918       vlib_physmem_free (vm, txq->tx_desc);
919       vlib_physmem_free (vm, txq->tx_comp);
920     }
921   /* *INDENT-ON* */
922   vec_free (vd->txqs);
923   vec_free (vd->tx_stats);
924
925   vlib_physmem_free (vm, vd->driver_shared);
926   vlib_physmem_free (vm, vd->queues);
927   vlib_physmem_free (vm, vd->rss);
928
929   clib_error_free (vd->error);
930   clib_memset (vd, 0, sizeof (*vd));
931   pool_put (vmxm->devices, vd);
932
933 }
934
935 /*
936  * fd.io coding-style-patch-verification: ON
937  *
938  * Local Variables:
939  * eval: (c-set-style "gnu")
940  * End:
941  */