vmxnet3: auto bind support
[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_interface_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_INTERFACE_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->lro_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   vnet_main_t *vnm = vnet_get_main ();
409   vmxnet3_main_t *vmxm = &vmxnet3_main;
410   clib_error_t *error = 0;
411   u32 ret, i, size;
412   vlib_thread_main_t *tm = vlib_get_thread_main ();
413
414   /* Quiesce the device */
415   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_QUIESCE_DEV);
416   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_CMD);
417   if (ret != 0)
418     {
419       error = clib_error_return (0, "error on quiescing device rc (%u)", ret);
420       return error;
421     }
422
423   /* Reset the device */
424   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_RESET_DEV);
425   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_CMD);
426   if (ret != 0)
427     {
428       error = clib_error_return (0, "error on resetting device rc (%u)", ret);
429       return error;
430     }
431
432   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_VRRS);
433   vd->version = count_leading_zeros (ret);
434   vd->version = uword_bits - vd->version;
435
436   if (vd->version == 0)
437     {
438       error = clib_error_return (0, "unsupported hardware version %u",
439                                  vd->version);
440       return error;
441     }
442
443   /* cap support version to 3 */
444   vmxnet3_reg_write (vd, 1, VMXNET3_REG_VRRS,
445                      1 << (clib_min (3, vd->version) - 1));
446
447   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_UVRS);
448   if (ret & 1)
449     vmxnet3_reg_write (vd, 1, VMXNET3_REG_UVRS, 1);
450   else
451     {
452       error = clib_error_return (0, "unsupported upt version %u", ret);
453       return error;
454     }
455
456   /* LRO is only supported for version >= 3 */
457   if ((vmxm->lro_configured) && (vd->version >= 3))
458     {
459       vd->lro_enable = 1;
460       vnm->interface_main.gso_interface_count++;
461     }
462
463   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK);
464   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_CMD);
465   if (ret & 1)
466     {
467       vd->flags |= VMXNET3_DEVICE_F_LINK_UP;
468       vd->link_speed = ret >> 16;
469     }
470   else
471     vd->flags &= ~VMXNET3_DEVICE_F_LINK_UP;
472
473   /* Get the mac address */
474   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_MACL);
475   clib_memcpy (vd->mac_addr, &ret, 4);
476   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_MACH);
477   clib_memcpy (vd->mac_addr + 4, &ret, 2);
478
479   size = sizeof (vmxnet3_rx_queue) * vd->num_rx_queues +
480     sizeof (vmxnet3_tx_queue) * vd->num_tx_queues;
481
482   vd->queues =
483     vlib_physmem_alloc_aligned_on_numa (vm, size, 512, vd->numa_node);
484   if (vd->queues == 0)
485     return vlib_physmem_last_error (vm);
486
487   clib_memset (vd->queues, 0, size);
488
489   if (vd->num_rx_queues > 1)
490     {
491       error = vmxnet3_rss_init (vm, vd);
492       if (error)
493         return error;
494     }
495
496   for (i = 0; i < vd->num_rx_queues; i++)
497     {
498       error = vmxnet3_rxq_init (vm, vd, i, args->rxq_size);
499       if (error)
500         return error;
501     }
502
503   for (i = 0; i < tm->n_vlib_mains; i++)
504     {
505       error = vmxnet3_txq_init (vm, vd, i, args->txq_size);
506       if (error)
507         return error;
508     }
509
510   error = vmxnet3_provision_driver_shared (vm, vd);
511   if (error)
512     return error;
513
514   vmxnet3_write_mac (vd);
515
516   /* Activate device */
517   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_ACTIVATE_DEV);
518   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_CMD);
519   if (ret != 0)
520     {
521       error =
522         clib_error_return (0, "error on activating device rc (%u)", ret);
523       return error;
524     }
525
526   return error;
527 }
528
529 static void
530 vmxnet3_rxq_irq_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h, u16 line)
531 {
532   vnet_main_t *vnm = vnet_get_main ();
533   vmxnet3_main_t *vmxm = &vmxnet3_main;
534   uword pd = vlib_pci_get_private_data (vm, h);
535   vmxnet3_device_t *vd = pool_elt_at_index (vmxm->devices, pd);
536   u16 qid = line;
537
538   if (vec_len (vd->rxqs) > qid && vd->rxqs[qid].int_mode != 0)
539     vnet_device_input_set_interrupt_pending (vnm, vd->hw_if_index, qid);
540 }
541
542 static void
543 vmxnet3_event_irq_handler (vlib_main_t * vm, vlib_pci_dev_handle_t h,
544                            u16 line)
545 {
546   vnet_main_t *vnm = vnet_get_main ();
547   vmxnet3_main_t *vmxm = &vmxnet3_main;
548   uword pd = vlib_pci_get_private_data (vm, h);
549   vmxnet3_device_t *vd = pool_elt_at_index (vmxm->devices, pd);
550   u32 ret;
551
552   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_GET_LINK);
553   ret = vmxnet3_reg_read (vd, 1, VMXNET3_REG_CMD);
554   if (ret & 1)
555     {
556       vd->flags |= VMXNET3_DEVICE_F_LINK_UP;
557       vd->link_speed = ret >> 16;
558       vnet_hw_interface_set_link_speed (vnm, vd->hw_if_index,
559                                         vd->link_speed * 1000);
560       vnet_hw_interface_set_flags (vnm, vd->hw_if_index,
561                                    VNET_HW_INTERFACE_FLAG_LINK_UP);
562     }
563   else
564     {
565       vd->flags &= ~VMXNET3_DEVICE_F_LINK_UP;
566       vnet_hw_interface_set_flags (vnm, vd->hw_if_index, 0);
567     }
568 }
569
570 static u8
571 vmxnet3_queue_size_valid (u16 qsz)
572 {
573   if (qsz < 64 || qsz > 4096)
574     return 0;
575   if ((qsz % 64) != 0)
576     return 0;
577   return 1;
578 }
579
580 static u8
581 vmxnet3_tx_queue_num_valid (u16 num)
582 {
583   vlib_thread_main_t *tm = vlib_get_thread_main ();
584
585   if ((num > VMXNET3_TXQ_MAX) || (num > tm->n_vlib_mains))
586     return 0;
587   return 1;
588 }
589
590 static u8
591 vmxnet3_rx_queue_num_valid (u16 num)
592 {
593   if (num > VMXNET3_RXQ_MAX)
594     return 0;
595   return 1;
596 }
597
598 void
599 vmxnet3_create_if (vlib_main_t * vm, vmxnet3_create_if_args_t * args)
600 {
601   vnet_main_t *vnm = vnet_get_main ();
602   vmxnet3_main_t *vmxm = &vmxnet3_main;
603   vmxnet3_device_t *vd;
604   vlib_pci_dev_handle_t h;
605   clib_error_t *error = 0;
606   u16 qid;
607   u32 num_intr;
608
609   if (args->txq_num == 0)
610     args->txq_num = 1;
611   if (args->rxq_num == 0)
612     args->rxq_num = 1;
613   if (!vmxnet3_rx_queue_num_valid (args->rxq_num))
614     {
615       args->rv = VNET_API_ERROR_INVALID_VALUE;
616       args->error =
617         clib_error_return (error, "number of rx queues must be <= %u",
618                            VMXNET3_RXQ_MAX);
619       vlib_log (VLIB_LOG_LEVEL_ERR, vmxm->log_default, "%U: %s",
620                 format_vlib_pci_addr, &args->addr,
621                 "number of rx queues must be <= %u", VMXNET3_RXQ_MAX);
622       return;
623     }
624
625   if (!vmxnet3_tx_queue_num_valid (args->txq_num))
626     {
627       args->rv = VNET_API_ERROR_INVALID_VALUE;
628       args->error =
629         clib_error_return (error,
630                            "number of tx queues must be <= %u and <= number of "
631                            "CPU's assigned to VPP", VMXNET3_TXQ_MAX);
632       vlib_log (VLIB_LOG_LEVEL_ERR, vmxm->log_default, "%U: %s",
633                 format_vlib_pci_addr, &args->addr,
634                 "number of tx queues must be <= %u and <= number of "
635                 "CPU's assigned to VPP", VMXNET3_TXQ_MAX);
636       return;
637     }
638   if (args->rxq_size == 0)
639     args->rxq_size = VMXNET3_NUM_RX_DESC;
640   if (args->txq_size == 0)
641     args->txq_size = VMXNET3_NUM_TX_DESC;
642
643   if (!vmxnet3_queue_size_valid (args->rxq_size) ||
644       !vmxnet3_queue_size_valid (args->txq_size))
645     {
646       args->rv = VNET_API_ERROR_INVALID_VALUE;
647       args->error =
648         clib_error_return (error,
649                            "queue size must be <= 4096, >= 64, "
650                            "and multiples of 64");
651       vlib_log (VLIB_LOG_LEVEL_ERR, vmxm->log_default, "%U: %s",
652                 format_vlib_pci_addr, &args->addr,
653                 "queue size must be <= 4096, >= 64, and multiples of 64");
654       return;
655     }
656
657   /* *INDENT-OFF* */
658   pool_foreach (vd, vmxm->devices, ({
659     if (vd->pci_addr.as_u32 == args->addr.as_u32)
660       {
661         args->rv = VNET_API_ERROR_ADDRESS_IN_USE;
662         args->error =
663           clib_error_return (error, "%U: %s", format_vlib_pci_addr,
664                              &args->addr, "pci address in use");
665         vlib_log (VLIB_LOG_LEVEL_ERR, vmxm->log_default, "%U: %s",
666                   format_vlib_pci_addr, &args->addr, "pci address in use");
667         return;
668       }
669   }));
670   /* *INDENT-ON* */
671
672   if (args->bind)
673     {
674       error = vlib_pci_bind_to_uio (vm, &args->addr, (char *) "auto");
675       if (error)
676         {
677           args->rv = VNET_API_ERROR_INVALID_INTERFACE;
678           args->error =
679             clib_error_return (error, "%U: %s", format_vlib_pci_addr,
680                                &args->addr,
681                                "error encountered on binding pci device");
682           vlib_log (VLIB_LOG_LEVEL_ERR, vmxm->log_default, "%U: %s",
683                     format_vlib_pci_addr, &args->addr,
684                     "error encountered on binding pci devicee");
685           return;
686         }
687     }
688
689   if ((error =
690        vlib_pci_device_open (vm, &args->addr, vmxnet3_pci_device_ids, &h)))
691     {
692       args->rv = VNET_API_ERROR_INVALID_INTERFACE;
693       args->error =
694         clib_error_return (error, "%U: %s", format_vlib_pci_addr,
695                            &args->addr,
696                            "error encountered on pci device open");
697       vlib_log (VLIB_LOG_LEVEL_ERR, vmxm->log_default, "%U: %s",
698                 format_vlib_pci_addr, &args->addr,
699                 "error encountered on pci device open");
700       return;
701     }
702
703   /*
704    * Do not use vmxnet3_log_error prior to this line since the macro
705    * references vd->pci_dev_handle
706    */
707   pool_get (vmxm->devices, vd);
708   vd->num_tx_queues = args->txq_num;
709   vd->num_rx_queues = args->rxq_num;
710   vd->dev_instance = vd - vmxm->devices;
711   vd->per_interface_next_index = ~0;
712   vd->pci_addr = args->addr;
713
714   if (args->enable_elog)
715     vd->flags |= VMXNET3_DEVICE_F_ELOG;
716
717   vd->pci_dev_handle = h;
718   vd->numa_node = vlib_pci_get_numa_node (vm, h);
719   vd->num_intrs = vd->num_rx_queues + 1;        // +1 for the event interrupt
720
721   vlib_pci_set_private_data (vm, h, vd->dev_instance);
722
723   if ((error = vlib_pci_bus_master_enable (vm, h)))
724     {
725       vmxnet3_log_error (vd, "error encountered on pci bus master enable");
726       goto error;
727     }
728
729   if ((error = vlib_pci_map_region (vm, h, 0, (void **) &vd->bar[0])))
730     {
731       vmxnet3_log_error (vd, "error encountered on pci map region for bar 0");
732       goto error;
733     }
734
735   if ((error = vlib_pci_map_region (vm, h, 1, (void **) &vd->bar[1])))
736     {
737       vmxnet3_log_error (vd, "error encountered on pci map region for bar 1");
738       goto error;
739     }
740
741   num_intr = vlib_pci_get_num_msix_interrupts (vm, h);
742   if (num_intr < vd->num_rx_queues + 1)
743     {
744       vmxnet3_log_error (vd,
745                          "No sufficient interrupt lines (%u) for rx queues",
746                          num_intr);
747       goto error;
748     }
749   if ((error = vlib_pci_register_msix_handler (vm, h, 0, vd->num_rx_queues,
750                                                &vmxnet3_rxq_irq_handler)))
751     {
752       vmxnet3_log_error (vd,
753                          "error encountered on pci register msix handler 0");
754       goto error;
755     }
756
757   if ((error = vlib_pci_register_msix_handler (vm, h, vd->num_rx_queues, 1,
758                                                &vmxnet3_event_irq_handler)))
759     {
760       vmxnet3_log_error (vd,
761                          "error encountered on pci register msix handler 1");
762       goto error;
763     }
764
765   if ((error = vlib_pci_enable_msix_irq (vm, h, 0, vd->num_rx_queues + 1)))
766     {
767       vmxnet3_log_error (vd, "error encountered on pci enable msix irq");
768       goto error;
769     }
770
771   if ((error = vlib_pci_intr_enable (vm, h)))
772     {
773       vmxnet3_log_error (vd, "error encountered on pci interrupt enable");
774       goto error;
775     }
776
777   if ((error = vmxnet3_device_init (vm, vd, args)))
778     {
779       vmxnet3_log_error (vd, "error encountered on device init");
780       goto error;
781     }
782
783   /* create interface */
784   error = ethernet_register_interface (vnm, vmxnet3_device_class.index,
785                                        vd->dev_instance, vd->mac_addr,
786                                        &vd->hw_if_index, vmxnet3_flag_change);
787
788   if (error)
789     {
790       vmxnet3_log_error (vd,
791                          "error encountered on ethernet register interface");
792       goto error;
793     }
794
795   vnet_sw_interface_t *sw = vnet_get_hw_sw_interface (vnm, vd->hw_if_index);
796   vd->sw_if_index = sw->sw_if_index;
797   args->sw_if_index = sw->sw_if_index;
798
799   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, vd->hw_if_index);
800   hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_INT_MODE;
801   if (vd->lro_enable)
802     hw->flags |= VNET_HW_INTERFACE_FLAG_SUPPORTS_GSO;
803
804   vnet_hw_interface_set_input_node (vnm, vd->hw_if_index,
805                                     vmxnet3_input_node.index);
806   /* Disable interrupts */
807   vmxnet3_disable_interrupt (vd);
808   vec_foreach_index (qid, vd->rxqs)
809   {
810     vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, qid);
811     u32 thread_index;
812     u32 numa_node;
813
814     vnet_hw_interface_assign_rx_thread (vnm, vd->hw_if_index, qid, ~0);
815     thread_index = vnet_get_device_input_thread_index (vnm, vd->hw_if_index,
816                                                        qid);
817     numa_node = vlib_mains[thread_index]->numa_node;
818     rxq->buffer_pool_index =
819       vlib_buffer_pool_get_default_for_numa (vm, numa_node);
820     vmxnet3_rxq_refill_ring0 (vm, vd, rxq);
821     vmxnet3_rxq_refill_ring1 (vm, vd, rxq);
822   }
823   vd->flags |= VMXNET3_DEVICE_F_INITIALIZED;
824   vmxnet3_enable_interrupt (vd);
825
826   vnet_hw_interface_set_link_speed (vnm, vd->hw_if_index,
827                                     vd->link_speed * 1000);
828   if (vd->flags & VMXNET3_DEVICE_F_LINK_UP)
829     vnet_hw_interface_set_flags (vnm, vd->hw_if_index,
830                                  VNET_HW_INTERFACE_FLAG_LINK_UP);
831   else
832     vnet_hw_interface_set_flags (vnm, vd->hw_if_index, 0);
833   return;
834
835 error:
836   vmxnet3_delete_if (vm, vd);
837   args->rv = VNET_API_ERROR_INVALID_INTERFACE;
838   args->error = error;
839 }
840
841 void
842 vmxnet3_delete_if (vlib_main_t * vm, vmxnet3_device_t * vd)
843 {
844   vnet_main_t *vnm = vnet_get_main ();
845   vmxnet3_main_t *vmxm = &vmxnet3_main;
846   u32 i, bi;
847   u16 desc_idx, qid;
848
849   /* Quiesce the device */
850   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_QUIESCE_DEV);
851
852   /* Reset the device */
853   vmxnet3_reg_write (vd, 1, VMXNET3_REG_CMD, VMXNET3_CMD_RESET_DEV);
854
855   if (vd->hw_if_index)
856     {
857       vnet_hw_interface_set_flags (vnm, vd->hw_if_index, 0);
858       vec_foreach_index (qid, vd->rxqs)
859         vnet_hw_interface_unassign_rx_thread (vnm, vd->hw_if_index, qid);
860       ethernet_delete_interface (vnm, vd->hw_if_index);
861     }
862
863   vlib_pci_device_close (vm, vd->pci_dev_handle);
864
865   /* *INDENT-OFF* */
866   vec_foreach_index (i, vd->rxqs)
867     {
868       vmxnet3_rxq_t *rxq = vec_elt_at_index (vd->rxqs, i);
869       u16 mask = rxq->size - 1;
870       u16 rid;
871
872       for (rid = 0; rid < VMXNET3_RX_RING_SIZE; rid++)
873         {
874           vmxnet3_rx_ring *ring;
875
876           ring = &rxq->rx_ring[rid];
877           desc_idx = (ring->consume + 1) & mask;
878           vlib_buffer_free_from_ring (vm, ring->bufs, desc_idx, rxq->size,
879                                       ring->fill);
880           vec_free (ring->bufs);
881           vlib_physmem_free (vm, rxq->rx_desc[rid]);
882         }
883       vlib_physmem_free (vm, rxq->rx_comp);
884     }
885   /* *INDENT-ON* */
886   vec_free (vd->rxqs);
887   vec_free (vd->rx_stats);
888
889   /* *INDENT-OFF* */
890   vec_foreach_index (i, vd->txqs)
891     {
892       vmxnet3_txq_t *txq = vec_elt_at_index (vd->txqs, i);
893       u16 mask = txq->size - 1;
894       u16 end_idx;
895
896       desc_idx = txq->tx_ring.consume;
897       end_idx = txq->tx_ring.produce;
898       while (desc_idx != end_idx)
899         {
900           bi = txq->tx_ring.bufs[desc_idx];
901           vlib_buffer_free_no_next (vm, &bi, 1);
902           desc_idx++;
903           desc_idx &= mask;
904         }
905       clib_spinlock_free (&txq->lock);
906       vec_free (txq->tx_ring.bufs);
907       vlib_physmem_free (vm, txq->tx_desc);
908       vlib_physmem_free (vm, txq->tx_comp);
909     }
910   /* *INDENT-ON* */
911   vec_free (vd->txqs);
912   vec_free (vd->tx_stats);
913
914   vlib_physmem_free (vm, vd->driver_shared);
915   vlib_physmem_free (vm, vd->queues);
916   vlib_physmem_free (vm, vd->rss);
917
918   clib_error_free (vd->error);
919   clib_memset (vd, 0, sizeof (*vd));
920   pool_put (vmxm->devices, vd);
921
922   if (vd->lro_enable)
923     vnm->interface_main.gso_interface_count--;
924 }
925
926 /*
927  * fd.io coding-style-patch-verification: ON
928  *
929  * Local Variables:
930  * eval: (c-set-style "gnu")
931  * End:
932  */