vlib: PCI rework to support VFIO
[vpp.git] / src / plugins / ixge / ixge.c
1 /*
2  * Copyright (c) 2016 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 /*
17  *   WARNING!
18  *   This driver is not intended for production use and it is unsupported.
19  *   It is provided for educational use only.
20  *   Please use supported DPDK driver instead.
21  */
22
23 #if __x86_64__ || __i386__
24 #include <vppinfra/vector.h>
25
26 #ifndef CLIB_HAVE_VEC128
27 #warning HACK: ixge driver wont really work, missing u32x4
28 typedef unsigned long long u32x4;
29 #endif
30
31 #include <vlib/vlib.h>
32 #include <vlib/unix/unix.h>
33 #include <vlib/pci/pci.h>
34 #include <vnet/vnet.h>
35 #include <ixge/ixge.h>
36 #include <vnet/ethernet/ethernet.h>
37 #include <vnet/plugin/plugin.h>
38 #include <vpp/app/version.h>
39
40 #define IXGE_ALWAYS_POLL 0
41
42 #define EVENT_SET_FLAGS 0
43 #define IXGE_HWBP_RACE_ELOG 0
44
45 #define PCI_VENDOR_ID_INTEL 0x8086
46
47 /* 10 GIG E (XGE) PHY IEEE 802.3 clause 45 definitions. */
48 #define XGE_PHY_DEV_TYPE_PMA_PMD 1
49 #define XGE_PHY_DEV_TYPE_PHY_XS 4
50 #define XGE_PHY_ID1 0x2
51 #define XGE_PHY_ID2 0x3
52 #define XGE_PHY_CONTROL 0x0
53 #define XGE_PHY_CONTROL_RESET (1 << 15)
54
55 ixge_main_t ixge_main;
56 static vlib_node_registration_t ixge_input_node;
57 static vlib_node_registration_t ixge_process_node;
58
59 static void
60 ixge_semaphore_get (ixge_device_t * xd)
61 {
62   ixge_main_t *xm = &ixge_main;
63   vlib_main_t *vm = xm->vlib_main;
64   ixge_regs_t *r = xd->regs;
65   u32 i;
66
67   i = 0;
68   while (!(r->software_semaphore & (1 << 0)))
69     {
70       if (i > 0)
71         vlib_process_suspend (vm, 100e-6);
72       i++;
73     }
74   do
75     {
76       r->software_semaphore |= 1 << 1;
77     }
78   while (!(r->software_semaphore & (1 << 1)));
79 }
80
81 static void
82 ixge_semaphore_release (ixge_device_t * xd)
83 {
84   ixge_regs_t *r = xd->regs;
85   r->software_semaphore &= ~3;
86 }
87
88 static void
89 ixge_software_firmware_sync (ixge_device_t * xd, u32 sw_mask)
90 {
91   ixge_main_t *xm = &ixge_main;
92   vlib_main_t *vm = xm->vlib_main;
93   ixge_regs_t *r = xd->regs;
94   u32 fw_mask = sw_mask << 5;
95   u32 m, done = 0;
96
97   while (!done)
98     {
99       ixge_semaphore_get (xd);
100       m = r->software_firmware_sync;
101       done = (m & fw_mask) == 0;
102       if (done)
103         r->software_firmware_sync = m | sw_mask;
104       ixge_semaphore_release (xd);
105       if (!done)
106         vlib_process_suspend (vm, 10e-3);
107     }
108 }
109
110 static void
111 ixge_software_firmware_sync_release (ixge_device_t * xd, u32 sw_mask)
112 {
113   ixge_regs_t *r = xd->regs;
114   ixge_semaphore_get (xd);
115   r->software_firmware_sync &= ~sw_mask;
116   ixge_semaphore_release (xd);
117 }
118
119 u32
120 ixge_read_write_phy_reg (ixge_device_t * xd, u32 dev_type, u32 reg_index,
121                          u32 v, u32 is_read)
122 {
123   ixge_regs_t *r = xd->regs;
124   const u32 busy_bit = 1 << 30;
125   u32 x;
126
127   ASSERT (xd->phy_index < 2);
128   ixge_software_firmware_sync (xd, 1 << (1 + xd->phy_index));
129
130   ASSERT (reg_index < (1 << 16));
131   ASSERT (dev_type < (1 << 5));
132   if (!is_read)
133     r->xge_mac.phy_data = v;
134
135   /* Address cycle. */
136   x =
137     reg_index | (dev_type << 16) | (xd->
138                                     phys[xd->phy_index].mdio_address << 21);
139   r->xge_mac.phy_command = x | busy_bit;
140   /* Busy wait timed to take 28e-6 secs.  No suspend. */
141   while (r->xge_mac.phy_command & busy_bit)
142     ;
143
144   r->xge_mac.phy_command = x | ((is_read ? 2 : 1) << 26) | busy_bit;
145   while (r->xge_mac.phy_command & busy_bit)
146     ;
147
148   if (is_read)
149     v = r->xge_mac.phy_data >> 16;
150
151   ixge_software_firmware_sync_release (xd, 1 << (1 + xd->phy_index));
152
153   return v;
154 }
155
156 static u32
157 ixge_read_phy_reg (ixge_device_t * xd, u32 dev_type, u32 reg_index)
158 {
159   return ixge_read_write_phy_reg (xd, dev_type, reg_index, 0,   /* is_read */
160                                   1);
161 }
162
163 static void
164 ixge_write_phy_reg (ixge_device_t * xd, u32 dev_type, u32 reg_index, u32 v)
165 {
166   (void) ixge_read_write_phy_reg (xd, dev_type, reg_index, v,   /* is_read */
167                                   0);
168 }
169
170 static void
171 ixge_i2c_put_bits (i2c_bus_t * b, int scl, int sda)
172 {
173   ixge_main_t *xm = &ixge_main;
174   ixge_device_t *xd = vec_elt_at_index (xm->devices, b->private_data);
175   u32 v;
176
177   v = 0;
178   v |= (sda != 0) << 3;
179   v |= (scl != 0) << 1;
180   xd->regs->i2c_control = v;
181 }
182
183 static void
184 ixge_i2c_get_bits (i2c_bus_t * b, int *scl, int *sda)
185 {
186   ixge_main_t *xm = &ixge_main;
187   ixge_device_t *xd = vec_elt_at_index (xm->devices, b->private_data);
188   u32 v;
189
190   v = xd->regs->i2c_control;
191   *sda = (v & (1 << 2)) != 0;
192   *scl = (v & (1 << 0)) != 0;
193 }
194
195 static u16
196 ixge_read_eeprom (ixge_device_t * xd, u32 address)
197 {
198   ixge_regs_t *r = xd->regs;
199   u32 v;
200   r->eeprom_read = (( /* start bit */ (1 << 0)) | (address << 2));
201   /* Wait for done bit. */
202   while (!((v = r->eeprom_read) & (1 << 1)))
203     ;
204   return v >> 16;
205 }
206
207 static void
208 ixge_sfp_enable_disable_laser (ixge_device_t * xd, uword enable)
209 {
210   u32 tx_disable_bit = 1 << 3;
211   if (enable)
212     xd->regs->sdp_control &= ~tx_disable_bit;
213   else
214     xd->regs->sdp_control |= tx_disable_bit;
215 }
216
217 static void
218 ixge_sfp_enable_disable_10g (ixge_device_t * xd, uword enable)
219 {
220   u32 is_10g_bit = 1 << 5;
221   if (enable)
222     xd->regs->sdp_control |= is_10g_bit;
223   else
224     xd->regs->sdp_control &= ~is_10g_bit;
225 }
226
227 static clib_error_t *
228 ixge_sfp_phy_init_from_eeprom (ixge_device_t * xd, u16 sfp_type)
229 {
230   u16 a, id, reg_values_addr = 0;
231
232   a = ixge_read_eeprom (xd, 0x2b);
233   if (a == 0 || a == 0xffff)
234     return clib_error_create ("no init sequence in eeprom");
235
236   while (1)
237     {
238       id = ixge_read_eeprom (xd, ++a);
239       if (id == 0xffff)
240         break;
241       reg_values_addr = ixge_read_eeprom (xd, ++a);
242       if (id == sfp_type)
243         break;
244     }
245   if (id != sfp_type)
246     return clib_error_create ("failed to find id 0x%x", sfp_type);
247
248   ixge_software_firmware_sync (xd, 1 << 3);
249   while (1)
250     {
251       u16 v = ixge_read_eeprom (xd, ++reg_values_addr);
252       if (v == 0xffff)
253         break;
254       xd->regs->core_analog_config = v;
255     }
256   ixge_software_firmware_sync_release (xd, 1 << 3);
257
258   /* Make sure laser is off.  We'll turn on the laser when
259      the interface is brought up. */
260   ixge_sfp_enable_disable_laser (xd, /* enable */ 0);
261   ixge_sfp_enable_disable_10g (xd, /* is_10g */ 1);
262
263   return 0;
264 }
265
266 static void
267 ixge_sfp_device_up_down (ixge_device_t * xd, uword is_up)
268 {
269   u32 v;
270
271   if (is_up)
272     {
273       /* pma/pmd 10g serial SFI. */
274       xd->regs->xge_mac.auto_negotiation_control2 &= ~(3 << 16);
275       xd->regs->xge_mac.auto_negotiation_control2 |= 2 << 16;
276
277       v = xd->regs->xge_mac.auto_negotiation_control;
278       v &= ~(7 << 13);
279       v |= (0 << 13);
280       /* Restart autoneg. */
281       v |= (1 << 12);
282       xd->regs->xge_mac.auto_negotiation_control = v;
283
284       while (!(xd->regs->xge_mac.link_partner_ability[0] & 0xf0000))
285         ;
286
287       v = xd->regs->xge_mac.auto_negotiation_control;
288
289       /* link mode 10g sfi serdes */
290       v &= ~(7 << 13);
291       v |= (3 << 13);
292
293       /* Restart autoneg. */
294       v |= (1 << 12);
295       xd->regs->xge_mac.auto_negotiation_control = v;
296
297       xd->regs->xge_mac.link_status;
298     }
299
300   ixge_sfp_enable_disable_laser (xd, /* enable */ is_up);
301
302   /* Give time for link partner to notice that we're up. */
303   if (is_up && vlib_in_process_context (vlib_get_main ()))
304     {
305       vlib_process_suspend (vlib_get_main (), 300e-3);
306     }
307 }
308
309 always_inline ixge_dma_regs_t *
310 get_dma_regs (ixge_device_t * xd, vlib_rx_or_tx_t rt, u32 qi)
311 {
312   ixge_regs_t *r = xd->regs;
313   ASSERT (qi < 128);
314   if (rt == VLIB_RX)
315     return qi < 64 ? &r->rx_dma0[qi] : &r->rx_dma1[qi - 64];
316   else
317     return &r->tx_dma[qi];
318 }
319
320 static clib_error_t *
321 ixge_interface_admin_up_down (vnet_main_t * vnm, u32 hw_if_index, u32 flags)
322 {
323   vnet_hw_interface_t *hif = vnet_get_hw_interface (vnm, hw_if_index);
324   uword is_up = (flags & VNET_SW_INTERFACE_FLAG_ADMIN_UP) != 0;
325   ixge_main_t *xm = &ixge_main;
326   ixge_device_t *xd = vec_elt_at_index (xm->devices, hif->dev_instance);
327   ixge_dma_regs_t *dr = get_dma_regs (xd, VLIB_RX, 0);
328
329   if (is_up)
330     {
331       xd->regs->rx_enable |= 1;
332       xd->regs->tx_dma_control |= 1;
333       dr->control |= 1 << 25;
334       while (!(dr->control & (1 << 25)))
335         ;
336     }
337   else
338     {
339       xd->regs->rx_enable &= ~1;
340       xd->regs->tx_dma_control &= ~1;
341     }
342
343   ixge_sfp_device_up_down (xd, is_up);
344
345   return /* no error */ 0;
346 }
347
348 static void
349 ixge_sfp_phy_init (ixge_device_t * xd)
350 {
351   ixge_phy_t *phy = xd->phys + xd->phy_index;
352   i2c_bus_t *ib = &xd->i2c_bus;
353
354   ib->private_data = xd->device_index;
355   ib->put_bits = ixge_i2c_put_bits;
356   ib->get_bits = ixge_i2c_get_bits;
357   vlib_i2c_init (ib);
358
359   vlib_i2c_read_eeprom (ib, 0x50, 0, 128, (u8 *) & xd->sfp_eeprom);
360
361   if (vlib_i2c_bus_timed_out (ib) || !sfp_eeprom_is_valid (&xd->sfp_eeprom))
362     xd->sfp_eeprom.id = SFP_ID_unknown;
363   else
364     {
365       /* FIXME 5 => SR/LR eeprom ID. */
366       clib_error_t *e =
367         ixge_sfp_phy_init_from_eeprom (xd, 5 + xd->pci_function);
368       if (e)
369         clib_error_report (e);
370     }
371
372   phy->mdio_address = ~0;
373 }
374
375 static void
376 ixge_phy_init (ixge_device_t * xd)
377 {
378   ixge_main_t *xm = &ixge_main;
379   vlib_main_t *vm = xm->vlib_main;
380   ixge_phy_t *phy = xd->phys + xd->phy_index;
381
382   switch (xd->device_id)
383     {
384     case IXGE_82599_sfp:
385     case IXGE_82599_sfp_em:
386     case IXGE_82599_sfp_fcoe:
387       /* others? */
388       return ixge_sfp_phy_init (xd);
389
390     default:
391       break;
392     }
393
394   /* Probe address of phy. */
395   {
396     u32 i, v;
397
398     phy->mdio_address = ~0;
399     for (i = 0; i < 32; i++)
400       {
401         phy->mdio_address = i;
402         v = ixge_read_phy_reg (xd, XGE_PHY_DEV_TYPE_PMA_PMD, XGE_PHY_ID1);
403         if (v != 0xffff && v != 0)
404           break;
405       }
406
407     /* No PHY found? */
408     if (i >= 32)
409       return;
410   }
411
412   phy->id =
413     ((ixge_read_phy_reg (xd, XGE_PHY_DEV_TYPE_PMA_PMD, XGE_PHY_ID1) << 16) |
414      ixge_read_phy_reg (xd, XGE_PHY_DEV_TYPE_PMA_PMD, XGE_PHY_ID2));
415
416   {
417     ELOG_TYPE_DECLARE (e) =
418     {
419     .function = (char *) __FUNCTION__,.format =
420         "ixge %d, phy id 0x%d mdio address %d",.format_args = "i4i4i4",};
421     struct
422     {
423       u32 instance, id, address;
424     } *ed;
425     ed = ELOG_DATA (&vm->elog_main, e);
426     ed->instance = xd->device_index;
427     ed->id = phy->id;
428     ed->address = phy->mdio_address;
429   }
430
431   /* Reset phy. */
432   ixge_write_phy_reg (xd, XGE_PHY_DEV_TYPE_PHY_XS, XGE_PHY_CONTROL,
433                       XGE_PHY_CONTROL_RESET);
434
435   /* Wait for self-clearning reset bit to clear. */
436   do
437     {
438       vlib_process_suspend (vm, 1e-3);
439     }
440   while (ixge_read_phy_reg (xd, XGE_PHY_DEV_TYPE_PHY_XS, XGE_PHY_CONTROL) &
441          XGE_PHY_CONTROL_RESET);
442 }
443
444 static u8 *
445 format_ixge_rx_from_hw_descriptor (u8 * s, va_list * va)
446 {
447   ixge_rx_from_hw_descriptor_t *d =
448     va_arg (*va, ixge_rx_from_hw_descriptor_t *);
449   u32 s0 = d->status[0], s2 = d->status[2];
450   u32 is_ip4, is_ip6, is_ip, is_tcp, is_udp;
451   u32 indent = format_get_indent (s);
452
453   s = format (s, "%s-owned",
454               (s2 & IXGE_RX_DESCRIPTOR_STATUS2_IS_OWNED_BY_SOFTWARE) ? "sw" :
455               "hw");
456   s =
457     format (s, ", length this descriptor %d, l3 offset %d",
458             d->n_packet_bytes_this_descriptor,
459             IXGE_RX_DESCRIPTOR_STATUS0_L3_OFFSET (s0));
460   if (s2 & IXGE_RX_DESCRIPTOR_STATUS2_IS_END_OF_PACKET)
461     s = format (s, ", end-of-packet");
462
463   s = format (s, "\n%U", format_white_space, indent);
464
465   if (s2 & IXGE_RX_DESCRIPTOR_STATUS2_ETHERNET_ERROR)
466     s = format (s, "layer2 error");
467
468   if (s0 & IXGE_RX_DESCRIPTOR_STATUS0_IS_LAYER2)
469     {
470       s = format (s, "layer 2 type %d", (s0 & 0x1f));
471       return s;
472     }
473
474   if (s2 & IXGE_RX_DESCRIPTOR_STATUS2_IS_VLAN)
475     s = format (s, "vlan header 0x%x\n%U", d->vlan_tag,
476                 format_white_space, indent);
477
478   if ((is_ip4 = (s0 & IXGE_RX_DESCRIPTOR_STATUS0_IS_IP4)))
479     {
480       s = format (s, "ip4%s",
481                   (s0 & IXGE_RX_DESCRIPTOR_STATUS0_IS_IP4_EXT) ? " options" :
482                   "");
483       if (s2 & IXGE_RX_DESCRIPTOR_STATUS2_IS_IP4_CHECKSUMMED)
484         s = format (s, " checksum %s",
485                     (s2 & IXGE_RX_DESCRIPTOR_STATUS2_IP4_CHECKSUM_ERROR) ?
486                     "bad" : "ok");
487     }
488   if ((is_ip6 = (s0 & IXGE_RX_DESCRIPTOR_STATUS0_IS_IP6)))
489     s = format (s, "ip6%s",
490                 (s0 & IXGE_RX_DESCRIPTOR_STATUS0_IS_IP6_EXT) ? " extended" :
491                 "");
492   is_tcp = is_udp = 0;
493   if ((is_ip = (is_ip4 | is_ip6)))
494     {
495       is_tcp = (s0 & IXGE_RX_DESCRIPTOR_STATUS0_IS_TCP) != 0;
496       is_udp = (s0 & IXGE_RX_DESCRIPTOR_STATUS0_IS_UDP) != 0;
497       if (is_tcp)
498         s = format (s, ", tcp");
499       if (is_udp)
500         s = format (s, ", udp");
501     }
502
503   if (s2 & IXGE_RX_DESCRIPTOR_STATUS2_IS_TCP_CHECKSUMMED)
504     s = format (s, ", tcp checksum %s",
505                 (s2 & IXGE_RX_DESCRIPTOR_STATUS2_TCP_CHECKSUM_ERROR) ? "bad" :
506                 "ok");
507   if (s2 & IXGE_RX_DESCRIPTOR_STATUS2_IS_UDP_CHECKSUMMED)
508     s = format (s, ", udp checksum %s",
509                 (s2 & IXGE_RX_DESCRIPTOR_STATUS2_UDP_CHECKSUM_ERROR) ? "bad" :
510                 "ok");
511
512   return s;
513 }
514
515 static u8 *
516 format_ixge_tx_descriptor (u8 * s, va_list * va)
517 {
518   ixge_tx_descriptor_t *d = va_arg (*va, ixge_tx_descriptor_t *);
519   u32 s0 = d->status0, s1 = d->status1;
520   u32 indent = format_get_indent (s);
521   u32 v;
522
523   s = format (s, "buffer 0x%Lx, %d packet bytes, %d bytes this buffer",
524               d->buffer_address, s1 >> 14, d->n_bytes_this_buffer);
525
526   s = format (s, "\n%U", format_white_space, indent);
527
528   if ((v = (s0 >> 0) & 3))
529     s = format (s, "reserved 0x%x, ", v);
530
531   if ((v = (s0 >> 2) & 3))
532     s = format (s, "mac 0x%x, ", v);
533
534   if ((v = (s0 >> 4) & 0xf) != 3)
535     s = format (s, "type 0x%x, ", v);
536
537   s = format (s, "%s%s%s%s%s%s%s%s",
538               (s0 & (1 << 8)) ? "eop, " : "",
539               (s0 & (1 << 9)) ? "insert-fcs, " : "",
540               (s0 & (1 << 10)) ? "reserved26, " : "",
541               (s0 & (1 << 11)) ? "report-status, " : "",
542               (s0 & (1 << 12)) ? "reserved28, " : "",
543               (s0 & (1 << 13)) ? "is-advanced, " : "",
544               (s0 & (1 << 14)) ? "vlan-enable, " : "",
545               (s0 & (1 << 15)) ? "tx-segmentation, " : "");
546
547   if ((v = s1 & 0xf) != 0)
548     s = format (s, "status 0x%x, ", v);
549
550   if ((v = (s1 >> 4) & 0xf))
551     s = format (s, "context 0x%x, ", v);
552
553   if ((v = (s1 >> 8) & 0x3f))
554     s = format (s, "options 0x%x, ", v);
555
556   return s;
557 }
558
559 typedef struct
560 {
561   ixge_descriptor_t before, after;
562
563   u32 buffer_index;
564
565   u16 device_index;
566
567   u8 queue_index;
568
569   u8 is_start_of_packet;
570
571   /* Copy of VLIB buffer; packet data stored in pre_data. */
572   vlib_buffer_t buffer;
573 } ixge_rx_dma_trace_t;
574
575 static u8 *
576 format_ixge_rx_dma_trace (u8 * s, va_list * va)
577 {
578   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
579   vlib_node_t *node = va_arg (*va, vlib_node_t *);
580   vnet_main_t *vnm = vnet_get_main ();
581   ixge_rx_dma_trace_t *t = va_arg (*va, ixge_rx_dma_trace_t *);
582   ixge_main_t *xm = &ixge_main;
583   ixge_device_t *xd = vec_elt_at_index (xm->devices, t->device_index);
584   format_function_t *f;
585   u32 indent = format_get_indent (s);
586
587   {
588     vnet_sw_interface_t *sw =
589       vnet_get_sw_interface (vnm, xd->vlib_sw_if_index);
590     s =
591       format (s, "%U rx queue %d", format_vnet_sw_interface_name, vnm, sw,
592               t->queue_index);
593   }
594
595   s = format (s, "\n%Ubefore: %U",
596               format_white_space, indent,
597               format_ixge_rx_from_hw_descriptor, &t->before);
598   s = format (s, "\n%Uafter : head/tail address 0x%Lx/0x%Lx",
599               format_white_space, indent,
600               t->after.rx_to_hw.head_address, t->after.rx_to_hw.tail_address);
601
602   s = format (s, "\n%Ubuffer 0x%x: %U",
603               format_white_space, indent,
604               t->buffer_index, format_vnet_buffer, &t->buffer);
605
606   s = format (s, "\n%U", format_white_space, indent);
607
608   f = node->format_buffer;
609   if (!f || !t->is_start_of_packet)
610     f = format_hex_bytes;
611   s = format (s, "%U", f, t->buffer.pre_data, sizeof (t->buffer.pre_data));
612
613   return s;
614 }
615
616 #define foreach_ixge_error                                      \
617   _ (none, "no error")                                          \
618   _ (tx_full_drops, "tx ring full drops")                       \
619   _ (ip4_checksum_error, "ip4 checksum errors")                 \
620   _ (rx_alloc_fail, "rx buf alloc from free list failed")       \
621   _ (rx_alloc_no_physmem, "rx buf alloc failed no physmem")
622
623 typedef enum
624 {
625 #define _(f,s) IXGE_ERROR_##f,
626   foreach_ixge_error
627 #undef _
628     IXGE_N_ERROR,
629 } ixge_error_t;
630
631 always_inline void
632 ixge_rx_next_and_error_from_status_x1 (ixge_device_t * xd,
633                                        u32 s00, u32 s02,
634                                        u8 * next0, u8 * error0, u32 * flags0)
635 {
636   u8 is0_ip4, is0_ip6, n0, e0;
637   u32 f0;
638
639   e0 = IXGE_ERROR_none;
640   n0 = IXGE_RX_NEXT_ETHERNET_INPUT;
641
642   is0_ip4 = s02 & IXGE_RX_DESCRIPTOR_STATUS2_IS_IP4_CHECKSUMMED;
643   n0 = is0_ip4 ? IXGE_RX_NEXT_IP4_INPUT : n0;
644
645   e0 = (is0_ip4 && (s02 & IXGE_RX_DESCRIPTOR_STATUS2_IP4_CHECKSUM_ERROR)
646         ? IXGE_ERROR_ip4_checksum_error : e0);
647
648   is0_ip6 = s00 & IXGE_RX_DESCRIPTOR_STATUS0_IS_IP6;
649   n0 = is0_ip6 ? IXGE_RX_NEXT_IP6_INPUT : n0;
650
651   n0 = (xd->per_interface_next_index != ~0) ?
652     xd->per_interface_next_index : n0;
653
654   /* Check for error. */
655   n0 = e0 != IXGE_ERROR_none ? IXGE_RX_NEXT_DROP : n0;
656
657   f0 = ((s02 & (IXGE_RX_DESCRIPTOR_STATUS2_IS_TCP_CHECKSUMMED
658                 | IXGE_RX_DESCRIPTOR_STATUS2_IS_UDP_CHECKSUMMED))
659         ? VNET_BUFFER_F_L4_CHECKSUM_COMPUTED : 0);
660
661   f0 |= ((s02 & (IXGE_RX_DESCRIPTOR_STATUS2_TCP_CHECKSUM_ERROR
662                  | IXGE_RX_DESCRIPTOR_STATUS2_UDP_CHECKSUM_ERROR))
663          ? 0 : VNET_BUFFER_F_L4_CHECKSUM_CORRECT);
664
665   *error0 = e0;
666   *next0 = n0;
667   *flags0 = f0;
668 }
669
670 always_inline void
671 ixge_rx_next_and_error_from_status_x2 (ixge_device_t * xd,
672                                        u32 s00, u32 s02,
673                                        u32 s10, u32 s12,
674                                        u8 * next0, u8 * error0, u32 * flags0,
675                                        u8 * next1, u8 * error1, u32 * flags1)
676 {
677   u8 is0_ip4, is0_ip6, n0, e0;
678   u8 is1_ip4, is1_ip6, n1, e1;
679   u32 f0, f1;
680
681   e0 = e1 = IXGE_ERROR_none;
682   n0 = n1 = IXGE_RX_NEXT_IP4_INPUT;
683
684   is0_ip4 = s02 & IXGE_RX_DESCRIPTOR_STATUS2_IS_IP4_CHECKSUMMED;
685   is1_ip4 = s12 & IXGE_RX_DESCRIPTOR_STATUS2_IS_IP4_CHECKSUMMED;
686
687   n0 = is0_ip4 ? IXGE_RX_NEXT_IP4_INPUT : n0;
688   n1 = is1_ip4 ? IXGE_RX_NEXT_IP4_INPUT : n1;
689
690   e0 = (is0_ip4 && (s02 & IXGE_RX_DESCRIPTOR_STATUS2_IP4_CHECKSUM_ERROR)
691         ? IXGE_ERROR_ip4_checksum_error : e0);
692   e1 = (is1_ip4 && (s12 & IXGE_RX_DESCRIPTOR_STATUS2_IP4_CHECKSUM_ERROR)
693         ? IXGE_ERROR_ip4_checksum_error : e1);
694
695   is0_ip6 = s00 & IXGE_RX_DESCRIPTOR_STATUS0_IS_IP6;
696   is1_ip6 = s10 & IXGE_RX_DESCRIPTOR_STATUS0_IS_IP6;
697
698   n0 = is0_ip6 ? IXGE_RX_NEXT_IP6_INPUT : n0;
699   n1 = is1_ip6 ? IXGE_RX_NEXT_IP6_INPUT : n1;
700
701   n0 = (xd->per_interface_next_index != ~0) ?
702     xd->per_interface_next_index : n0;
703   n1 = (xd->per_interface_next_index != ~0) ?
704     xd->per_interface_next_index : n1;
705
706   /* Check for error. */
707   n0 = e0 != IXGE_ERROR_none ? IXGE_RX_NEXT_DROP : n0;
708   n1 = e1 != IXGE_ERROR_none ? IXGE_RX_NEXT_DROP : n1;
709
710   *error0 = e0;
711   *error1 = e1;
712
713   *next0 = n0;
714   *next1 = n1;
715
716   f0 = ((s02 & (IXGE_RX_DESCRIPTOR_STATUS2_IS_TCP_CHECKSUMMED
717                 | IXGE_RX_DESCRIPTOR_STATUS2_IS_UDP_CHECKSUMMED))
718         ? VNET_BUFFER_F_L4_CHECKSUM_COMPUTED : 0);
719   f1 = ((s12 & (IXGE_RX_DESCRIPTOR_STATUS2_IS_TCP_CHECKSUMMED
720                 | IXGE_RX_DESCRIPTOR_STATUS2_IS_UDP_CHECKSUMMED))
721         ? VNET_BUFFER_F_L4_CHECKSUM_COMPUTED : 0);
722
723   f0 |= ((s02 & (IXGE_RX_DESCRIPTOR_STATUS2_TCP_CHECKSUM_ERROR
724                  | IXGE_RX_DESCRIPTOR_STATUS2_UDP_CHECKSUM_ERROR))
725          ? 0 : VNET_BUFFER_F_L4_CHECKSUM_CORRECT);
726   f1 |= ((s12 & (IXGE_RX_DESCRIPTOR_STATUS2_TCP_CHECKSUM_ERROR
727                  | IXGE_RX_DESCRIPTOR_STATUS2_UDP_CHECKSUM_ERROR))
728          ? 0 : VNET_BUFFER_F_L4_CHECKSUM_CORRECT);
729
730   *flags0 = f0;
731   *flags1 = f1;
732 }
733
734 static void
735 ixge_rx_trace (ixge_main_t * xm,
736                ixge_device_t * xd,
737                ixge_dma_queue_t * dq,
738                ixge_descriptor_t * before_descriptors,
739                u32 * before_buffers,
740                ixge_descriptor_t * after_descriptors, uword n_descriptors)
741 {
742   vlib_main_t *vm = xm->vlib_main;
743   vlib_node_runtime_t *node = dq->rx.node;
744   ixge_rx_from_hw_descriptor_t *bd;
745   ixge_rx_to_hw_descriptor_t *ad;
746   u32 *b, n_left, is_sop, next_index_sop;
747
748   n_left = n_descriptors;
749   b = before_buffers;
750   bd = &before_descriptors->rx_from_hw;
751   ad = &after_descriptors->rx_to_hw;
752   is_sop = dq->rx.is_start_of_packet;
753   next_index_sop = dq->rx.saved_start_of_packet_next_index;
754
755   while (n_left >= 2)
756     {
757       u32 bi0, bi1, flags0, flags1;
758       vlib_buffer_t *b0, *b1;
759       ixge_rx_dma_trace_t *t0, *t1;
760       u8 next0, error0, next1, error1;
761
762       bi0 = b[0];
763       bi1 = b[1];
764       n_left -= 2;
765
766       b0 = vlib_get_buffer (vm, bi0);
767       b1 = vlib_get_buffer (vm, bi1);
768
769       ixge_rx_next_and_error_from_status_x2 (xd,
770                                              bd[0].status[0], bd[0].status[2],
771                                              bd[1].status[0], bd[1].status[2],
772                                              &next0, &error0, &flags0,
773                                              &next1, &error1, &flags1);
774
775       next_index_sop = is_sop ? next0 : next_index_sop;
776       vlib_trace_buffer (vm, node, next_index_sop, b0, /* follow_chain */ 0);
777       t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
778       t0->is_start_of_packet = is_sop;
779       is_sop = (b0->flags & VLIB_BUFFER_NEXT_PRESENT) == 0;
780
781       next_index_sop = is_sop ? next1 : next_index_sop;
782       vlib_trace_buffer (vm, node, next_index_sop, b1, /* follow_chain */ 0);
783       t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
784       t1->is_start_of_packet = is_sop;
785       is_sop = (b1->flags & VLIB_BUFFER_NEXT_PRESENT) == 0;
786
787       t0->queue_index = dq->queue_index;
788       t1->queue_index = dq->queue_index;
789       t0->device_index = xd->device_index;
790       t1->device_index = xd->device_index;
791       t0->before.rx_from_hw = bd[0];
792       t1->before.rx_from_hw = bd[1];
793       t0->after.rx_to_hw = ad[0];
794       t1->after.rx_to_hw = ad[1];
795       t0->buffer_index = bi0;
796       t1->buffer_index = bi1;
797       memcpy (&t0->buffer, b0, sizeof (b0[0]) - sizeof (b0->pre_data));
798       memcpy (&t1->buffer, b1, sizeof (b1[0]) - sizeof (b0->pre_data));
799       memcpy (t0->buffer.pre_data, b0->data + b0->current_data,
800               sizeof (t0->buffer.pre_data));
801       memcpy (t1->buffer.pre_data, b1->data + b1->current_data,
802               sizeof (t1->buffer.pre_data));
803
804       b += 2;
805       bd += 2;
806       ad += 2;
807     }
808
809   while (n_left >= 1)
810     {
811       u32 bi0, flags0;
812       vlib_buffer_t *b0;
813       ixge_rx_dma_trace_t *t0;
814       u8 next0, error0;
815
816       bi0 = b[0];
817       n_left -= 1;
818
819       b0 = vlib_get_buffer (vm, bi0);
820
821       ixge_rx_next_and_error_from_status_x1 (xd,
822                                              bd[0].status[0], bd[0].status[2],
823                                              &next0, &error0, &flags0);
824
825       next_index_sop = is_sop ? next0 : next_index_sop;
826       vlib_trace_buffer (vm, node, next_index_sop, b0, /* follow_chain */ 0);
827       t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
828       t0->is_start_of_packet = is_sop;
829       is_sop = (b0->flags & VLIB_BUFFER_NEXT_PRESENT) == 0;
830
831       t0->queue_index = dq->queue_index;
832       t0->device_index = xd->device_index;
833       t0->before.rx_from_hw = bd[0];
834       t0->after.rx_to_hw = ad[0];
835       t0->buffer_index = bi0;
836       memcpy (&t0->buffer, b0, sizeof (b0[0]) - sizeof (b0->pre_data));
837       memcpy (t0->buffer.pre_data, b0->data + b0->current_data,
838               sizeof (t0->buffer.pre_data));
839
840       b += 1;
841       bd += 1;
842       ad += 1;
843     }
844 }
845
846 typedef struct
847 {
848   ixge_tx_descriptor_t descriptor;
849
850   u32 buffer_index;
851
852   u16 device_index;
853
854   u8 queue_index;
855
856   u8 is_start_of_packet;
857
858   /* Copy of VLIB buffer; packet data stored in pre_data. */
859   vlib_buffer_t buffer;
860 } ixge_tx_dma_trace_t;
861
862 static u8 *
863 format_ixge_tx_dma_trace (u8 * s, va_list * va)
864 {
865   CLIB_UNUSED (vlib_main_t * vm) = va_arg (*va, vlib_main_t *);
866   CLIB_UNUSED (vlib_node_t * node) = va_arg (*va, vlib_node_t *);
867   ixge_tx_dma_trace_t *t = va_arg (*va, ixge_tx_dma_trace_t *);
868   vnet_main_t *vnm = vnet_get_main ();
869   ixge_main_t *xm = &ixge_main;
870   ixge_device_t *xd = vec_elt_at_index (xm->devices, t->device_index);
871   format_function_t *f;
872   u32 indent = format_get_indent (s);
873
874   {
875     vnet_sw_interface_t *sw =
876       vnet_get_sw_interface (vnm, xd->vlib_sw_if_index);
877     s =
878       format (s, "%U tx queue %d", format_vnet_sw_interface_name, vnm, sw,
879               t->queue_index);
880   }
881
882   s = format (s, "\n%Udescriptor: %U",
883               format_white_space, indent,
884               format_ixge_tx_descriptor, &t->descriptor);
885
886   s = format (s, "\n%Ubuffer 0x%x: %U",
887               format_white_space, indent,
888               t->buffer_index, format_vnet_buffer, &t->buffer);
889
890   s = format (s, "\n%U", format_white_space, indent);
891
892   f = format_ethernet_header_with_length;
893   if (!f || !t->is_start_of_packet)
894     f = format_hex_bytes;
895   s = format (s, "%U", f, t->buffer.pre_data, sizeof (t->buffer.pre_data));
896
897   return s;
898 }
899
900 typedef struct
901 {
902   vlib_node_runtime_t *node;
903
904   u32 is_start_of_packet;
905
906   u32 n_bytes_in_packet;
907
908   ixge_tx_descriptor_t *start_of_packet_descriptor;
909 } ixge_tx_state_t;
910
911 static void
912 ixge_tx_trace (ixge_main_t * xm,
913                ixge_device_t * xd,
914                ixge_dma_queue_t * dq,
915                ixge_tx_state_t * tx_state,
916                ixge_tx_descriptor_t * descriptors,
917                u32 * buffers, uword n_descriptors)
918 {
919   vlib_main_t *vm = xm->vlib_main;
920   vlib_node_runtime_t *node = tx_state->node;
921   ixge_tx_descriptor_t *d;
922   u32 *b, n_left, is_sop;
923
924   n_left = n_descriptors;
925   b = buffers;
926   d = descriptors;
927   is_sop = tx_state->is_start_of_packet;
928
929   while (n_left >= 2)
930     {
931       u32 bi0, bi1;
932       vlib_buffer_t *b0, *b1;
933       ixge_tx_dma_trace_t *t0, *t1;
934
935       bi0 = b[0];
936       bi1 = b[1];
937       n_left -= 2;
938
939       b0 = vlib_get_buffer (vm, bi0);
940       b1 = vlib_get_buffer (vm, bi1);
941
942       t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
943       t0->is_start_of_packet = is_sop;
944       is_sop = (b0->flags & VLIB_BUFFER_NEXT_PRESENT) == 0;
945
946       t1 = vlib_add_trace (vm, node, b1, sizeof (t1[0]));
947       t1->is_start_of_packet = is_sop;
948       is_sop = (b1->flags & VLIB_BUFFER_NEXT_PRESENT) == 0;
949
950       t0->queue_index = dq->queue_index;
951       t1->queue_index = dq->queue_index;
952       t0->device_index = xd->device_index;
953       t1->device_index = xd->device_index;
954       t0->descriptor = d[0];
955       t1->descriptor = d[1];
956       t0->buffer_index = bi0;
957       t1->buffer_index = bi1;
958       memcpy (&t0->buffer, b0, sizeof (b0[0]) - sizeof (b0->pre_data));
959       memcpy (&t1->buffer, b1, sizeof (b1[0]) - sizeof (b0->pre_data));
960       memcpy (t0->buffer.pre_data, b0->data + b0->current_data,
961               sizeof (t0->buffer.pre_data));
962       memcpy (t1->buffer.pre_data, b1->data + b1->current_data,
963               sizeof (t1->buffer.pre_data));
964
965       b += 2;
966       d += 2;
967     }
968
969   while (n_left >= 1)
970     {
971       u32 bi0;
972       vlib_buffer_t *b0;
973       ixge_tx_dma_trace_t *t0;
974
975       bi0 = b[0];
976       n_left -= 1;
977
978       b0 = vlib_get_buffer (vm, bi0);
979
980       t0 = vlib_add_trace (vm, node, b0, sizeof (t0[0]));
981       t0->is_start_of_packet = is_sop;
982       is_sop = (b0->flags & VLIB_BUFFER_NEXT_PRESENT) == 0;
983
984       t0->queue_index = dq->queue_index;
985       t0->device_index = xd->device_index;
986       t0->descriptor = d[0];
987       t0->buffer_index = bi0;
988       memcpy (&t0->buffer, b0, sizeof (b0[0]) - sizeof (b0->pre_data));
989       memcpy (t0->buffer.pre_data, b0->data + b0->current_data,
990               sizeof (t0->buffer.pre_data));
991
992       b += 1;
993       d += 1;
994     }
995 }
996
997 always_inline uword
998 ixge_ring_sub (ixge_dma_queue_t * q, u32 i0, u32 i1)
999 {
1000   i32 d = i1 - i0;
1001   ASSERT (i0 < q->n_descriptors);
1002   ASSERT (i1 < q->n_descriptors);
1003   return d < 0 ? q->n_descriptors + d : d;
1004 }
1005
1006 always_inline uword
1007 ixge_ring_add (ixge_dma_queue_t * q, u32 i0, u32 i1)
1008 {
1009   u32 d = i0 + i1;
1010   ASSERT (i0 < q->n_descriptors);
1011   ASSERT (i1 < q->n_descriptors);
1012   d -= d >= q->n_descriptors ? q->n_descriptors : 0;
1013   return d;
1014 }
1015
1016 always_inline uword
1017 ixge_tx_descriptor_matches_template (ixge_main_t * xm,
1018                                      ixge_tx_descriptor_t * d)
1019 {
1020   u32 cmp;
1021
1022   cmp = ((d->status0 & xm->tx_descriptor_template_mask.status0)
1023          ^ xm->tx_descriptor_template.status0);
1024   if (cmp)
1025     return 0;
1026   cmp = ((d->status1 & xm->tx_descriptor_template_mask.status1)
1027          ^ xm->tx_descriptor_template.status1);
1028   if (cmp)
1029     return 0;
1030
1031   return 1;
1032 }
1033
1034 static uword
1035 ixge_tx_no_wrap (ixge_main_t * xm,
1036                  ixge_device_t * xd,
1037                  ixge_dma_queue_t * dq,
1038                  u32 * buffers,
1039                  u32 start_descriptor_index,
1040                  u32 n_descriptors, ixge_tx_state_t * tx_state)
1041 {
1042   vlib_main_t *vm = xm->vlib_main;
1043   ixge_tx_descriptor_t *d, *d_sop;
1044   u32 n_left = n_descriptors;
1045   u32 *to_free = vec_end (xm->tx_buffers_pending_free);
1046   u32 *to_tx =
1047     vec_elt_at_index (dq->descriptor_buffer_indices, start_descriptor_index);
1048   u32 is_sop = tx_state->is_start_of_packet;
1049   u32 len_sop = tx_state->n_bytes_in_packet;
1050   u16 template_status = xm->tx_descriptor_template.status0;
1051   u32 descriptor_prefetch_rotor = 0;
1052
1053   ASSERT (start_descriptor_index + n_descriptors <= dq->n_descriptors);
1054   d = &dq->descriptors[start_descriptor_index].tx;
1055   d_sop = is_sop ? d : tx_state->start_of_packet_descriptor;
1056
1057   while (n_left >= 4)
1058     {
1059       vlib_buffer_t *b0, *b1;
1060       u32 bi0, fi0, len0;
1061       u32 bi1, fi1, len1;
1062       u8 is_eop0, is_eop1;
1063
1064       /* Prefetch next iteration. */
1065       vlib_prefetch_buffer_with_index (vm, buffers[2], LOAD);
1066       vlib_prefetch_buffer_with_index (vm, buffers[3], LOAD);
1067
1068       if ((descriptor_prefetch_rotor & 0x3) == 0)
1069         CLIB_PREFETCH (d + 4, CLIB_CACHE_LINE_BYTES, STORE);
1070
1071       descriptor_prefetch_rotor += 2;
1072
1073       bi0 = buffers[0];
1074       bi1 = buffers[1];
1075
1076       to_free[0] = fi0 = to_tx[0];
1077       to_tx[0] = bi0;
1078       to_free += fi0 != 0;
1079
1080       to_free[0] = fi1 = to_tx[1];
1081       to_tx[1] = bi1;
1082       to_free += fi1 != 0;
1083
1084       buffers += 2;
1085       n_left -= 2;
1086       to_tx += 2;
1087
1088       b0 = vlib_get_buffer (vm, bi0);
1089       b1 = vlib_get_buffer (vm, bi1);
1090
1091       is_eop0 = (b0->flags & VLIB_BUFFER_NEXT_PRESENT) == 0;
1092       is_eop1 = (b1->flags & VLIB_BUFFER_NEXT_PRESENT) == 0;
1093
1094       len0 = b0->current_length;
1095       len1 = b1->current_length;
1096
1097       ASSERT (ixge_tx_descriptor_matches_template (xm, d + 0));
1098       ASSERT (ixge_tx_descriptor_matches_template (xm, d + 1));
1099
1100       d[0].buffer_address =
1101         vlib_get_buffer_data_physical_address (vm, bi0) + b0->current_data;
1102       d[1].buffer_address =
1103         vlib_get_buffer_data_physical_address (vm, bi1) + b1->current_data;
1104
1105       d[0].n_bytes_this_buffer = len0;
1106       d[1].n_bytes_this_buffer = len1;
1107
1108       d[0].status0 =
1109         template_status | (is_eop0 <<
1110                            IXGE_TX_DESCRIPTOR_STATUS0_LOG2_IS_END_OF_PACKET);
1111       d[1].status0 =
1112         template_status | (is_eop1 <<
1113                            IXGE_TX_DESCRIPTOR_STATUS0_LOG2_IS_END_OF_PACKET);
1114
1115       len_sop = (is_sop ? 0 : len_sop) + len0;
1116       d_sop[0].status1 =
1117         IXGE_TX_DESCRIPTOR_STATUS1_N_BYTES_IN_PACKET (len_sop);
1118       d += 1;
1119       d_sop = is_eop0 ? d : d_sop;
1120
1121       is_sop = is_eop0;
1122
1123       len_sop = (is_sop ? 0 : len_sop) + len1;
1124       d_sop[0].status1 =
1125         IXGE_TX_DESCRIPTOR_STATUS1_N_BYTES_IN_PACKET (len_sop);
1126       d += 1;
1127       d_sop = is_eop1 ? d : d_sop;
1128
1129       is_sop = is_eop1;
1130     }
1131
1132   while (n_left > 0)
1133     {
1134       vlib_buffer_t *b0;
1135       u32 bi0, fi0, len0;
1136       u8 is_eop0;
1137
1138       bi0 = buffers[0];
1139
1140       to_free[0] = fi0 = to_tx[0];
1141       to_tx[0] = bi0;
1142       to_free += fi0 != 0;
1143
1144       buffers += 1;
1145       n_left -= 1;
1146       to_tx += 1;
1147
1148       b0 = vlib_get_buffer (vm, bi0);
1149
1150       is_eop0 = (b0->flags & VLIB_BUFFER_NEXT_PRESENT) == 0;
1151
1152       len0 = b0->current_length;
1153
1154       ASSERT (ixge_tx_descriptor_matches_template (xm, d + 0));
1155
1156       d[0].buffer_address =
1157         vlib_get_buffer_data_physical_address (vm, bi0) + b0->current_data;
1158
1159       d[0].n_bytes_this_buffer = len0;
1160
1161       d[0].status0 =
1162         template_status | (is_eop0 <<
1163                            IXGE_TX_DESCRIPTOR_STATUS0_LOG2_IS_END_OF_PACKET);
1164
1165       len_sop = (is_sop ? 0 : len_sop) + len0;
1166       d_sop[0].status1 =
1167         IXGE_TX_DESCRIPTOR_STATUS1_N_BYTES_IN_PACKET (len_sop);
1168       d += 1;
1169       d_sop = is_eop0 ? d : d_sop;
1170
1171       is_sop = is_eop0;
1172     }
1173
1174   if (tx_state->node->flags & VLIB_NODE_FLAG_TRACE)
1175     {
1176       to_tx =
1177         vec_elt_at_index (dq->descriptor_buffer_indices,
1178                           start_descriptor_index);
1179       ixge_tx_trace (xm, xd, dq, tx_state,
1180                      &dq->descriptors[start_descriptor_index].tx, to_tx,
1181                      n_descriptors);
1182     }
1183
1184   _vec_len (xm->tx_buffers_pending_free) =
1185     to_free - xm->tx_buffers_pending_free;
1186
1187   /* When we are done d_sop can point to end of ring.  Wrap it if so. */
1188   {
1189     ixge_tx_descriptor_t *d_start = &dq->descriptors[0].tx;
1190
1191     ASSERT (d_sop - d_start <= dq->n_descriptors);
1192     d_sop = d_sop - d_start == dq->n_descriptors ? d_start : d_sop;
1193   }
1194
1195   tx_state->is_start_of_packet = is_sop;
1196   tx_state->start_of_packet_descriptor = d_sop;
1197   tx_state->n_bytes_in_packet = len_sop;
1198
1199   return n_descriptors;
1200 }
1201
1202 static uword
1203 ixge_interface_tx (vlib_main_t * vm,
1204                    vlib_node_runtime_t * node, vlib_frame_t * f)
1205 {
1206   ixge_main_t *xm = &ixge_main;
1207   vnet_interface_output_runtime_t *rd = (void *) node->runtime_data;
1208   ixge_device_t *xd = vec_elt_at_index (xm->devices, rd->dev_instance);
1209   ixge_dma_queue_t *dq;
1210   u32 *from, n_left_tx, n_descriptors_to_tx, n_tail_drop;
1211   u32 queue_index = 0;          /* fixme parameter */
1212   ixge_tx_state_t tx_state;
1213
1214   tx_state.node = node;
1215   tx_state.is_start_of_packet = 1;
1216   tx_state.start_of_packet_descriptor = 0;
1217   tx_state.n_bytes_in_packet = 0;
1218
1219   from = vlib_frame_vector_args (f);
1220
1221   dq = vec_elt_at_index (xd->dma_queues[VLIB_TX], queue_index);
1222
1223   dq->head_index = dq->tx.head_index_write_back[0];
1224
1225   /* Since head == tail means ring is empty we can send up to dq->n_descriptors - 1. */
1226   n_left_tx = dq->n_descriptors - 1;
1227   n_left_tx -= ixge_ring_sub (dq, dq->head_index, dq->tail_index);
1228
1229   _vec_len (xm->tx_buffers_pending_free) = 0;
1230
1231   n_descriptors_to_tx = f->n_vectors;
1232   n_tail_drop = 0;
1233   if (PREDICT_FALSE (n_descriptors_to_tx > n_left_tx))
1234     {
1235       i32 i, n_ok, i_eop, i_sop;
1236
1237       i_sop = i_eop = ~0;
1238       for (i = n_left_tx - 1; i >= 0; i--)
1239         {
1240           vlib_buffer_t *b = vlib_get_buffer (vm, from[i]);
1241           if (!(b->flags & VLIB_BUFFER_NEXT_PRESENT))
1242             {
1243               if (i_sop != ~0 && i_eop != ~0)
1244                 break;
1245               i_eop = i;
1246               i_sop = i + 1;
1247             }
1248         }
1249       if (i == 0)
1250         n_ok = 0;
1251       else
1252         n_ok = i_eop + 1;
1253
1254       {
1255         ELOG_TYPE_DECLARE (e) =
1256         {
1257         .function = (char *) __FUNCTION__,.format =
1258             "ixge %d, ring full to tx %d head %d tail %d",.format_args =
1259             "i2i2i2i2",};
1260         struct
1261         {
1262           u16 instance, to_tx, head, tail;
1263         } *ed;
1264         ed = ELOG_DATA (&vm->elog_main, e);
1265         ed->instance = xd->device_index;
1266         ed->to_tx = n_descriptors_to_tx;
1267         ed->head = dq->head_index;
1268         ed->tail = dq->tail_index;
1269       }
1270
1271       if (n_ok < n_descriptors_to_tx)
1272         {
1273           n_tail_drop = n_descriptors_to_tx - n_ok;
1274           vec_add (xm->tx_buffers_pending_free, from + n_ok, n_tail_drop);
1275           vlib_error_count (vm, ixge_input_node.index,
1276                             IXGE_ERROR_tx_full_drops, n_tail_drop);
1277         }
1278
1279       n_descriptors_to_tx = n_ok;
1280     }
1281
1282   dq->tx.n_buffers_on_ring += n_descriptors_to_tx;
1283
1284   /* Process from tail to end of descriptor ring. */
1285   if (n_descriptors_to_tx > 0 && dq->tail_index < dq->n_descriptors)
1286     {
1287       u32 n =
1288         clib_min (dq->n_descriptors - dq->tail_index, n_descriptors_to_tx);
1289       n = ixge_tx_no_wrap (xm, xd, dq, from, dq->tail_index, n, &tx_state);
1290       from += n;
1291       n_descriptors_to_tx -= n;
1292       dq->tail_index += n;
1293       ASSERT (dq->tail_index <= dq->n_descriptors);
1294       if (dq->tail_index == dq->n_descriptors)
1295         dq->tail_index = 0;
1296     }
1297
1298   if (n_descriptors_to_tx > 0)
1299     {
1300       u32 n =
1301         ixge_tx_no_wrap (xm, xd, dq, from, 0, n_descriptors_to_tx, &tx_state);
1302       from += n;
1303       ASSERT (n == n_descriptors_to_tx);
1304       dq->tail_index += n;
1305       ASSERT (dq->tail_index <= dq->n_descriptors);
1306       if (dq->tail_index == dq->n_descriptors)
1307         dq->tail_index = 0;
1308     }
1309
1310   /* We should only get full packets. */
1311   ASSERT (tx_state.is_start_of_packet);
1312
1313   /* Report status when last descriptor is done. */
1314   {
1315     u32 i = dq->tail_index == 0 ? dq->n_descriptors - 1 : dq->tail_index - 1;
1316     ixge_tx_descriptor_t *d = &dq->descriptors[i].tx;
1317     d->status0 |= IXGE_TX_DESCRIPTOR_STATUS0_REPORT_STATUS;
1318   }
1319
1320   /* Give new descriptors to hardware. */
1321   {
1322     ixge_dma_regs_t *dr = get_dma_regs (xd, VLIB_TX, queue_index);
1323
1324     CLIB_MEMORY_BARRIER ();
1325
1326     dr->tail_index = dq->tail_index;
1327   }
1328
1329   /* Free any buffers that are done. */
1330   {
1331     u32 n = _vec_len (xm->tx_buffers_pending_free);
1332     if (n > 0)
1333       {
1334         vlib_buffer_free_no_next (vm, xm->tx_buffers_pending_free, n);
1335         _vec_len (xm->tx_buffers_pending_free) = 0;
1336         ASSERT (dq->tx.n_buffers_on_ring >= n);
1337         dq->tx.n_buffers_on_ring -= (n - n_tail_drop);
1338       }
1339   }
1340
1341   return f->n_vectors;
1342 }
1343
1344 static uword
1345 ixge_rx_queue_no_wrap (ixge_main_t * xm,
1346                        ixge_device_t * xd,
1347                        ixge_dma_queue_t * dq,
1348                        u32 start_descriptor_index, u32 n_descriptors)
1349 {
1350   vlib_main_t *vm = xm->vlib_main;
1351   vlib_node_runtime_t *node = dq->rx.node;
1352   ixge_descriptor_t *d;
1353   static ixge_descriptor_t *d_trace_save;
1354   static u32 *d_trace_buffers;
1355   u32 n_descriptors_left = n_descriptors;
1356   u32 *to_rx =
1357     vec_elt_at_index (dq->descriptor_buffer_indices, start_descriptor_index);
1358   u32 *to_add;
1359   u32 bi_sop = dq->rx.saved_start_of_packet_buffer_index;
1360   u32 bi_last = dq->rx.saved_last_buffer_index;
1361   u32 next_index_sop = dq->rx.saved_start_of_packet_next_index;
1362   u32 is_sop = dq->rx.is_start_of_packet;
1363   u32 next_index, n_left_to_next, *to_next;
1364   u32 n_packets = 0;
1365   u32 n_bytes = 0;
1366   u32 n_trace = vlib_get_trace_count (vm, node);
1367   vlib_buffer_t *b_last, b_dummy;
1368
1369   ASSERT (start_descriptor_index + n_descriptors <= dq->n_descriptors);
1370   d = &dq->descriptors[start_descriptor_index];
1371
1372   b_last = bi_last != ~0 ? vlib_get_buffer (vm, bi_last) : &b_dummy;
1373   next_index = dq->rx.next_index;
1374
1375   if (n_trace > 0)
1376     {
1377       u32 n = clib_min (n_trace, n_descriptors);
1378       if (d_trace_save)
1379         {
1380           _vec_len (d_trace_save) = 0;
1381           _vec_len (d_trace_buffers) = 0;
1382         }
1383       vec_add (d_trace_save, (ixge_descriptor_t *) d, n);
1384       vec_add (d_trace_buffers, to_rx, n);
1385     }
1386
1387   {
1388     uword l = vec_len (xm->rx_buffers_to_add);
1389
1390     if (l < n_descriptors_left)
1391       {
1392         u32 n_to_alloc = 2 * dq->n_descriptors - l;
1393         u32 n_allocated;
1394
1395         vec_resize (xm->rx_buffers_to_add, n_to_alloc);
1396
1397         _vec_len (xm->rx_buffers_to_add) = l;
1398         n_allocated =
1399           vlib_buffer_alloc (vm, xm->rx_buffers_to_add + l, n_to_alloc);
1400         _vec_len (xm->rx_buffers_to_add) += n_allocated;
1401
1402         /* Handle transient allocation failure */
1403         if (PREDICT_FALSE (l + n_allocated <= n_descriptors_left))
1404           {
1405             if (n_allocated == 0)
1406               vlib_error_count (vm, ixge_input_node.index,
1407                                 IXGE_ERROR_rx_alloc_no_physmem, 1);
1408             else
1409               vlib_error_count (vm, ixge_input_node.index,
1410                                 IXGE_ERROR_rx_alloc_fail, 1);
1411
1412             n_descriptors_left = l + n_allocated;
1413           }
1414         n_descriptors = n_descriptors_left;
1415       }
1416
1417     /* Add buffers from end of vector going backwards. */
1418     to_add = vec_end (xm->rx_buffers_to_add) - 1;
1419   }
1420
1421   while (n_descriptors_left > 0)
1422     {
1423       vlib_get_next_frame (vm, node, next_index, to_next, n_left_to_next);
1424
1425       while (n_descriptors_left >= 4 && n_left_to_next >= 2)
1426         {
1427           vlib_buffer_t *b0, *b1;
1428           u32 bi0, fi0, len0, l3_offset0, s20, s00, flags0;
1429           u32 bi1, fi1, len1, l3_offset1, s21, s01, flags1;
1430           u8 is_eop0, error0, next0;
1431           u8 is_eop1, error1, next1;
1432           ixge_descriptor_t d0, d1;
1433
1434           vlib_prefetch_buffer_with_index (vm, to_rx[2], STORE);
1435           vlib_prefetch_buffer_with_index (vm, to_rx[3], STORE);
1436
1437           CLIB_PREFETCH (d + 2, 32, STORE);
1438
1439           d0.as_u32x4 = d[0].as_u32x4;
1440           d1.as_u32x4 = d[1].as_u32x4;
1441
1442           s20 = d0.rx_from_hw.status[2];
1443           s21 = d1.rx_from_hw.status[2];
1444
1445           s00 = d0.rx_from_hw.status[0];
1446           s01 = d1.rx_from_hw.status[0];
1447
1448           if (!
1449               ((s20 & s21) & IXGE_RX_DESCRIPTOR_STATUS2_IS_OWNED_BY_SOFTWARE))
1450             goto found_hw_owned_descriptor_x2;
1451
1452           bi0 = to_rx[0];
1453           bi1 = to_rx[1];
1454
1455           ASSERT (to_add - 1 >= xm->rx_buffers_to_add);
1456           fi0 = to_add[0];
1457           fi1 = to_add[-1];
1458
1459           to_rx[0] = fi0;
1460           to_rx[1] = fi1;
1461           to_rx += 2;
1462           to_add -= 2;
1463
1464 #if 0
1465           ASSERT (VLIB_BUFFER_KNOWN_ALLOCATED ==
1466                   vlib_buffer_is_known (vm, bi0));
1467           ASSERT (VLIB_BUFFER_KNOWN_ALLOCATED ==
1468                   vlib_buffer_is_known (vm, bi1));
1469           ASSERT (VLIB_BUFFER_KNOWN_ALLOCATED ==
1470                   vlib_buffer_is_known (vm, fi0));
1471           ASSERT (VLIB_BUFFER_KNOWN_ALLOCATED ==
1472                   vlib_buffer_is_known (vm, fi1));
1473 #endif
1474
1475           b0 = vlib_get_buffer (vm, bi0);
1476           b1 = vlib_get_buffer (vm, bi1);
1477
1478           /*
1479            * Turn this on if you run into
1480            * "bad monkey" contexts, and you want to know exactly
1481            * which nodes they've visited... See main.c...
1482            */
1483           VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1484           VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b1);
1485
1486           CLIB_PREFETCH (b0->data, CLIB_CACHE_LINE_BYTES, LOAD);
1487           CLIB_PREFETCH (b1->data, CLIB_CACHE_LINE_BYTES, LOAD);
1488
1489           is_eop0 = (s20 & IXGE_RX_DESCRIPTOR_STATUS2_IS_END_OF_PACKET) != 0;
1490           is_eop1 = (s21 & IXGE_RX_DESCRIPTOR_STATUS2_IS_END_OF_PACKET) != 0;
1491
1492           ixge_rx_next_and_error_from_status_x2 (xd, s00, s20, s01, s21,
1493                                                  &next0, &error0, &flags0,
1494                                                  &next1, &error1, &flags1);
1495
1496           next0 = is_sop ? next0 : next_index_sop;
1497           next1 = is_eop0 ? next1 : next0;
1498           next_index_sop = next1;
1499
1500           b0->flags |= flags0 | (!is_eop0 << VLIB_BUFFER_LOG2_NEXT_PRESENT);
1501           b1->flags |= flags1 | (!is_eop1 << VLIB_BUFFER_LOG2_NEXT_PRESENT);
1502
1503           vnet_buffer (b0)->sw_if_index[VLIB_RX] = xd->vlib_sw_if_index;
1504           vnet_buffer (b1)->sw_if_index[VLIB_RX] = xd->vlib_sw_if_index;
1505           vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1506           vnet_buffer (b1)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1507
1508           b0->error = node->errors[error0];
1509           b1->error = node->errors[error1];
1510
1511           len0 = d0.rx_from_hw.n_packet_bytes_this_descriptor;
1512           len1 = d1.rx_from_hw.n_packet_bytes_this_descriptor;
1513           n_bytes += len0 + len1;
1514           n_packets += is_eop0 + is_eop1;
1515
1516           /* Give new buffers to hardware. */
1517           d0.rx_to_hw.tail_address =
1518             vlib_get_buffer_data_physical_address (vm, fi0);
1519           d1.rx_to_hw.tail_address =
1520             vlib_get_buffer_data_physical_address (vm, fi1);
1521           d0.rx_to_hw.head_address = d[0].rx_to_hw.tail_address;
1522           d1.rx_to_hw.head_address = d[1].rx_to_hw.tail_address;
1523           d[0].as_u32x4 = d0.as_u32x4;
1524           d[1].as_u32x4 = d1.as_u32x4;
1525
1526           d += 2;
1527           n_descriptors_left -= 2;
1528
1529           /* Point to either l2 or l3 header depending on next. */
1530           l3_offset0 = (is_sop && (next0 != IXGE_RX_NEXT_ETHERNET_INPUT))
1531             ? IXGE_RX_DESCRIPTOR_STATUS0_L3_OFFSET (s00) : 0;
1532           l3_offset1 = (is_eop0 && (next1 != IXGE_RX_NEXT_ETHERNET_INPUT))
1533             ? IXGE_RX_DESCRIPTOR_STATUS0_L3_OFFSET (s01) : 0;
1534
1535           b0->current_length = len0 - l3_offset0;
1536           b1->current_length = len1 - l3_offset1;
1537           b0->current_data = l3_offset0;
1538           b1->current_data = l3_offset1;
1539
1540           b_last->next_buffer = is_sop ? ~0 : bi0;
1541           b0->next_buffer = is_eop0 ? ~0 : bi1;
1542           bi_last = bi1;
1543           b_last = b1;
1544
1545           if (CLIB_DEBUG > 0)
1546             {
1547               u32 bi_sop0 = is_sop ? bi0 : bi_sop;
1548               u32 bi_sop1 = is_eop0 ? bi1 : bi_sop0;
1549
1550               if (is_eop0)
1551                 {
1552                   u8 *msg = vlib_validate_buffer (vm, bi_sop0,
1553                                                   /* follow_buffer_next */ 1);
1554                   ASSERT (!msg);
1555                 }
1556               if (is_eop1)
1557                 {
1558                   u8 *msg = vlib_validate_buffer (vm, bi_sop1,
1559                                                   /* follow_buffer_next */ 1);
1560                   ASSERT (!msg);
1561                 }
1562             }
1563           if (0)                /* "Dave" version */
1564             {
1565               u32 bi_sop0 = is_sop ? bi0 : bi_sop;
1566               u32 bi_sop1 = is_eop0 ? bi1 : bi_sop0;
1567
1568               if (is_eop0)
1569                 {
1570                   to_next[0] = bi_sop0;
1571                   to_next++;
1572                   n_left_to_next--;
1573
1574                   vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1575                                                    to_next, n_left_to_next,
1576                                                    bi_sop0, next0);
1577                 }
1578               if (is_eop1)
1579                 {
1580                   to_next[0] = bi_sop1;
1581                   to_next++;
1582                   n_left_to_next--;
1583
1584                   vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1585                                                    to_next, n_left_to_next,
1586                                                    bi_sop1, next1);
1587                 }
1588               is_sop = is_eop1;
1589               bi_sop = bi_sop1;
1590             }
1591           if (1)                /* "Eliot" version */
1592             {
1593               /* Speculatively enqueue to cached next. */
1594               u8 saved_is_sop = is_sop;
1595               u32 bi_sop_save = bi_sop;
1596
1597               bi_sop = saved_is_sop ? bi0 : bi_sop;
1598               to_next[0] = bi_sop;
1599               to_next += is_eop0;
1600               n_left_to_next -= is_eop0;
1601
1602               bi_sop = is_eop0 ? bi1 : bi_sop;
1603               to_next[0] = bi_sop;
1604               to_next += is_eop1;
1605               n_left_to_next -= is_eop1;
1606
1607               is_sop = is_eop1;
1608
1609               if (PREDICT_FALSE
1610                   (!(next0 == next_index && next1 == next_index)))
1611                 {
1612                   /* Undo speculation. */
1613                   to_next -= is_eop0 + is_eop1;
1614                   n_left_to_next += is_eop0 + is_eop1;
1615
1616                   /* Re-do both descriptors being careful about where we enqueue. */
1617                   bi_sop = saved_is_sop ? bi0 : bi_sop_save;
1618                   if (is_eop0)
1619                     {
1620                       if (next0 != next_index)
1621                         vlib_set_next_frame_buffer (vm, node, next0, bi_sop);
1622                       else
1623                         {
1624                           to_next[0] = bi_sop;
1625                           to_next += 1;
1626                           n_left_to_next -= 1;
1627                         }
1628                     }
1629
1630                   bi_sop = is_eop0 ? bi1 : bi_sop;
1631                   if (is_eop1)
1632                     {
1633                       if (next1 != next_index)
1634                         vlib_set_next_frame_buffer (vm, node, next1, bi_sop);
1635                       else
1636                         {
1637                           to_next[0] = bi_sop;
1638                           to_next += 1;
1639                           n_left_to_next -= 1;
1640                         }
1641                     }
1642
1643                   /* Switch cached next index when next for both packets is the same. */
1644                   if (is_eop0 && is_eop1 && next0 == next1)
1645                     {
1646                       vlib_put_next_frame (vm, node, next_index,
1647                                            n_left_to_next);
1648                       next_index = next0;
1649                       vlib_get_next_frame (vm, node, next_index,
1650                                            to_next, n_left_to_next);
1651                     }
1652                 }
1653             }
1654         }
1655
1656       /* Bail out of dual loop and proceed with single loop. */
1657     found_hw_owned_descriptor_x2:
1658
1659       while (n_descriptors_left > 0 && n_left_to_next > 0)
1660         {
1661           vlib_buffer_t *b0;
1662           u32 bi0, fi0, len0, l3_offset0, s20, s00, flags0;
1663           u8 is_eop0, error0, next0;
1664           ixge_descriptor_t d0;
1665
1666           d0.as_u32x4 = d[0].as_u32x4;
1667
1668           s20 = d0.rx_from_hw.status[2];
1669           s00 = d0.rx_from_hw.status[0];
1670
1671           if (!(s20 & IXGE_RX_DESCRIPTOR_STATUS2_IS_OWNED_BY_SOFTWARE))
1672             goto found_hw_owned_descriptor_x1;
1673
1674           bi0 = to_rx[0];
1675           ASSERT (to_add >= xm->rx_buffers_to_add);
1676           fi0 = to_add[0];
1677
1678           to_rx[0] = fi0;
1679           to_rx += 1;
1680           to_add -= 1;
1681
1682 #if 0
1683           ASSERT (VLIB_BUFFER_KNOWN_ALLOCATED ==
1684                   vlib_buffer_is_known (vm, bi0));
1685           ASSERT (VLIB_BUFFER_KNOWN_ALLOCATED ==
1686                   vlib_buffer_is_known (vm, fi0));
1687 #endif
1688
1689           b0 = vlib_get_buffer (vm, bi0);
1690
1691           /*
1692            * Turn this on if you run into
1693            * "bad monkey" contexts, and you want to know exactly
1694            * which nodes they've visited...
1695            */
1696           VLIB_BUFFER_TRACE_TRAJECTORY_INIT (b0);
1697
1698           is_eop0 = (s20 & IXGE_RX_DESCRIPTOR_STATUS2_IS_END_OF_PACKET) != 0;
1699           ixge_rx_next_and_error_from_status_x1
1700             (xd, s00, s20, &next0, &error0, &flags0);
1701
1702           next0 = is_sop ? next0 : next_index_sop;
1703           next_index_sop = next0;
1704
1705           b0->flags |= flags0 | (!is_eop0 << VLIB_BUFFER_LOG2_NEXT_PRESENT);
1706
1707           vnet_buffer (b0)->sw_if_index[VLIB_RX] = xd->vlib_sw_if_index;
1708           vnet_buffer (b0)->sw_if_index[VLIB_TX] = (u32) ~ 0;
1709
1710           b0->error = node->errors[error0];
1711
1712           len0 = d0.rx_from_hw.n_packet_bytes_this_descriptor;
1713           n_bytes += len0;
1714           n_packets += is_eop0;
1715
1716           /* Give new buffer to hardware. */
1717           d0.rx_to_hw.tail_address =
1718             vlib_get_buffer_data_physical_address (vm, fi0);
1719           d0.rx_to_hw.head_address = d0.rx_to_hw.tail_address;
1720           d[0].as_u32x4 = d0.as_u32x4;
1721
1722           d += 1;
1723           n_descriptors_left -= 1;
1724
1725           /* Point to either l2 or l3 header depending on next. */
1726           l3_offset0 = (is_sop && (next0 != IXGE_RX_NEXT_ETHERNET_INPUT))
1727             ? IXGE_RX_DESCRIPTOR_STATUS0_L3_OFFSET (s00) : 0;
1728           b0->current_length = len0 - l3_offset0;
1729           b0->current_data = l3_offset0;
1730
1731           b_last->next_buffer = is_sop ? ~0 : bi0;
1732           bi_last = bi0;
1733           b_last = b0;
1734
1735           bi_sop = is_sop ? bi0 : bi_sop;
1736
1737           if (CLIB_DEBUG > 0 && is_eop0)
1738             {
1739               u8 *msg =
1740                 vlib_validate_buffer (vm, bi_sop, /* follow_buffer_next */ 1);
1741               ASSERT (!msg);
1742             }
1743
1744           if (0)                /* "Dave" version */
1745             {
1746               if (is_eop0)
1747                 {
1748                   to_next[0] = bi_sop;
1749                   to_next++;
1750                   n_left_to_next--;
1751
1752                   vlib_validate_buffer_enqueue_x1 (vm, node, next_index,
1753                                                    to_next, n_left_to_next,
1754                                                    bi_sop, next0);
1755                 }
1756             }
1757           if (1)                /* "Eliot" version */
1758             {
1759               if (PREDICT_TRUE (next0 == next_index))
1760                 {
1761                   to_next[0] = bi_sop;
1762                   to_next += is_eop0;
1763                   n_left_to_next -= is_eop0;
1764                 }
1765               else
1766                 {
1767                   if (next0 != next_index && is_eop0)
1768                     vlib_set_next_frame_buffer (vm, node, next0, bi_sop);
1769
1770                   vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1771                   next_index = next0;
1772                   vlib_get_next_frame (vm, node, next_index,
1773                                        to_next, n_left_to_next);
1774                 }
1775             }
1776           is_sop = is_eop0;
1777         }
1778       vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1779     }
1780
1781 found_hw_owned_descriptor_x1:
1782   if (n_descriptors_left > 0)
1783     vlib_put_next_frame (vm, node, next_index, n_left_to_next);
1784
1785   _vec_len (xm->rx_buffers_to_add) = (to_add + 1) - xm->rx_buffers_to_add;
1786
1787   {
1788     u32 n_done = n_descriptors - n_descriptors_left;
1789
1790     if (n_trace > 0 && n_done > 0)
1791       {
1792         u32 n = clib_min (n_trace, n_done);
1793         ixge_rx_trace (xm, xd, dq,
1794                        d_trace_save,
1795                        d_trace_buffers,
1796                        &dq->descriptors[start_descriptor_index], n);
1797         vlib_set_trace_count (vm, node, n_trace - n);
1798       }
1799     if (d_trace_save)
1800       {
1801         _vec_len (d_trace_save) = 0;
1802         _vec_len (d_trace_buffers) = 0;
1803       }
1804
1805     /* Don't keep a reference to b_last if we don't have to.
1806        Otherwise we can over-write a next_buffer pointer after already haven
1807        enqueued a packet. */
1808     if (is_sop)
1809       {
1810         b_last->next_buffer = ~0;
1811         bi_last = ~0;
1812       }
1813
1814     dq->rx.n_descriptors_done_this_call = n_done;
1815     dq->rx.n_descriptors_done_total += n_done;
1816     dq->rx.is_start_of_packet = is_sop;
1817     dq->rx.saved_start_of_packet_buffer_index = bi_sop;
1818     dq->rx.saved_last_buffer_index = bi_last;
1819     dq->rx.saved_start_of_packet_next_index = next_index_sop;
1820     dq->rx.next_index = next_index;
1821     dq->rx.n_bytes += n_bytes;
1822
1823     return n_packets;
1824   }
1825 }
1826
1827 static uword
1828 ixge_rx_queue (ixge_main_t * xm,
1829                ixge_device_t * xd,
1830                vlib_node_runtime_t * node, u32 queue_index)
1831 {
1832   ixge_dma_queue_t *dq =
1833     vec_elt_at_index (xd->dma_queues[VLIB_RX], queue_index);
1834   ixge_dma_regs_t *dr = get_dma_regs (xd, VLIB_RX, dq->queue_index);
1835   uword n_packets = 0;
1836   u32 hw_head_index, sw_head_index;
1837
1838   /* One time initialization. */
1839   if (!dq->rx.node)
1840     {
1841       dq->rx.node = node;
1842       dq->rx.is_start_of_packet = 1;
1843       dq->rx.saved_start_of_packet_buffer_index = ~0;
1844       dq->rx.saved_last_buffer_index = ~0;
1845     }
1846
1847   dq->rx.next_index = node->cached_next_index;
1848
1849   dq->rx.n_descriptors_done_total = 0;
1850   dq->rx.n_descriptors_done_this_call = 0;
1851   dq->rx.n_bytes = 0;
1852
1853   /* Fetch head from hardware and compare to where we think we are. */
1854   hw_head_index = dr->head_index;
1855   sw_head_index = dq->head_index;
1856
1857   if (hw_head_index == sw_head_index)
1858     goto done;
1859
1860   if (hw_head_index < sw_head_index)
1861     {
1862       u32 n_tried = dq->n_descriptors - sw_head_index;
1863       n_packets += ixge_rx_queue_no_wrap (xm, xd, dq, sw_head_index, n_tried);
1864       sw_head_index =
1865         ixge_ring_add (dq, sw_head_index,
1866                        dq->rx.n_descriptors_done_this_call);
1867
1868       if (dq->rx.n_descriptors_done_this_call != n_tried)
1869         goto done;
1870     }
1871   if (hw_head_index >= sw_head_index)
1872     {
1873       u32 n_tried = hw_head_index - sw_head_index;
1874       n_packets += ixge_rx_queue_no_wrap (xm, xd, dq, sw_head_index, n_tried);
1875       sw_head_index =
1876         ixge_ring_add (dq, sw_head_index,
1877                        dq->rx.n_descriptors_done_this_call);
1878     }
1879
1880 done:
1881   dq->head_index = sw_head_index;
1882   dq->tail_index =
1883     ixge_ring_add (dq, dq->tail_index, dq->rx.n_descriptors_done_total);
1884
1885   /* Give tail back to hardware. */
1886   CLIB_MEMORY_BARRIER ();
1887
1888   dr->tail_index = dq->tail_index;
1889
1890   vlib_increment_combined_counter (vnet_main.
1891                                    interface_main.combined_sw_if_counters +
1892                                    VNET_INTERFACE_COUNTER_RX,
1893                                    0 /* thread_index */ ,
1894                                    xd->vlib_sw_if_index, n_packets,
1895                                    dq->rx.n_bytes);
1896
1897   return n_packets;
1898 }
1899
1900 static void
1901 ixge_interrupt (ixge_main_t * xm, ixge_device_t * xd, u32 i)
1902 {
1903   vlib_main_t *vm = xm->vlib_main;
1904   ixge_regs_t *r = xd->regs;
1905
1906   if (i != 20)
1907     {
1908       ELOG_TYPE_DECLARE (e) =
1909       {
1910         .function = (char *) __FUNCTION__,.format =
1911           "ixge %d, %s",.format_args = "i1t1",.n_enum_strings =
1912           16,.enum_strings =
1913         {
1914       "flow director",
1915             "rx miss",
1916             "pci exception",
1917             "mailbox",
1918             "link status change",
1919             "linksec key exchange",
1920             "manageability event",
1921             "reserved23",
1922             "sdp0",
1923             "sdp1",
1924             "sdp2",
1925             "sdp3",
1926             "ecc", "descriptor handler error", "tcp timer", "other",},};
1927       struct
1928       {
1929         u8 instance;
1930         u8 index;
1931       } *ed;
1932       ed = ELOG_DATA (&vm->elog_main, e);
1933       ed->instance = xd->device_index;
1934       ed->index = i - 16;
1935     }
1936   else
1937     {
1938       u32 v = r->xge_mac.link_status;
1939       uword is_up = (v & (1 << 30)) != 0;
1940
1941       ELOG_TYPE_DECLARE (e) =
1942       {
1943       .function = (char *) __FUNCTION__,.format =
1944           "ixge %d, link status change 0x%x",.format_args = "i4i4",};
1945       struct
1946       {
1947         u32 instance, link_status;
1948       } *ed;
1949       ed = ELOG_DATA (&vm->elog_main, e);
1950       ed->instance = xd->device_index;
1951       ed->link_status = v;
1952       xd->link_status_at_last_link_change = v;
1953
1954       vlib_process_signal_event (vm, ixge_process_node.index,
1955                                  EVENT_SET_FLAGS,
1956                                  ((is_up << 31) | xd->vlib_hw_if_index));
1957     }
1958 }
1959
1960 always_inline u32
1961 clean_block (u32 * b, u32 * t, u32 n_left)
1962 {
1963   u32 *t0 = t;
1964
1965   while (n_left >= 4)
1966     {
1967       u32 bi0, bi1, bi2, bi3;
1968
1969       t[0] = bi0 = b[0];
1970       b[0] = 0;
1971       t += bi0 != 0;
1972
1973       t[0] = bi1 = b[1];
1974       b[1] = 0;
1975       t += bi1 != 0;
1976
1977       t[0] = bi2 = b[2];
1978       b[2] = 0;
1979       t += bi2 != 0;
1980
1981       t[0] = bi3 = b[3];
1982       b[3] = 0;
1983       t += bi3 != 0;
1984
1985       b += 4;
1986       n_left -= 4;
1987     }
1988
1989   while (n_left > 0)
1990     {
1991       u32 bi0;
1992
1993       t[0] = bi0 = b[0];
1994       b[0] = 0;
1995       t += bi0 != 0;
1996       b += 1;
1997       n_left -= 1;
1998     }
1999
2000   return t - t0;
2001 }
2002
2003 static void
2004 ixge_tx_queue (ixge_main_t * xm, ixge_device_t * xd, u32 queue_index)
2005 {
2006   vlib_main_t *vm = xm->vlib_main;
2007   ixge_dma_queue_t *dq =
2008     vec_elt_at_index (xd->dma_queues[VLIB_TX], queue_index);
2009   u32 n_clean, *b, *t, *t0;
2010   i32 n_hw_owned_descriptors;
2011   i32 first_to_clean, last_to_clean;
2012   u64 hwbp_race = 0;
2013
2014   /* Handle case where head write back pointer update
2015    * arrives after the interrupt during high PCI bus loads.
2016    */
2017   while ((dq->head_index == dq->tx.head_index_write_back[0]) &&
2018          dq->tx.n_buffers_on_ring && (dq->head_index != dq->tail_index))
2019     {
2020       hwbp_race++;
2021       if (IXGE_HWBP_RACE_ELOG && (hwbp_race == 1))
2022         {
2023           ELOG_TYPE_DECLARE (e) =
2024           {
2025           .function = (char *) __FUNCTION__,.format =
2026               "ixge %d tx head index race: head %4d, tail %4d, buffs %4d",.format_args
2027               = "i4i4i4i4",};
2028           struct
2029           {
2030             u32 instance, head_index, tail_index, n_buffers_on_ring;
2031           } *ed;
2032           ed = ELOG_DATA (&vm->elog_main, e);
2033           ed->instance = xd->device_index;
2034           ed->head_index = dq->head_index;
2035           ed->tail_index = dq->tail_index;
2036           ed->n_buffers_on_ring = dq->tx.n_buffers_on_ring;
2037         }
2038     }
2039
2040   dq->head_index = dq->tx.head_index_write_back[0];
2041   n_hw_owned_descriptors = ixge_ring_sub (dq, dq->head_index, dq->tail_index);
2042   ASSERT (dq->tx.n_buffers_on_ring >= n_hw_owned_descriptors);
2043   n_clean = dq->tx.n_buffers_on_ring - n_hw_owned_descriptors;
2044
2045   if (IXGE_HWBP_RACE_ELOG && hwbp_race)
2046     {
2047       ELOG_TYPE_DECLARE (e) =
2048       {
2049       .function = (char *) __FUNCTION__,.format =
2050           "ixge %d tx head index race: head %4d, hw_owned %4d, n_clean %4d, retries %d",.format_args
2051           = "i4i4i4i4i4",};
2052       struct
2053       {
2054         u32 instance, head_index, n_hw_owned_descriptors, n_clean, retries;
2055       } *ed;
2056       ed = ELOG_DATA (&vm->elog_main, e);
2057       ed->instance = xd->device_index;
2058       ed->head_index = dq->head_index;
2059       ed->n_hw_owned_descriptors = n_hw_owned_descriptors;
2060       ed->n_clean = n_clean;
2061       ed->retries = hwbp_race;
2062     }
2063
2064   /*
2065    * This function used to wait until hardware owned zero descriptors.
2066    * At high PPS rates, that doesn't happen until the TX ring is
2067    * completely full of descriptors which need to be cleaned up.
2068    * That, in turn, causes TX ring-full drops and/or long RX service
2069    * interruptions.
2070    */
2071   if (n_clean == 0)
2072     return;
2073
2074   /* Clean the n_clean descriptors prior to the reported hardware head */
2075   last_to_clean = dq->head_index - 1;
2076   last_to_clean = (last_to_clean < 0) ? last_to_clean + dq->n_descriptors :
2077     last_to_clean;
2078
2079   first_to_clean = (last_to_clean) - (n_clean - 1);
2080   first_to_clean = (first_to_clean < 0) ? first_to_clean + dq->n_descriptors :
2081     first_to_clean;
2082
2083   vec_resize (xm->tx_buffers_pending_free, dq->n_descriptors - 1);
2084   t0 = t = xm->tx_buffers_pending_free;
2085   b = dq->descriptor_buffer_indices + first_to_clean;
2086
2087   /* Wrap case: clean from first to end, then start to last */
2088   if (first_to_clean > last_to_clean)
2089     {
2090       t += clean_block (b, t, (dq->n_descriptors - 1) - first_to_clean);
2091       first_to_clean = 0;
2092       b = dq->descriptor_buffer_indices;
2093     }
2094
2095   /* Typical case: clean from first to last */
2096   if (first_to_clean <= last_to_clean)
2097     t += clean_block (b, t, (last_to_clean - first_to_clean) + 1);
2098
2099   if (t > t0)
2100     {
2101       u32 n = t - t0;
2102       vlib_buffer_free_no_next (vm, t0, n);
2103       ASSERT (dq->tx.n_buffers_on_ring >= n);
2104       dq->tx.n_buffers_on_ring -= n;
2105       _vec_len (xm->tx_buffers_pending_free) = 0;
2106     }
2107 }
2108
2109 /* RX queue interrupts 0 thru 7; TX 8 thru 15. */
2110 always_inline uword
2111 ixge_interrupt_is_rx_queue (uword i)
2112 {
2113   return i < 8;
2114 }
2115
2116 always_inline uword
2117 ixge_interrupt_is_tx_queue (uword i)
2118 {
2119   return i >= 8 && i < 16;
2120 }
2121
2122 always_inline uword
2123 ixge_tx_queue_to_interrupt (uword i)
2124 {
2125   return 8 + i;
2126 }
2127
2128 always_inline uword
2129 ixge_rx_queue_to_interrupt (uword i)
2130 {
2131   return 0 + i;
2132 }
2133
2134 always_inline uword
2135 ixge_interrupt_rx_queue (uword i)
2136 {
2137   ASSERT (ixge_interrupt_is_rx_queue (i));
2138   return i - 0;
2139 }
2140
2141 always_inline uword
2142 ixge_interrupt_tx_queue (uword i)
2143 {
2144   ASSERT (ixge_interrupt_is_tx_queue (i));
2145   return i - 8;
2146 }
2147
2148 static uword
2149 ixge_device_input (ixge_main_t * xm,
2150                    ixge_device_t * xd, vlib_node_runtime_t * node)
2151 {
2152   ixge_regs_t *r = xd->regs;
2153   u32 i, s;
2154   uword n_rx_packets = 0;
2155
2156   s = r->interrupt.status_write_1_to_set;
2157   if (s)
2158     r->interrupt.status_write_1_to_clear = s;
2159
2160   /* *INDENT-OFF* */
2161   foreach_set_bit (i, s, ({
2162     if (ixge_interrupt_is_rx_queue (i))
2163       n_rx_packets += ixge_rx_queue (xm, xd, node, ixge_interrupt_rx_queue (i));
2164
2165     else if (ixge_interrupt_is_tx_queue (i))
2166       ixge_tx_queue (xm, xd, ixge_interrupt_tx_queue (i));
2167
2168     else
2169       ixge_interrupt (xm, xd, i);
2170   }));
2171   /* *INDENT-ON* */
2172
2173   return n_rx_packets;
2174 }
2175
2176 static uword
2177 ixge_input (vlib_main_t * vm, vlib_node_runtime_t * node, vlib_frame_t * f)
2178 {
2179   ixge_main_t *xm = &ixge_main;
2180   ixge_device_t *xd;
2181   uword n_rx_packets = 0;
2182
2183   if (node->state == VLIB_NODE_STATE_INTERRUPT)
2184     {
2185       uword i;
2186
2187       /* Loop over devices with interrupts. */
2188       /* *INDENT-OFF* */
2189       foreach_set_bit (i, node->runtime_data[0], ({
2190         xd = vec_elt_at_index (xm->devices, i);
2191         n_rx_packets += ixge_device_input (xm, xd, node);
2192
2193         /* Re-enable interrupts since we're going to stay in interrupt mode. */
2194         if (! (node->flags & VLIB_NODE_FLAG_SWITCH_FROM_INTERRUPT_TO_POLLING_MODE))
2195           xd->regs->interrupt.enable_write_1_to_set = ~0;
2196       }));
2197       /* *INDENT-ON* */
2198
2199       /* Clear mask of devices with pending interrupts. */
2200       node->runtime_data[0] = 0;
2201     }
2202   else
2203     {
2204       /* Poll all devices for input/interrupts. */
2205       vec_foreach (xd, xm->devices)
2206       {
2207         n_rx_packets += ixge_device_input (xm, xd, node);
2208
2209         /* Re-enable interrupts when switching out of polling mode. */
2210         if (node->flags &
2211             VLIB_NODE_FLAG_SWITCH_FROM_POLLING_TO_INTERRUPT_MODE)
2212           xd->regs->interrupt.enable_write_1_to_set = ~0;
2213       }
2214     }
2215
2216   return n_rx_packets;
2217 }
2218
2219 static char *ixge_error_strings[] = {
2220 #define _(n,s) s,
2221   foreach_ixge_error
2222 #undef _
2223 };
2224
2225 /* *INDENT-OFF* */
2226 VLIB_REGISTER_NODE (ixge_input_node, static) = {
2227   .function = ixge_input,
2228   .type = VLIB_NODE_TYPE_INPUT,
2229   .name = "ixge-input",
2230
2231   /* Will be enabled if/when hardware is detected. */
2232   .state = VLIB_NODE_STATE_DISABLED,
2233
2234   .format_buffer = format_ethernet_header_with_length,
2235   .format_trace = format_ixge_rx_dma_trace,
2236
2237   .n_errors = IXGE_N_ERROR,
2238   .error_strings = ixge_error_strings,
2239
2240   .n_next_nodes = IXGE_RX_N_NEXT,
2241   .next_nodes = {
2242     [IXGE_RX_NEXT_DROP] = "error-drop",
2243     [IXGE_RX_NEXT_ETHERNET_INPUT] = "ethernet-input",
2244     [IXGE_RX_NEXT_IP4_INPUT] = "ip4-input",
2245     [IXGE_RX_NEXT_IP6_INPUT] = "ip6-input",
2246   },
2247 };
2248
2249 VLIB_NODE_FUNCTION_MULTIARCH_CLONE (ixge_input)
2250 CLIB_MULTIARCH_SELECT_FN (ixge_input)
2251 /* *INDENT-ON* */
2252
2253 static u8 *
2254 format_ixge_device_name (u8 * s, va_list * args)
2255 {
2256   u32 i = va_arg (*args, u32);
2257   ixge_main_t *xm = &ixge_main;
2258   ixge_device_t *xd = vec_elt_at_index (xm->devices, i);
2259   vlib_pci_addr_t *addr = vlib_pci_get_addr (xd->pci_dev_handle);
2260   return format (s, "TenGigabitEthernet%x/%x/%x/%x",
2261                  addr->domain, addr->bus, addr->slot, addr->function);
2262 }
2263
2264 #define IXGE_COUNTER_IS_64_BIT (1 << 0)
2265 #define IXGE_COUNTER_NOT_CLEAR_ON_READ (1 << 1)
2266
2267 static u8 ixge_counter_flags[] = {
2268 #define _(a,f) 0,
2269 #define _64(a,f) IXGE_COUNTER_IS_64_BIT,
2270   foreach_ixge_counter
2271 #undef _
2272 #undef _64
2273 };
2274
2275 static void
2276 ixge_update_counters (ixge_device_t * xd)
2277 {
2278   /* Byte offset for counter registers. */
2279   static u32 reg_offsets[] = {
2280 #define _(a,f) (a) / sizeof (u32),
2281 #define _64(a,f) _(a,f)
2282     foreach_ixge_counter
2283 #undef _
2284 #undef _64
2285   };
2286   volatile u32 *r = (volatile u32 *) xd->regs;
2287   int i;
2288
2289   for (i = 0; i < ARRAY_LEN (xd->counters); i++)
2290     {
2291       u32 o = reg_offsets[i];
2292       xd->counters[i] += r[o];
2293       if (ixge_counter_flags[i] & IXGE_COUNTER_NOT_CLEAR_ON_READ)
2294         r[o] = 0;
2295       if (ixge_counter_flags[i] & IXGE_COUNTER_IS_64_BIT)
2296         xd->counters[i] += (u64) r[o + 1] << (u64) 32;
2297     }
2298 }
2299
2300 static u8 *
2301 format_ixge_device_id (u8 * s, va_list * args)
2302 {
2303   u32 device_id = va_arg (*args, u32);
2304   char *t = 0;
2305   switch (device_id)
2306     {
2307 #define _(f,n) case n: t = #f; break;
2308       foreach_ixge_pci_device_id;
2309 #undef _
2310     default:
2311       t = 0;
2312       break;
2313     }
2314   if (t == 0)
2315     s = format (s, "unknown 0x%x", device_id);
2316   else
2317     s = format (s, "%s", t);
2318   return s;
2319 }
2320
2321 static u8 *
2322 format_ixge_link_status (u8 * s, va_list * args)
2323 {
2324   ixge_device_t *xd = va_arg (*args, ixge_device_t *);
2325   u32 v = xd->link_status_at_last_link_change;
2326
2327   s = format (s, "%s", (v & (1 << 30)) ? "up" : "down");
2328
2329   {
2330     char *modes[] = {
2331       "1g", "10g parallel", "10g serial", "autoneg",
2332     };
2333     char *speeds[] = {
2334       "unknown", "100m", "1g", "10g",
2335     };
2336     s = format (s, ", mode %s, speed %s",
2337                 modes[(v >> 26) & 3], speeds[(v >> 28) & 3]);
2338   }
2339
2340   return s;
2341 }
2342
2343 static u8 *
2344 format_ixge_device (u8 * s, va_list * args)
2345 {
2346   u32 dev_instance = va_arg (*args, u32);
2347   CLIB_UNUSED (int verbose) = va_arg (*args, int);
2348   ixge_main_t *xm = &ixge_main;
2349   ixge_device_t *xd = vec_elt_at_index (xm->devices, dev_instance);
2350   ixge_phy_t *phy = xd->phys + xd->phy_index;
2351   u32 indent = format_get_indent (s);
2352
2353   ixge_update_counters (xd);
2354   xd->link_status_at_last_link_change = xd->regs->xge_mac.link_status;
2355
2356   s = format (s, "Intel 8259X: id %U\n%Ulink %U",
2357               format_ixge_device_id, xd->device_id,
2358               format_white_space, indent + 2, format_ixge_link_status, xd);
2359
2360   {
2361
2362     vlib_pci_addr_t *addr = vlib_pci_get_addr (xd->pci_dev_handle);
2363     vlib_pci_device_info_t *d = vlib_pci_get_device_info (addr, 0);
2364
2365     if (d)
2366       s = format (s, "\n%UPCIe %U", format_white_space, indent + 2,
2367                   format_vlib_pci_link_speed, d);
2368   }
2369
2370   s = format (s, "\n%U", format_white_space, indent + 2);
2371   if (phy->mdio_address != ~0)
2372     s = format (s, "PHY address %d, id 0x%x", phy->mdio_address, phy->id);
2373   else if (xd->sfp_eeprom.id == SFP_ID_sfp)
2374     s = format (s, "SFP %U", format_sfp_eeprom, &xd->sfp_eeprom);
2375   else
2376     s = format (s, "PHY not found");
2377
2378   /* FIXME */
2379   {
2380     ixge_dma_queue_t *dq = vec_elt_at_index (xd->dma_queues[VLIB_RX], 0);
2381     ixge_dma_regs_t *dr = get_dma_regs (xd, VLIB_RX, 0);
2382     u32 hw_head_index = dr->head_index;
2383     u32 sw_head_index = dq->head_index;
2384     u32 nitems;
2385
2386     nitems = ixge_ring_sub (dq, hw_head_index, sw_head_index);
2387     s = format (s, "\n%U%d unprocessed, %d total buffers on rx queue 0 ring",
2388                 format_white_space, indent + 2, nitems, dq->n_descriptors);
2389
2390     s = format (s, "\n%U%d buffers in driver rx cache",
2391                 format_white_space, indent + 2,
2392                 vec_len (xm->rx_buffers_to_add));
2393
2394     s = format (s, "\n%U%d buffers on tx queue 0 ring",
2395                 format_white_space, indent + 2,
2396                 xd->dma_queues[VLIB_TX][0].tx.n_buffers_on_ring);
2397   }
2398   {
2399     u32 i;
2400     u64 v;
2401     static char *names[] = {
2402 #define _(a,f) #f,
2403 #define _64(a,f) _(a,f)
2404       foreach_ixge_counter
2405 #undef _
2406 #undef _64
2407     };
2408
2409     for (i = 0; i < ARRAY_LEN (names); i++)
2410       {
2411         v = xd->counters[i] - xd->counters_last_clear[i];
2412         if (v != 0)
2413           s = format (s, "\n%U%-40U%16Ld",
2414                       format_white_space, indent + 2,
2415                       format_c_identifier, names[i], v);
2416       }
2417   }
2418
2419   return s;
2420 }
2421
2422 static void
2423 ixge_clear_hw_interface_counters (u32 instance)
2424 {
2425   ixge_main_t *xm = &ixge_main;
2426   ixge_device_t *xd = vec_elt_at_index (xm->devices, instance);
2427   ixge_update_counters (xd);
2428   memcpy (xd->counters_last_clear, xd->counters, sizeof (xd->counters));
2429 }
2430
2431 /*
2432  * Dynamically redirect all pkts from a specific interface
2433  * to the specified node
2434  */
2435 static void
2436 ixge_set_interface_next_node (vnet_main_t * vnm, u32 hw_if_index,
2437                               u32 node_index)
2438 {
2439   ixge_main_t *xm = &ixge_main;
2440   vnet_hw_interface_t *hw = vnet_get_hw_interface (vnm, hw_if_index);
2441   ixge_device_t *xd = vec_elt_at_index (xm->devices, hw->dev_instance);
2442
2443   /* Shut off redirection */
2444   if (node_index == ~0)
2445     {
2446       xd->per_interface_next_index = node_index;
2447       return;
2448     }
2449
2450   xd->per_interface_next_index =
2451     vlib_node_add_next (xm->vlib_main, ixge_input_node.index, node_index);
2452 }
2453
2454
2455 /* *INDENT-OFF* */
2456 VNET_DEVICE_CLASS (ixge_device_class) = {
2457   .name = "ixge",
2458   .tx_function = ixge_interface_tx,
2459   .format_device_name = format_ixge_device_name,
2460   .format_device = format_ixge_device,
2461   .format_tx_trace = format_ixge_tx_dma_trace,
2462   .clear_counters = ixge_clear_hw_interface_counters,
2463   .admin_up_down_function = ixge_interface_admin_up_down,
2464   .rx_redirect_to_node = ixge_set_interface_next_node,
2465 };
2466 /* *INDENT-ON* */
2467
2468 #define IXGE_N_BYTES_IN_RX_BUFFER  (2048)       // DAW-HACK: Set Rx buffer size so all packets < ETH_MTU_SIZE fit in the buffer (i.e. sop & eop for all descriptors).
2469
2470 static clib_error_t *
2471 ixge_dma_init (ixge_device_t * xd, vlib_rx_or_tx_t rt, u32 queue_index)
2472 {
2473   ixge_main_t *xm = &ixge_main;
2474   vlib_main_t *vm = xm->vlib_main;
2475   ixge_dma_queue_t *dq;
2476   clib_error_t *error = 0;
2477
2478   vec_validate (xd->dma_queues[rt], queue_index);
2479   dq = vec_elt_at_index (xd->dma_queues[rt], queue_index);
2480
2481   if (!xm->n_descriptors_per_cache_line)
2482     xm->n_descriptors_per_cache_line =
2483       CLIB_CACHE_LINE_BYTES / sizeof (dq->descriptors[0]);
2484
2485   if (!xm->n_bytes_in_rx_buffer)
2486     xm->n_bytes_in_rx_buffer = IXGE_N_BYTES_IN_RX_BUFFER;
2487   xm->n_bytes_in_rx_buffer = round_pow2 (xm->n_bytes_in_rx_buffer, 1024);
2488
2489   if (!xm->n_descriptors[rt])
2490     xm->n_descriptors[rt] = 4 * VLIB_FRAME_SIZE;
2491
2492   dq->queue_index = queue_index;
2493   dq->n_descriptors =
2494     round_pow2 (xm->n_descriptors[rt], xm->n_descriptors_per_cache_line);
2495   dq->head_index = dq->tail_index = 0;
2496
2497   dq->descriptors =
2498     vlib_physmem_alloc_aligned (vm, xm->physmem_region, &error,
2499                                 dq->n_descriptors *
2500                                 sizeof (dq->descriptors[0]),
2501                                 128 /* per chip spec */ );
2502   if (error)
2503     return error;
2504
2505   memset (dq->descriptors, 0,
2506           dq->n_descriptors * sizeof (dq->descriptors[0]));
2507   vec_resize (dq->descriptor_buffer_indices, dq->n_descriptors);
2508
2509   if (rt == VLIB_RX)
2510     {
2511       u32 n_alloc, i;
2512
2513       n_alloc = vlib_buffer_alloc (vm, dq->descriptor_buffer_indices,
2514                                    vec_len (dq->descriptor_buffer_indices));
2515       ASSERT (n_alloc == vec_len (dq->descriptor_buffer_indices));
2516       for (i = 0; i < n_alloc; i++)
2517         {
2518           dq->descriptors[i].rx_to_hw.tail_address =
2519             vlib_get_buffer_data_physical_address (vm,
2520                                                    dq->descriptor_buffer_indices
2521                                                    [i]);
2522         }
2523     }
2524   else
2525     {
2526       u32 i;
2527
2528       dq->tx.head_index_write_back = vlib_physmem_alloc (vm,
2529                                                          xm->physmem_region,
2530                                                          &error,
2531                                                          CLIB_CACHE_LINE_BYTES);
2532
2533       for (i = 0; i < dq->n_descriptors; i++)
2534         dq->descriptors[i].tx = xm->tx_descriptor_template;
2535
2536       vec_validate (xm->tx_buffers_pending_free, dq->n_descriptors - 1);
2537     }
2538
2539   {
2540     ixge_dma_regs_t *dr = get_dma_regs (xd, rt, queue_index);
2541     u64 a;
2542
2543     a =
2544       vlib_physmem_virtual_to_physical (vm, xm->physmem_region,
2545                                         dq->descriptors);
2546     dr->descriptor_address[0] = a & 0xFFFFFFFF;
2547     dr->descriptor_address[1] = a >> (u64) 32;
2548     dr->n_descriptor_bytes = dq->n_descriptors * sizeof (dq->descriptors[0]);
2549     dq->head_index = dq->tail_index = 0;
2550
2551     if (rt == VLIB_RX)
2552       {
2553         ASSERT ((xm->n_bytes_in_rx_buffer / 1024) < 32);
2554         dr->rx_split_control =
2555           ( /* buffer size */ ((xm->n_bytes_in_rx_buffer / 1024) << 0)
2556            | (                  /* lo free descriptor threshold (units of 64 descriptors) */
2557                (1 << 22)) | (   /* descriptor type: advanced one buffer */
2558                               (1 << 25)) | (    /* drop if no descriptors available */
2559                                              (1 << 28)));
2560
2561         /* Give hardware all but last 16 cache lines' worth of descriptors. */
2562         dq->tail_index = dq->n_descriptors -
2563           16 * xm->n_descriptors_per_cache_line;
2564       }
2565     else
2566       {
2567         /* Make sure its initialized before hardware can get to it. */
2568         dq->tx.head_index_write_back[0] = dq->head_index;
2569
2570         a = vlib_physmem_virtual_to_physical (vm, xm->physmem_region,
2571                                               dq->tx.head_index_write_back);
2572         dr->tx.head_index_write_back_address[0] = /* enable bit */ 1 | a;
2573         dr->tx.head_index_write_back_address[1] = (u64) a >> (u64) 32;
2574       }
2575
2576     /* DMA on 82599 does not work with [13] rx data write relaxed ordering
2577        and [12] undocumented set. */
2578     if (rt == VLIB_RX)
2579       dr->dca_control &= ~((1 << 13) | (1 << 12));
2580
2581     CLIB_MEMORY_BARRIER ();
2582
2583     if (rt == VLIB_TX)
2584       {
2585         xd->regs->tx_dma_control |= (1 << 0);
2586         dr->control |= ((32 << 0)       /* prefetch threshold */
2587                         | (64 << 8)     /* host threshold */
2588                         | (0 << 16) /* writeback threshold */ );
2589       }
2590
2591     /* Enable this queue and wait for hardware to initialize
2592        before adding to tail. */
2593     if (rt == VLIB_TX)
2594       {
2595         dr->control |= 1 << 25;
2596         while (!(dr->control & (1 << 25)))
2597           ;
2598       }
2599
2600     /* Set head/tail indices and enable DMA. */
2601     dr->head_index = dq->head_index;
2602     dr->tail_index = dq->tail_index;
2603   }
2604
2605   return error;
2606 }
2607
2608 static u32
2609 ixge_flag_change (vnet_main_t * vnm, vnet_hw_interface_t * hw, u32 flags)
2610 {
2611   ixge_device_t *xd;
2612   ixge_regs_t *r;
2613   u32 old;
2614   ixge_main_t *xm = &ixge_main;
2615
2616   xd = vec_elt_at_index (xm->devices, hw->dev_instance);
2617   r = xd->regs;
2618
2619   old = r->filter_control;
2620
2621   if (flags & ETHERNET_INTERFACE_FLAG_ACCEPT_ALL)
2622     r->filter_control = old | (1 << 9) /* unicast promiscuous */ ;
2623   else
2624     r->filter_control = old & ~(1 << 9);
2625
2626   return old;
2627 }
2628
2629 static void
2630 ixge_device_init (ixge_main_t * xm)
2631 {
2632   vnet_main_t *vnm = vnet_get_main ();
2633   ixge_device_t *xd;
2634
2635   /* Reset chip(s). */
2636   vec_foreach (xd, xm->devices)
2637   {
2638     ixge_regs_t *r = xd->regs;
2639     const u32 reset_bit = (1 << 26) | (1 << 3);
2640
2641     r->control |= reset_bit;
2642
2643     /* No need to suspend.  Timed to take ~1e-6 secs */
2644     while (r->control & reset_bit)
2645       ;
2646
2647     /* Software loaded. */
2648     r->extended_control |= (1 << 28);
2649
2650     ixge_phy_init (xd);
2651
2652     /* Register ethernet interface. */
2653     {
2654       u8 addr8[6];
2655       u32 i, addr32[2];
2656       clib_error_t *error;
2657
2658       addr32[0] = r->rx_ethernet_address0[0][0];
2659       addr32[1] = r->rx_ethernet_address0[0][1];
2660       for (i = 0; i < 6; i++)
2661         addr8[i] = addr32[i / 4] >> ((i % 4) * 8);
2662
2663       error = ethernet_register_interface
2664         (vnm, ixge_device_class.index, xd->device_index,
2665          /* ethernet address */ addr8,
2666          &xd->vlib_hw_if_index, ixge_flag_change);
2667       if (error)
2668         clib_error_report (error);
2669     }
2670
2671     {
2672       vnet_sw_interface_t *sw =
2673         vnet_get_hw_sw_interface (vnm, xd->vlib_hw_if_index);
2674       xd->vlib_sw_if_index = sw->sw_if_index;
2675     }
2676
2677     ixge_dma_init (xd, VLIB_RX, /* queue_index */ 0);
2678
2679     xm->n_descriptors[VLIB_TX] = 20 * VLIB_FRAME_SIZE;
2680
2681     ixge_dma_init (xd, VLIB_TX, /* queue_index */ 0);
2682
2683     /* RX/TX queue 0 gets mapped to interrupt bits 0 & 8. */
2684     r->interrupt.queue_mapping[0] = (( /* valid bit */ (1 << 7) |
2685                                       ixge_rx_queue_to_interrupt (0)) << 0);
2686
2687     r->interrupt.queue_mapping[0] |= (( /* valid bit */ (1 << 7) |
2688                                        ixge_tx_queue_to_interrupt (0)) << 8);
2689
2690     /* No use in getting too many interrupts.
2691        Limit them to one every 3/4 ring size at line rate
2692        min sized packets.
2693        No need for this since kernel/vlib main loop provides adequate interrupt
2694        limiting scheme. */
2695     if (0)
2696       {
2697         f64 line_rate_max_pps =
2698           10e9 / (8 * (64 + /* interframe padding */ 20));
2699         ixge_throttle_queue_interrupt (r, 0,
2700                                        .75 * xm->n_descriptors[VLIB_RX] /
2701                                        line_rate_max_pps);
2702       }
2703
2704     /* Accept all multicast and broadcast packets. Should really add them
2705        to the dst_ethernet_address register array. */
2706     r->filter_control |= (1 << 10) | (1 << 8);
2707
2708     /* Enable frames up to size in mac frame size register. */
2709     r->xge_mac.control |= 1 << 2;
2710     r->xge_mac.rx_max_frame_size = (9216 + 14) << 16;
2711
2712     /* Enable all interrupts. */
2713     if (!IXGE_ALWAYS_POLL)
2714       r->interrupt.enable_write_1_to_set = ~0;
2715   }
2716 }
2717
2718 static uword
2719 ixge_process (vlib_main_t * vm, vlib_node_runtime_t * rt, vlib_frame_t * f)
2720 {
2721   vnet_main_t *vnm = vnet_get_main ();
2722   ixge_main_t *xm = &ixge_main;
2723   ixge_device_t *xd;
2724   uword event_type, *event_data = 0;
2725   f64 timeout, link_debounce_deadline;
2726
2727   ixge_device_init (xm);
2728
2729   /* Clear all counters. */
2730   vec_foreach (xd, xm->devices)
2731   {
2732     ixge_update_counters (xd);
2733     memset (xd->counters, 0, sizeof (xd->counters));
2734   }
2735
2736   timeout = 30.0;
2737   link_debounce_deadline = 1e70;
2738
2739   while (1)
2740     {
2741       /* 36 bit stat counters could overflow in ~50 secs.
2742          We poll every 30 secs to be conservative. */
2743       vlib_process_wait_for_event_or_clock (vm, timeout);
2744
2745       event_type = vlib_process_get_events (vm, &event_data);
2746
2747       switch (event_type)
2748         {
2749         case EVENT_SET_FLAGS:
2750           /* 1 ms */
2751           link_debounce_deadline = vlib_time_now (vm) + 1e-3;
2752           timeout = 1e-3;
2753           break;
2754
2755         case ~0:
2756           /* No events found: timer expired. */
2757           if (vlib_time_now (vm) > link_debounce_deadline)
2758             {
2759               vec_foreach (xd, xm->devices)
2760               {
2761                 ixge_regs_t *r = xd->regs;
2762                 u32 v = r->xge_mac.link_status;
2763                 uword is_up = (v & (1 << 30)) != 0;
2764
2765                 vnet_hw_interface_set_flags
2766                   (vnm, xd->vlib_hw_if_index,
2767                    is_up ? VNET_HW_INTERFACE_FLAG_LINK_UP : 0);
2768               }
2769               link_debounce_deadline = 1e70;
2770               timeout = 30.0;
2771             }
2772           break;
2773
2774         default:
2775           ASSERT (0);
2776         }
2777
2778       if (event_data)
2779         _vec_len (event_data) = 0;
2780
2781       /* Query stats every 30 secs. */
2782       {
2783         f64 now = vlib_time_now (vm);
2784         if (now - xm->time_last_stats_update > 30)
2785           {
2786             xm->time_last_stats_update = now;
2787             vec_foreach (xd, xm->devices) ixge_update_counters (xd);
2788           }
2789       }
2790     }
2791
2792   return 0;
2793 }
2794
2795 static vlib_node_registration_t ixge_process_node = {
2796   .function = ixge_process,
2797   .type = VLIB_NODE_TYPE_PROCESS,
2798   .name = "ixge-process",
2799 };
2800
2801 clib_error_t *
2802 ixge_init (vlib_main_t * vm)
2803 {
2804   ixge_main_t *xm = &ixge_main;
2805   clib_error_t *error;
2806
2807   xm->vlib_main = vm;
2808   memset (&xm->tx_descriptor_template, 0,
2809           sizeof (xm->tx_descriptor_template));
2810   memset (&xm->tx_descriptor_template_mask, 0,
2811           sizeof (xm->tx_descriptor_template_mask));
2812   xm->tx_descriptor_template.status0 =
2813     (IXGE_TX_DESCRIPTOR_STATUS0_ADVANCED |
2814      IXGE_TX_DESCRIPTOR_STATUS0_IS_ADVANCED |
2815      IXGE_TX_DESCRIPTOR_STATUS0_INSERT_FCS);
2816   xm->tx_descriptor_template_mask.status0 = 0xffff;
2817   xm->tx_descriptor_template_mask.status1 = 0x00003fff;
2818
2819   xm->tx_descriptor_template_mask.status0 &=
2820     ~(IXGE_TX_DESCRIPTOR_STATUS0_IS_END_OF_PACKET
2821       | IXGE_TX_DESCRIPTOR_STATUS0_REPORT_STATUS);
2822   xm->tx_descriptor_template_mask.status1 &=
2823     ~(IXGE_TX_DESCRIPTOR_STATUS1_DONE);
2824
2825   error = vlib_call_init_function (vm, pci_bus_init);
2826
2827   return error;
2828 }
2829
2830 VLIB_INIT_FUNCTION (ixge_init);
2831
2832
2833 static void
2834 ixge_pci_intr_handler (vlib_pci_dev_handle_t h)
2835 {
2836   ixge_main_t *xm = &ixge_main;
2837   vlib_main_t *vm = xm->vlib_main;
2838   uword private_data = vlib_pci_get_private_data (h);
2839
2840   vlib_node_set_interrupt_pending (vm, ixge_input_node.index);
2841
2842   /* Let node know which device is interrupting. */
2843   {
2844     vlib_node_runtime_t *rt =
2845       vlib_node_get_runtime (vm, ixge_input_node.index);
2846     rt->runtime_data[0] |= 1 << private_data;
2847   }
2848 }
2849
2850 static clib_error_t *
2851 ixge_pci_init (vlib_main_t * vm, vlib_pci_dev_handle_t h)
2852 {
2853   ixge_main_t *xm = &ixge_main;
2854   clib_error_t *error = 0;
2855   void *r;
2856   ixge_device_t *xd;
2857   vlib_pci_addr_t *addr = vlib_pci_get_addr (h);
2858   vlib_pci_device_info_t *d = vlib_pci_get_device_info (addr, 0);
2859
2860   /* Allocate physmem region for DMA buffers */
2861   if (xm->physmem_region_allocated == 0)
2862     {
2863       error = vlib_physmem_region_alloc (vm, "ixge decriptors", 2 << 20, 0,
2864                                          VLIB_PHYSMEM_F_INIT_MHEAP,
2865                                          &xm->physmem_region);
2866       xm->physmem_region_allocated = 1;
2867     }
2868   if (error)
2869     return error;
2870
2871   error = vlib_pci_map_resource (h, 0, &r);
2872   if (error)
2873     return error;
2874
2875   vec_add2 (xm->devices, xd, 1);
2876
2877   if (vec_len (xm->devices) == 1)
2878     {
2879       ixge_input_node.function = ixge_input_multiarch_select ();
2880     }
2881
2882   xd->pci_dev_handle = h;
2883   xd->device_id = d->device_id;
2884   xd->regs = r;
2885   xd->device_index = xd - xm->devices;
2886   xd->pci_function = addr->function;
2887   xd->per_interface_next_index = ~0;
2888
2889   vlib_pci_set_private_data (h, xd->device_index);
2890
2891   /* Chip found so enable node. */
2892   {
2893     vlib_node_set_state (vm, ixge_input_node.index,
2894                          (IXGE_ALWAYS_POLL
2895                           ? VLIB_NODE_STATE_POLLING
2896                           : VLIB_NODE_STATE_INTERRUPT));
2897
2898     //dev->private_data = xd->device_index;
2899   }
2900
2901   if (vec_len (xm->devices) == 1)
2902     {
2903       vlib_register_node (vm, &ixge_process_node);
2904       xm->process_node_index = ixge_process_node.index;
2905     }
2906
2907   error = vlib_pci_bus_master_enable (h);
2908
2909   if (error)
2910     return error;
2911
2912   return vlib_pci_intr_enable (h);
2913 }
2914
2915 /* *INDENT-OFF* */
2916 PCI_REGISTER_DEVICE (ixge_pci_device_registration,static) = {
2917   .init_function = ixge_pci_init,
2918   .interrupt_handler = ixge_pci_intr_handler,
2919   .supported_devices = {
2920 #define _(t,i) { .vendor_id = PCI_VENDOR_ID_INTEL, .device_id = i, },
2921     foreach_ixge_pci_device_id
2922 #undef _
2923     { 0 },
2924   },
2925 };
2926 /* *INDENT-ON* */
2927
2928 void
2929 ixge_set_next_node (ixge_rx_next_t next, char *name)
2930 {
2931   vlib_node_registration_t *r = &ixge_input_node;
2932
2933   switch (next)
2934     {
2935     case IXGE_RX_NEXT_IP4_INPUT:
2936     case IXGE_RX_NEXT_IP6_INPUT:
2937     case IXGE_RX_NEXT_ETHERNET_INPUT:
2938       r->next_nodes[next] = name;
2939       break;
2940
2941     default:
2942       clib_warning ("%s: illegal next %d\n", __FUNCTION__, next);
2943       break;
2944     }
2945 }
2946
2947 /* *INDENT-OFF* */
2948 VLIB_PLUGIN_REGISTER () = {
2949     .version = VPP_BUILD_VER,
2950     .default_disabled = 1,
2951     .description = "Intel 82599 Family Native Driver (experimental)",
2952 };
2953 #endif
2954
2955 /* *INDENT-ON* */
2956
2957 /*
2958  * fd.io coding-style-patch-verification: ON
2959  *
2960  * Local Variables:
2961  * eval: (c-set-style "gnu")
2962  * End:
2963  */