IPv6 HBH: Refactor code. Separate out RFC2460 HBH handling and the more experimental
[vpp.git] / dpdk / dpdk-16.04_patches / 0016-enic-scatter-rx.patch
1 diff -r -u dpdk-16.04.orig2/drivers/net/enic/base/rq_enet_desc.h dpdk-16.04/drivers/net/enic/base/rq_enet_desc.h
2 --- dpdk-16.04.orig2/drivers/net/enic/base/rq_enet_desc.h       2016-05-13 18:09:07.523938072 -0700
3 +++ dpdk-16.04/drivers/net/enic/base/rq_enet_desc.h     2016-05-13 18:09:54.359743075 -0700
4 @@ -55,7 +55,7 @@
5  #define RQ_ENET_TYPE_BITS              2
6  #define RQ_ENET_TYPE_MASK              ((1 << RQ_ENET_TYPE_BITS) - 1)
7  
8 -static inline void rq_enet_desc_enc(struct rq_enet_desc *desc,
9 +static inline void rq_enet_desc_enc(volatile struct rq_enet_desc *desc,
10         u64 address, u8 type, u16 length)
11  {
12         desc->address = cpu_to_le64(address);
13 diff -r -u dpdk-16.04.orig2/drivers/net/enic/base/vnic_rq.c dpdk-16.04/drivers/net/enic/base/vnic_rq.c
14 --- dpdk-16.04.orig2/drivers/net/enic/base/vnic_rq.c    2016-05-13 18:09:07.533938883 -0700
15 +++ dpdk-16.04/drivers/net/enic/base/vnic_rq.c  2016-05-13 18:09:54.360743158 -0700
16 @@ -84,11 +84,16 @@
17         iowrite32(cq_index, &rq->ctrl->cq_index);
18         iowrite32(error_interrupt_enable, &rq->ctrl->error_interrupt_enable);
19         iowrite32(error_interrupt_offset, &rq->ctrl->error_interrupt_offset);
20 -       iowrite32(0, &rq->ctrl->dropped_packet_count);
21         iowrite32(0, &rq->ctrl->error_status);
22         iowrite32(fetch_index, &rq->ctrl->fetch_index);
23         iowrite32(posted_index, &rq->ctrl->posted_index);
24 -
25 +       if (rq->is_sop) {
26 +//             printf("Writing 0x%x to %s rq\n",
27 +//                    ((rq->is_sop << 10) | rq->data_queue_idx),
28 +//                    rq->is_sop ? "sop":"data");
29 +               iowrite32(((rq->is_sop << 10) | rq->data_queue_idx),
30 +                         &rq->ctrl->data_ring);
31 +       }
32  }
33  
34  void vnic_rq_init(struct vnic_rq *rq, unsigned int cq_index,
35 @@ -96,6 +101,7 @@
36         unsigned int error_interrupt_offset)
37  {
38         u32 fetch_index = 0;
39 +
40         /* Use current fetch_index as the ring starting point */
41         fetch_index = ioread32(&rq->ctrl->fetch_index);
42  
43 @@ -110,6 +116,8 @@
44                 error_interrupt_offset);
45         rq->rxst_idx = 0;
46         rq->tot_pkts = 0;
47 +       rq->pkt_first_seg = NULL;
48 +       rq->pkt_last_seg = NULL;
49  }
50  
51  void vnic_rq_error_out(struct vnic_rq *rq, unsigned int error)
52 diff -r -u dpdk-16.04.orig2/drivers/net/enic/base/vnic_rq.h dpdk-16.04/drivers/net/enic/base/vnic_rq.h
53 --- dpdk-16.04.orig2/drivers/net/enic/base/vnic_rq.h    2016-05-13 18:09:07.540939452 -0700
54 +++ dpdk-16.04/drivers/net/enic/base/vnic_rq.h  2016-05-13 18:09:54.362743322 -0700
55 @@ -60,10 +60,18 @@
56         u32 pad7;
57         u32 error_status;               /* 0x48 */
58         u32 pad8;
59 -       u32 dropped_packet_count;       /* 0x50 */
60 +       u32 tcp_sn;                     /* 0x50 */
61         u32 pad9;
62 -       u32 dropped_packet_count_rc;    /* 0x58 */
63 +       u32 unused;                     /* 0x58 */
64         u32 pad10;
65 +       u32 dca_select;                 /* 0x60 */
66 +       u32 pad11;
67 +       u32 dca_value;                  /* 0x68 */
68 +       u32 pad12;
69 +       u32 data_ring;                  /* 0x70 */
70 +       u32 pad13;
71 +       u32 header_split;               /* 0x78 */
72 +       u32 pad14;
73  };
74  
75  struct vnic_rq {
76 @@ -82,6 +90,12 @@
77         struct rte_mempool *mp;
78         uint16_t rxst_idx;
79         uint32_t tot_pkts;
80 +       uint16_t data_queue_idx;
81 +       uint8_t is_sop;
82 +       uint8_t in_use;
83 +       struct rte_mbuf *pkt_first_seg;
84 +       struct rte_mbuf *pkt_last_seg;
85 +       unsigned int max_mbufs_per_pkt;
86  };
87  
88  static inline unsigned int vnic_rq_desc_avail(struct vnic_rq *rq)
89 diff -r -u dpdk-16.04.orig2/drivers/net/enic/enic.h dpdk-16.04/drivers/net/enic/enic.h
90 --- dpdk-16.04.orig2/drivers/net/enic/enic.h    2016-05-13 18:09:07.553940507 -0700
91 +++ dpdk-16.04/drivers/net/enic/enic.h  2016-05-13 18:09:54.365743565 -0700
92 @@ -142,6 +142,16 @@
93         struct enic_soft_stats soft_stats;
94  };
95  
96 +static inline unsigned int enic_sop_rq(__rte_unused struct enic *enic, unsigned int rq)
97 +{
98 +       return rq * 2;
99 +}
100 +
101 +static inline unsigned int enic_data_rq(__rte_unused struct enic *enic, unsigned int rq)
102 +{
103 +       return rq * 2 + 1;
104 +}
105 +
106  static inline unsigned int enic_cq_rq(__rte_unused struct enic *enic, unsigned int rq)
107  {
108         return rq;
109 diff -r -u dpdk-16.04.orig2/drivers/net/enic/enic_main.c dpdk-16.04/drivers/net/enic/enic_main.c
110 --- dpdk-16.04.orig2/drivers/net/enic/enic_main.c       2016-05-13 18:09:07.557940834 -0700
111 +++ dpdk-16.04/drivers/net/enic/enic_main.c     2016-05-13 18:10:40.099459001 -0700
112 @@ -248,15 +248,23 @@
113         unsigned int error_interrupt_offset = 0;
114         unsigned int index = 0;
115         unsigned int cq_idx;
116 +       struct vnic_rq *data_rq;
117  
118         vnic_dev_stats_clear(enic->vdev);
119  
120         for (index = 0; index < enic->rq_count; index++) {
121 -               vnic_rq_init(&enic->rq[index],
122 +               vnic_rq_init(&enic->rq[enic_sop_rq(enic, index)],
123                         enic_cq_rq(enic, index),
124                         error_interrupt_enable,
125                         error_interrupt_offset);
126  
127 +               data_rq = &enic->rq[enic_data_rq(enic, index)];
128 +               if (data_rq->in_use) 
129 +                       vnic_rq_init(data_rq,
130 +                                    enic_cq_rq(enic, index),
131 +                                    error_interrupt_enable,
132 +                                    error_interrupt_offset);
133 +
134                 cq_idx = enic_cq_rq(enic, index);
135                 vnic_cq_init(&enic->cq[cq_idx],
136                         0 /* flow_control_enable */,
137 @@ -306,6 +314,9 @@
138         unsigned i;
139         dma_addr_t dma_addr;
140  
141 +       if (!rq->in_use)
142 +               return 0;
143 +
144         dev_debug(enic, "queue %u, allocating %u rx queue mbufs\n", rq->index,
145                   rq->ring.desc_count);
146  
147 @@ -317,20 +328,20 @@
148                         return -ENOMEM;
149                 }
150  
151 -               dma_addr = (dma_addr_t)(mb->buf_physaddr
152 -                          + RTE_PKTMBUF_HEADROOM);
153 -
154 -               rq_enet_desc_enc(rqd, dma_addr, RQ_ENET_TYPE_ONLY_SOP,
155 -                                mb->buf_len - RTE_PKTMBUF_HEADROOM);
156 +               dma_addr = (dma_addr_t)(mb->buf_physaddr + RTE_PKTMBUF_HEADROOM);
157 +               rq_enet_desc_enc(rqd, dma_addr,
158 +                               (rq->is_sop ? RQ_ENET_TYPE_ONLY_SOP
159 +                               : RQ_ENET_TYPE_NOT_SOP),
160 +                               mb->buf_len - RTE_PKTMBUF_HEADROOM);
161                 rq->mbuf_ring[i] = mb;
162         }
163  
164         /* make sure all prior writes are complete before doing the PIO write */
165         rte_rmb();
166  
167 -       /* Post all but the last 2 cache lines' worth of descriptors */
168 -       rq->posted_index = rq->ring.desc_count - (2 * RTE_CACHE_LINE_SIZE
169 -                       / sizeof(struct rq_enet_desc));
170 +       /* Post all but the last buffer to VIC. */
171 +       rq->posted_index = rq->ring.desc_count - 1;
172 +
173         rq->rx_nb_hold = 0;
174  
175         dev_debug(enic, "port=%u, qidx=%u, Write %u posted idx, %u sw held\n",
176 @@ -338,6 +349,8 @@
177         iowrite32(rq->posted_index, &rq->ctrl->posted_index);
178         rte_rmb();
179  
180 +//     printf("posted %d buffers to %s rq\n", rq->ring.desc_count,
181 +//            rq->is_sop ? "sop" : "data");
182         return 0;
183  
184  }
185 @@ -399,17 +412,25 @@
186                         "Flow director feature will not work\n");
187  
188         for (index = 0; index < enic->rq_count; index++) {
189 -               err = enic_alloc_rx_queue_mbufs(enic, &enic->rq[index]);
190 +               err = enic_alloc_rx_queue_mbufs(enic, &enic->rq[enic_sop_rq(enic, index)]);
191                 if (err) {
192 -                       dev_err(enic, "Failed to alloc RX queue mbufs\n");
193 +                       dev_err(enic, "Failed to alloc sop RX queue mbufs\n");
194 +                       return err;
195 +               }
196 +               err = enic_alloc_rx_queue_mbufs(enic, &enic->rq[enic_data_rq(enic, index)]);
197 +               if (err) {
198 +                       /* release the previously allocated mbufs for the sop rq */
199 +                       enic_rxmbuf_queue_release(enic, &enic->rq[enic_sop_rq(enic, index)]);
200 +
201 +                       dev_err(enic, "Failed to alloc data RX queue mbufs\n");
202                         return err;
203                 }
204         }
205  
206         for (index = 0; index < enic->wq_count; index++)
207 -               vnic_wq_enable(&enic->wq[index]);
208 +               enic_start_wq(enic, index);
209         for (index = 0; index < enic->rq_count; index++)
210 -               vnic_rq_enable(&enic->rq[index]);
211 +               enic_start_rq(enic, index);
212  
213         vnic_dev_enable_wait(enic->vdev);
214  
215 @@ -441,14 +462,26 @@
216  
217  void enic_free_rq(void *rxq)
218  {
219 -       struct vnic_rq *rq = (struct vnic_rq *)rxq;
220 -       struct enic *enic = vnic_dev_priv(rq->vdev);
221 +       struct vnic_rq *rq_sop = (struct vnic_rq *)rxq;
222 +       struct enic *enic = vnic_dev_priv(rq_sop->vdev);
223 +       struct vnic_rq *rq_data = &enic->rq[rq_sop->data_queue_idx];
224 +
225 +       enic_rxmbuf_queue_release(enic, rq_sop);
226 +       if (rq_data->in_use)
227 +               enic_rxmbuf_queue_release(enic, rq_data);
228 +
229 +       rte_free(rq_sop->mbuf_ring);
230 +       if (rq_data->in_use)
231 +               rte_free(rq_data->mbuf_ring);
232 +
233 +       rq_sop->mbuf_ring = NULL;
234 +       rq_data->mbuf_ring = NULL;
235 +
236 +       vnic_rq_free(rq_sop);
237 +       if (rq_data->in_use)
238 +               vnic_rq_free(rq_data);
239  
240 -       enic_rxmbuf_queue_release(enic, rq);
241 -       rte_free(rq->mbuf_ring);
242 -       rq->mbuf_ring = NULL;
243 -       vnic_rq_free(rq);
244 -       vnic_cq_free(&enic->cq[rq->index]);
245 +       vnic_cq_free(&enic->cq[rq_sop->index]);
246  }
247  
248  void enic_start_wq(struct enic *enic, uint16_t queue_idx)
249 @@ -463,12 +496,32 @@
250  
251  void enic_start_rq(struct enic *enic, uint16_t queue_idx)
252  {
253 -       vnic_rq_enable(&enic->rq[queue_idx]);
254 +       struct vnic_rq *rq_sop = &enic->rq[enic_sop_rq(enic, queue_idx)];
255 +       struct vnic_rq *rq_data = &enic->rq[rq_sop->data_queue_idx];
256 +
257 +       if (rq_data->in_use)
258 +               vnic_rq_enable(rq_data);
259 +       rte_mb();
260 +       vnic_rq_enable(rq_sop);
261 +
262  }
263  
264  int enic_stop_rq(struct enic *enic, uint16_t queue_idx)
265  {
266 -       return vnic_rq_disable(&enic->rq[queue_idx]);
267 +       int ret1 = 0, ret2 = 0;
268 +
269 +       struct vnic_rq *rq_sop = &enic->rq[enic_sop_rq(enic, queue_idx)];
270 +       struct vnic_rq *rq_data = &enic->rq[rq_sop->data_queue_idx];
271 +
272 +       ret2 = vnic_rq_disable(rq_sop);
273 +       rte_mb();
274 +       if (rq_data->in_use) 
275 +               ret1 = vnic_rq_disable(rq_data);
276 +
277 +       if (ret2)
278 +               return ret2;
279 +       else
280 +               return ret1;
281  }
282  
283  int enic_alloc_rq(struct enic *enic, uint16_t queue_idx,
284 @@ -476,53 +529,128 @@
285         uint16_t nb_desc)
286  {
287         int rc;
288 -       struct vnic_rq *rq = &enic->rq[queue_idx];
289 -
290 -       rq->socket_id = socket_id;
291 -       rq->mp = mp;
292 +       uint16_t sop_queue_idx = enic_sop_rq(enic, queue_idx);
293 +       uint16_t data_queue_idx = enic_data_rq(enic, queue_idx);
294 +       struct vnic_rq *rq_sop = &enic->rq[sop_queue_idx];
295 +       struct vnic_rq *rq_data = &enic->rq[data_queue_idx];
296 +       unsigned int mbuf_size, mbufs_per_pkt;
297 +       unsigned int nb_sop_desc, nb_data_desc;
298 +       uint16_t min_sop, max_sop, min_data, max_data;
299 +
300 +       rq_sop->is_sop = 1;
301 +       rq_sop->data_queue_idx = data_queue_idx;
302 +       rq_data->is_sop = 0;
303 +       rq_data->data_queue_idx = 0;
304 +       rq_sop->socket_id = socket_id;
305 +       rq_sop->mp = mp;
306 +       rq_data->socket_id = socket_id;
307 +       rq_data->mp = mp;
308 +       rq_sop->in_use = 1;
309 +
310 +       mbuf_size = (uint16_t)(rte_pktmbuf_data_room_size(mp) - RTE_PKTMBUF_HEADROOM);
311 +
312 +       /* ceil(mtu/mbuf_size) */
313 +       mbufs_per_pkt = (enic->config.mtu + (mbuf_size - 1)) / mbuf_size;
314 +
315 +       if (mbufs_per_pkt > 1)
316 +               rq_data->in_use = 1;
317 +       else
318 +               rq_data->in_use = 0;
319 +
320 +       /* number of descriptors have to be a multiple of 32 */
321 +       nb_sop_desc = (nb_desc / mbufs_per_pkt) & ~0x1F;
322 +       nb_data_desc = (nb_desc - nb_sop_desc) & ~0x1F;
323 +
324 +       rq_sop->max_mbufs_per_pkt = mbufs_per_pkt;
325 +       rq_data->max_mbufs_per_pkt = mbufs_per_pkt;
326 +
327 +       //printf("mtu = %u, mbuf_size = %u, mbuf_per_pkt = %u\n",
328 +       //       enic->config.mtu, mbuf_size, mbufs_per_pkt);
329 +
330 +       if (mbufs_per_pkt > 1) {
331 +               min_sop = 64;
332 +               max_sop = ((enic->config.rq_desc_count / (mbufs_per_pkt - 1)) & ~0x1F);
333 +               min_data = min_sop * (mbufs_per_pkt - 1);
334 +               max_data = enic->config.rq_desc_count;
335 +       } else {
336 +               min_sop = 64;
337 +               max_sop = enic->config.rq_desc_count;
338 +               min_data = 0;
339 +               max_data = 0;
340 +       }
341  
342 -       if (nb_desc) {
343 -               if (nb_desc > enic->config.rq_desc_count) {
344 -                       dev_warning(enic,
345 -                               "RQ %d - number of rx desc in cmd line (%d)"\
346 -                               "is greater than that in the UCSM/CIMC adapter"\
347 -                               "policy.  Applying the value in the adapter "\
348 -                               "policy (%d).\n",
349 -                               queue_idx, nb_desc, enic->config.rq_desc_count);
350 -                       nb_desc = enic->config.rq_desc_count;
351 -               }
352 -               dev_info(enic, "RX Queues - effective number of descs:%d\n",
353 -                        nb_desc);
354 +       if (nb_desc < (min_sop + min_data)) {
355 +               dev_warning(enic,
356 +                           "Number of rx descs too low, adjusting to minimum\n");
357 +               nb_sop_desc = min_sop;
358 +               nb_data_desc = min_data;
359 +       } else if (nb_desc > (max_sop + max_data)){
360 +               dev_warning(enic,
361 +                           "Number of rx_descs too high, adjusting to maximum\n");
362 +               nb_sop_desc = max_sop;
363 +               nb_data_desc = max_data;
364         }
365 +       dev_info(enic, "For mtu %d and mbuf size %d valid rx descriptor range is %d to %d\n",
366 +                enic->config.mtu, mbuf_size, min_sop + min_data, max_sop + max_data);
367 +
368 +       dev_info(enic, "Using %d rx descriptors (sop %d, data %d)\n",
369 +                nb_sop_desc + nb_data_desc, nb_sop_desc, nb_data_desc);
370  
371 -       /* Allocate queue resources */
372 -       rc = vnic_rq_alloc(enic->vdev, rq, queue_idx,
373 -               nb_desc, sizeof(struct rq_enet_desc));
374 +       /* Allocate sop queue resources */
375 +       rc = vnic_rq_alloc(enic->vdev, rq_sop, sop_queue_idx,
376 +               nb_sop_desc, sizeof(struct rq_enet_desc));
377         if (rc) {
378 -               dev_err(enic, "error in allocation of rq\n");
379 +               dev_err(enic, "error in allocation of sop rq\n");
380                 goto err_exit;
381         }
382 +       nb_sop_desc = rq_sop->ring.desc_count;
383  
384 +       if (rq_data->in_use) {
385 +               /* Allocate data queue resources */
386 +               rc = vnic_rq_alloc(enic->vdev, rq_data, data_queue_idx,
387 +                                  nb_data_desc,
388 +                                  sizeof(struct rq_enet_desc));
389 +               if (rc) {
390 +                       dev_err(enic, "error in allocation of data rq\n");
391 +                       goto err_free_rq_sop;
392 +               }
393 +               nb_data_desc = rq_data->ring.desc_count;
394 +       }
395         rc = vnic_cq_alloc(enic->vdev, &enic->cq[queue_idx], queue_idx,
396 -               socket_id, nb_desc,
397 -               sizeof(struct cq_enet_rq_desc));
398 +                          socket_id, nb_sop_desc + nb_data_desc,
399 +                          sizeof(struct cq_enet_rq_desc));
400         if (rc) {
401                 dev_err(enic, "error in allocation of cq for rq\n");
402 -               goto err_free_rq_exit;
403 +               goto err_free_rq_data;
404         }
405  
406 -       /* Allocate the mbuf ring */
407 -       rq->mbuf_ring = (struct rte_mbuf **)rte_zmalloc_socket("rq->mbuf_ring",
408 -                       sizeof(struct rte_mbuf *) * nb_desc,
409 -                       RTE_CACHE_LINE_SIZE, rq->socket_id);
410 +       /* Allocate the mbuf rings */
411 +       rq_sop->mbuf_ring = (struct rte_mbuf **)rte_zmalloc_socket("rq->mbuf_ring",
412 +                       sizeof(struct rte_mbuf *) * nb_sop_desc,
413 +                       RTE_CACHE_LINE_SIZE, rq_sop->socket_id);
414 +       if (rq_sop->mbuf_ring == NULL)
415 +               goto err_free_cq;
416 +
417 +       if (rq_data->in_use) {
418 +               rq_data->mbuf_ring = (struct rte_mbuf **)rte_zmalloc_socket("rq->mbuf_ring",
419 +                             sizeof(struct rte_mbuf *) * nb_data_desc,
420 +                             RTE_CACHE_LINE_SIZE, rq_sop->socket_id);
421 +               if (rq_data->mbuf_ring == NULL)
422 +                       goto err_free_sop_mbuf;
423 +       }
424  
425 -       if (rq->mbuf_ring != NULL)
426 -               return 0;
427 +       return 0;
428  
429 +err_free_sop_mbuf:
430 +       rte_free(rq_sop->mbuf_ring);
431 +err_free_cq:
432         /* cleanup on error */
433         vnic_cq_free(&enic->cq[queue_idx]);
434 -err_free_rq_exit:
435 -       vnic_rq_free(rq);
436 +err_free_rq_data:
437 +       if (rq_data->in_use)
438 +               vnic_rq_free(rq_data);
439 +err_free_rq_sop:
440 +       vnic_rq_free(rq_sop);
441  err_exit:
442         return -ENOMEM;
443  }
444
445 diff -r -u dpdk-16.04.orig2/drivers/net/enic/enic_rxtx.c dpdk-16.04/drivers/net/enic/enic_rxtx.c
446 --- dpdk-16.04.orig2/drivers/net/enic/enic_rxtx.c       2016-05-13 18:09:07.556940752 -0700
447 +++ dpdk-16.04/drivers/net/enic/enic_rxtx.c     2016-05-13 18:12:22.225755674 -0700
448 @@ -242,22 +242,27 @@
449  enic_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts,
450                uint16_t nb_pkts)
451  {
452 -       struct vnic_rq *rq = rx_queue;
453 -       struct enic *enic = vnic_dev_priv(rq->vdev);
454 -       unsigned int rx_id;
455 +       struct vnic_rq *sop_rq = rx_queue;
456 +       struct vnic_rq *data_rq;
457 +       struct vnic_rq *rq;
458 +       struct enic *enic = vnic_dev_priv(sop_rq->vdev);
459 +        uint16_t cq_idx;
460 +       uint16_t rq_idx;
461 +       uint16_t rq_num;
462         struct rte_mbuf *nmb, *rxmb;
463         uint16_t nb_rx = 0;
464 -       uint16_t nb_hold;
465         struct vnic_cq *cq;
466         volatile struct cq_desc *cqd_ptr;
467         uint8_t color;
468 -       uint16_t nb_err = 0;
469 +       uint16_t seg_length;
470 +       struct rte_mbuf *first_seg = sop_rq->pkt_first_seg;
471 +       struct rte_mbuf *last_seg = sop_rq->pkt_last_seg;
472 +
473 +       cq = &enic->cq[enic_cq_rq(enic, sop_rq->index)];
474 +       cq_idx = cq->to_clean;          /* index of cqd, rqd, mbuf_table */
475 +       cqd_ptr = (struct cq_desc *)(cq->ring.descs) + cq_idx;
476  
477 -       cq = &enic->cq[enic_cq_rq(enic, rq->index)];
478 -       rx_id = cq->to_clean;           /* index of cqd, rqd, mbuf_table */
479 -       cqd_ptr = (struct cq_desc *)(cq->ring.descs) + rx_id;
480 -
481 -       nb_hold = rq->rx_nb_hold;       /* mbufs held by software */
482 +       data_rq = &enic->rq[sop_rq->data_queue_idx];
483  
484         while (nb_rx < nb_pkts) {
485                 volatile struct rq_enet_desc *rqd_ptr;
486 @@ -265,6 +270,7 @@
487                 struct cq_desc cqd;
488                 uint64_t ol_err_flags;
489                 uint8_t packet_error;
490 +               uint16_t ciflags;
491  
492                 /* Check for pkts available */
493                 color = (cqd_ptr->type_color >> CQ_DESC_COLOR_SHIFT)
494 @@ -272,9 +278,13 @@
495                 if (color == cq->last_color)
496                         break;
497  
498 -               /* Get the cq descriptor and rq pointer */
499 +               /* Get the cq descriptor and extract rq info from it */
500                 cqd = *cqd_ptr;
501 -               rqd_ptr = (struct rq_enet_desc *)(rq->ring.descs) + rx_id;
502 +               rq_num = cqd.q_number & CQ_DESC_Q_NUM_MASK;
503 +               rq_idx = cqd.completed_index & CQ_DESC_COMP_NDX_MASK;
504 +
505 +               rq = &enic->rq[rq_num];
506 +               rqd_ptr = ((struct rq_enet_desc *)rq->ring.descs) + rq_idx;
507  
508                 /* allocate a new mbuf */
509                 nmb = rte_rxmbuf_alloc(rq->mp);
510 @@ -287,67 +297,106 @@
511                 packet_error = enic_cq_rx_to_pkt_err_flags(&cqd, &ol_err_flags);
512  
513                 /* Get the mbuf to return and replace with one just allocated */
514 -               rxmb = rq->mbuf_ring[rx_id];
515 -               rq->mbuf_ring[rx_id] = nmb;
516 +               rxmb = rq->mbuf_ring[rq_idx];
517 +               rq->mbuf_ring[rq_idx] = nmb;
518  
519                 /* Increment cqd, rqd, mbuf_table index */
520 -               rx_id++;
521 -               if (unlikely(rx_id == rq->ring.desc_count)) {
522 -                       rx_id = 0;
523 +               cq_idx++;
524 +               if (unlikely(cq_idx == cq->ring.desc_count)) {
525 +                       cq_idx = 0;
526                         cq->last_color = cq->last_color ? 0 : 1;
527                 }
528  
529                 /* Prefetch next mbuf & desc while processing current one */
530 -               cqd_ptr = (struct cq_desc *)(cq->ring.descs) + rx_id;
531 +               cqd_ptr = (struct cq_desc *)(cq->ring.descs) + cq_idx;
532                 rte_enic_prefetch(cqd_ptr);
533 -               rte_enic_prefetch(rq->mbuf_ring[rx_id]);
534 -               rte_enic_prefetch((struct rq_enet_desc *)(rq->ring.descs)
535 -                                + rx_id);
536 +//             rte_enic_prefetch(rq->mbuf_ring[rx_id]);
537 +//             rte_enic_prefetch((struct rq_enet_desc *)(rq->ring.descs)
538 +//                              + rx_id);
539 +
540 +               ciflags = enic_cq_rx_desc_ciflags((struct cq_enet_rq_desc *) &cqd);
541  
542                 /* Push descriptor for newly allocated mbuf */
543 -               dma_addr = (dma_addr_t)(nmb->buf_physaddr
544 -                          + RTE_PKTMBUF_HEADROOM);
545 -               rqd_ptr->address = rte_cpu_to_le_64(dma_addr);
546 -               rqd_ptr->length_type = cpu_to_le16(nmb->buf_len
547 -                                      - RTE_PKTMBUF_HEADROOM);
548 +
549 +               dma_addr = (dma_addr_t)(nmb->buf_physaddr + RTE_PKTMBUF_HEADROOM);
550 +                rq_enet_desc_enc(rqd_ptr, dma_addr,
551 +                                (rq->is_sop ? RQ_ENET_TYPE_ONLY_SOP
552 +                                : RQ_ENET_TYPE_NOT_SOP),
553 +                               nmb->buf_len - RTE_PKTMBUF_HEADROOM);
554  
555                 /* Fill in the rest of the mbuf */
556 -               rxmb->data_off = RTE_PKTMBUF_HEADROOM;
557 -               rxmb->nb_segs = 1;
558 +               seg_length = enic_cq_rx_desc_n_bytes(&cqd);
559 +               rxmb->packet_type = enic_cq_rx_flags_to_pkt_type(&cqd);
560 +               enic_cq_rx_to_pkt_flags(&cqd, rxmb);
561 +               if (rq->is_sop) {
562 +                       first_seg = rxmb;
563 +                       first_seg->nb_segs = 1;
564 +                       first_seg->pkt_len = seg_length;
565 +               } else {
566 +                       first_seg->pkt_len = (uint16_t)(first_seg->pkt_len
567 +                                                       + seg_length);
568 +                       first_seg->nb_segs++;
569 +                       last_seg->next = rxmb;
570 +               }
571 +
572                 rxmb->next = NULL;
573                 rxmb->port = enic->port_id;
574 -               if (!packet_error) {
575 -                       rxmb->pkt_len = enic_cq_rx_desc_n_bytes(&cqd);
576 -                       rxmb->packet_type = enic_cq_rx_flags_to_pkt_type(&cqd);
577 -                       enic_cq_rx_to_pkt_flags(&cqd, rxmb);
578 -               } else {
579 -                       rte_pktmbuf_free(rxmb);
580 +               rxmb->data_len = seg_length;
581 +
582 +               rq->rx_nb_hold++;
583 +
584 +               if (!(enic_cq_rx_desc_eop(ciflags))) {
585 +                       last_seg = rxmb;
586 +                       continue;
587 +               }
588 +
589 +               if (unlikely(packet_error)) {
590 +                       rte_pktmbuf_free(first_seg);
591                         rte_atomic64_inc(&enic->soft_stats.rx_packet_errors);
592 -                       nb_err++;
593 +
594                         continue;
595                 }
596 -               rxmb->data_len = rxmb->pkt_len;
597 +
598 +
599 +//             printf("EOP:  final packet length is %d\n", first_seg->pkt_len);
600 +//             rte_pktmbuf_dump(stdout, first_seg, 64);
601  
602                 /* prefetch mbuf data for caller */
603 -               rte_packet_prefetch(RTE_PTR_ADD(rxmb->buf_addr,
604 +               rte_packet_prefetch(RTE_PTR_ADD(first_seg->buf_addr,
605                                     RTE_PKTMBUF_HEADROOM));
606  
607                 /* store the mbuf address into the next entry of the array */
608 -               rx_pkts[nb_rx++] = rxmb;
609 +               rx_pkts[nb_rx++] = first_seg;
610         }
611  
612 -       nb_hold += nb_rx + nb_err;
613 -       cq->to_clean = rx_id;
614 +       sop_rq->pkt_first_seg = first_seg;
615 +       sop_rq->pkt_last_seg = last_seg;
616 +
617 +       cq->to_clean = cq_idx;
618 +
619 +       if ((sop_rq->rx_nb_hold + data_rq->rx_nb_hold) > sop_rq->rx_free_thresh) {
620 +               if (data_rq->in_use) {
621 +                       data_rq->posted_index = enic_ring_add(data_rq->ring.desc_count,
622 +                                                             data_rq->posted_index,
623 +                                                             data_rq->rx_nb_hold);
624 +                       //printf("Processed %d data descs.  Posted index now %d\n",
625 +                       //       data_rq->rx_nb_hold, data_rq->posted_index);
626 +                       data_rq->rx_nb_hold = 0;
627 +               }
628 +               sop_rq->posted_index = enic_ring_add(sop_rq->ring.desc_count,
629 +                                                    sop_rq->posted_index,
630 +                                                    sop_rq->rx_nb_hold);
631 +               //printf("Processed %d sop descs.  Posted index now %d\n",
632 +               //       sop_rq->rx_nb_hold, sop_rq->posted_index);
633 +               sop_rq->rx_nb_hold = 0;
634  
635 -       if (nb_hold > rq->rx_free_thresh) {
636 -               rq->posted_index = enic_ring_add(rq->ring.desc_count,
637 -                               rq->posted_index, nb_hold);
638 -               nb_hold = 0;
639                 rte_mb();
640 -               iowrite32(rq->posted_index, &rq->ctrl->posted_index);
641 +               if (data_rq->in_use)
642 +                       iowrite32(data_rq->posted_index, &data_rq->ctrl->posted_index);
643 +               rte_compiler_barrier();
644 +               iowrite32(sop_rq->posted_index, &sop_rq->ctrl->posted_index);
645         }
646  
647 -       rq->rx_nb_hold = nb_hold;
648  
649         return nb_rx;
650  }