xref: /titanic_52/usr/src/uts/common/io/bnxe/577xx/drivers/common/lm/device/lm_send.c (revision d14abf155341d55053c76eeec58b787a456b753b)
1 /*******************************************************************************
2  *
3  * CDDL HEADER START
4  *
5  * The contents of this file are subject to the terms of the
6  * Common Development and Distribution License (the "License").
7  * You may not use this file except in compliance with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  *
22  * Copyright 2014 QLogic Corporation
23  * The contents of this file are subject to the terms of the
24  * QLogic End User License (the "License").
25  * You may not use this file except in compliance with the License.
26  *
27  * You can obtain a copy of the License at
28  * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
29  * QLogic_End_User_Software_License.txt
30  * See the License for the specific language governing permissions
31  * and limitations under the License.
32  *
33  * Module Description:
34  *
35  *
36  * History:
37  *    11/15/01 Hav Khauv        Inception.
38  *    4/4/06  Eliezer           begin modifying
39  ******************************************************************************/
40 
41 #include "lm5710.h"
42 #include "microcode_constants.h"
43 #include "eth_constants.h"
44 #include "bd_chain.h"
45 #include "ecore_common.h"
46 
47 u8_t lm_is_tx_completion(lm_device_t *pdev, u8_t chain_idx)
48 {
49     u8_t result             = FALSE;
50     lm_tx_chain_t *tx_chain = &LM_TXQ(pdev, chain_idx);
51 
52     DbgBreakIf(!(pdev && tx_chain));
53 
54     //the hw_con_idx_ptr of the rcq_chain points directly to the Rx index in the USTORM part of the non-default status block
55     //changed from *tx_chain->hw_con_idx_ptr != tx_chain->cons_idx
56     if ( tx_chain->hw_con_idx_ptr && (mm_le16_to_cpu(*tx_chain->hw_con_idx_ptr) != tx_chain->pkt_idx))
57     {
58         result = TRUE;
59     }
60     DbgMessage(pdev, INFORMi, "lm_is_tx_completion: result is:%s\n", result? "TRUE" : "FALSE");
61 
62     return result;
63 }
64 
65 static void lm_handle_lso_split(IN  lm_address_t frag_addr_data_offset,
66                                 IN  u16_t data_part_size,
67                                 IN  lm_tx_chain_t *tx_chain,
68                                 IN  struct eth_tx_start_bd *start_bd,
69                                 IN  struct eth_tx_bd *generic_bd
70                                 )
71 {
72     struct eth_tx_bd *prod_bd;
73     u16_t old_nbd = mm_le16_to_cpu(start_bd->nbd);
74     u16_t old_nbytes = mm_le16_to_cpu(generic_bd->nbytes);
75 
76     ASSERT_STATIC(OFFSETOF(struct eth_tx_bd, nbytes) == OFFSETOF(struct eth_tx_start_bd, nbytes)) ;
77     DbgBreakIfFastPath(!(start_bd && generic_bd));
78 
79     //increase nbd on account of the split BD
80     start_bd->nbd = mm_cpu_to_le16(old_nbd + 1);
81 
82     //fix the num of bytes of the BD which has the headers+data to correspond only to the headers part
83     generic_bd->nbytes = mm_cpu_to_le16(old_nbytes - data_part_size);
84     //this is phys addr which points to the start of the data part right after the end of the headers
85     LM_INC64(&frag_addr_data_offset, mm_le16_to_cpu(generic_bd->nbytes));
86 
87     //Advance to the next BD.
88     prod_bd = (struct eth_tx_bd *)lm_bd_chain_produce_bd(&tx_chain->bd_chain);
89 
90     //fill the fields of the new additional BD which holds _only_ data
91     prod_bd->addr_lo              = mm_cpu_to_le32(frag_addr_data_offset.as_u32.low);
92     prod_bd->addr_hi              = mm_cpu_to_le32(frag_addr_data_offset.as_u32.high);
93     prod_bd->nbytes               = mm_cpu_to_le16(data_part_size);
94 
95     tx_chain->lso_split_used++;
96 
97     DbgMessage(NULL, WARNl2tx, "#lm_handle_lso_split: after split: original bd nbytes=0x%x,new bd nbytes=0x%x\n",
98                mm_le16_to_cpu(generic_bd->nbytes), mm_le16_to_cpu(prod_bd->nbytes));
99 }
100 
101 static void lm_pre_process_lso_packet(
102     IN  lm_device_t     *pdev,
103     IN  lm_packet_t     *packet,
104     IN  lm_frag_list_t  *frags,
105     OUT u8_t            *split_required,
106     IN  u16_t            total_hlen_bytes
107     )
108 {
109     /* find headers nbds, for that calc eth_hlen and total_hlen_bytes,
110        and take the opportunity to decide if header data separation is required */
111     u32_t cnt;
112     u16_t sum_frag_size = 0;
113     u8_t  hdr_nbds      = 0;
114 
115     *split_required = FALSE;
116 
117     for(cnt = 0; cnt < frags->cnt; cnt++)
118     {
119         hdr_nbds++;
120         sum_frag_size += (u16_t)frags->frag_arr[cnt].size;
121         if (total_hlen_bytes <= sum_frag_size)
122         {
123             if (total_hlen_bytes < sum_frag_size)
124             {
125                 *split_required = TRUE;
126             }
127             break;
128         }
129     }
130     DbgBreakIfFastPath(total_hlen_bytes > sum_frag_size);
131     packet->u1.tx.hdr_nbds = hdr_nbds;
132 }
133 
134 static void lm_process_lso_packet(IN  lm_packet_t *packet,
135                                   IN  lm_device_t *pdev,
136                                   IN  lm_tx_chain_t *tx_chain,
137                                   IN  lm_frag_list_t *frags,
138                                   IN  void *parse_bd,
139                                   IN  struct eth_tx_start_bd *start_bd,
140                                   OUT lm_frag_t **frag,
141                                   IN  u16_t total_hlen_bytes,
142                                   IN  u8_t split_required)
143 {
144     struct eth_tx_bd *prod_bd = NULL;
145     u32_t cnt                 = 0;
146     u16_t hlen_reminder       = total_hlen_bytes;
147 
148     /* "Sanity check.  Maximum total length for IP and TCP headers
149      * is 120 bytes." was here. The sanity check is removed. Corresponding statistics is added */
150     if ((packet->l2pkt_tx_info->lso_ip_hdr_len + packet->l2pkt_tx_info->lso_tcp_hdr_len) > 120) {
151         pdev->debug_info.number_of_long_LSO_headers++;
152     }
153     start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_SW_LSO;
154 
155     if (CHIP_IS_E1x(pdev))
156     {
157         struct eth_tx_parse_bd_e1x *parse_bd_e1x = (struct eth_tx_parse_bd_e1x *)parse_bd;
158         parse_bd_e1x->lso_mss          = mm_cpu_to_le16(packet->l2pkt_tx_info->lso_mss);
159         parse_bd_e1x->ip_id            = mm_cpu_to_le16(packet->l2pkt_tx_info->lso_ipid);
160         parse_bd_e1x->tcp_send_seq     = mm_cpu_to_le32(packet->l2pkt_tx_info->lso_tcp_send_seq);
161         parse_bd_e1x->tcp_flags        = packet->l2pkt_tx_info->lso_tcp_flags; // no endianity since it is u8_t
162 
163 
164         //in case of LSO it is required according to fw to toggle the ETH_TX_PARSE_BD_PSEUDO_CS_WITHOUT_LEN flag since the TCP seg len is 0
165         parse_bd_e1x->global_data |= ETH_TX_PARSE_BD_E1X_PSEUDO_CS_WITHOUT_LEN;
166 
167         if GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_TCP_LSO_SNAP_FRAME)
168         {
169             parse_bd_e1x->global_data |= ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN;
170         }
171     }
172     else
173     {
174         struct eth_tx_parse_bd_e2 *parse_bd_e2 = (struct eth_tx_parse_bd_e2 *)parse_bd;
175         parse_bd_e2->parsing_data |= ETH_TX_PARSE_BD_E2_LSO_MSS & (packet->l2pkt_tx_info->lso_mss << ETH_TX_PARSE_BD_E2_LSO_MSS_SHIFT);
176     }
177 
178 
179     //enforce this due to miniport design in case of LSO and CSUM
180     SET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_COMPUTE_TCP_UDP_CKSUM);
181 
182     if (!GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_IPV6_PACKET))
183     {
184         SET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_COMPUTE_IP_CKSUM);
185     }
186 
187 
188     //required only in case of LSO - num of bds the headers occupy all together
189     RESET_FLAGS(start_bd->general_data, ETH_TX_START_BD_HDR_NBDS);
190     start_bd->general_data |= ((packet->u1.tx.hdr_nbds & ETH_TX_START_BD_HDR_NBDS) << ETH_TX_START_BD_HDR_NBDS_SHIFT);
191 
192     //check for split in START BD
193     if (split_required)
194     {
195         if ((start_bd->general_data & ETH_TX_START_BD_HDR_NBDS) == 1)
196         {
197             lm_handle_lso_split(frags->frag_arr[0].addr,
198                                 mm_le16_to_cpu(start_bd->nbytes) - hlen_reminder,
199                                 tx_chain,
200                                 start_bd,
201                                 (struct eth_tx_bd *)start_bd );
202             split_required = FALSE;
203         }
204         else
205         {
206         u16_t start_bd_nbytes = mm_le16_to_cpu(start_bd->nbytes);
207 
208             DbgBreakIfFastPath(hlen_reminder <= start_bd_nbytes);
209             hlen_reminder -= start_bd_nbytes;
210         }
211     }
212 
213     for(cnt = 1; cnt < frags->cnt; cnt++)
214     {
215         DbgBreakIfFastPath((*frag)->size >= 0x10000 || (*frag)->size == 0);
216 
217         //Advance to the next BD.
218         prod_bd = (struct eth_tx_bd *)lm_bd_chain_produce_bd(&tx_chain->bd_chain);
219 
220         prod_bd->addr_lo              = mm_cpu_to_le32((*frag)->addr.as_u32.low);
221         prod_bd->addr_hi              = mm_cpu_to_le32((*frag)->addr.as_u32.high);
222         prod_bd->nbytes               = mm_cpu_to_le16((u16_t) (*frag)->size);
223 
224         //if there is a split condition and we are on the exact BD, do it! we don't enter here if there was a split already!
225         if (split_required)
226         {
227             if (cnt == ((start_bd->general_data & ETH_TX_START_BD_HDR_NBDS) - 1))
228             {
229                 lm_handle_lso_split((*frag)->addr,
230                                     mm_le16_to_cpu(prod_bd->nbytes) - hlen_reminder,
231                                     tx_chain,
232                                     start_bd,
233                                     prod_bd
234                                     );
235                 split_required = FALSE;
236             }
237             else
238             {
239                 u16_t prod_bd_nbytes = mm_le16_to_cpu(prod_bd->nbytes);
240 
241                 DbgBreakIfFastPath(hlen_reminder <= prod_bd_nbytes);
242                 hlen_reminder -= prod_bd_nbytes;
243             }
244         }
245 
246         packet->size += (*frag)->size;
247         (*frag)++;
248     }
249 
250 
251 
252     //statistics
253     //since this is fast path, we do not use ATOMIC INC.
254     //therefore the statistic might not be completely accurate
255     //possible fix (FUTURE, if required): count the statistic item per RSS/TSS
256     LM_COMMON_DRV_STATS_INC_ETH(pdev, tx_lso_frames);
257 }
258 
259 /**
260  * @Description:
261  *   returns coalesce buffer of size >= buf_size, or NULL if none available
262  * @Assumptions:
263  *   txq lock is taken by the caller
264 */
265 lm_coalesce_buffer_t *
266 lm_get_coalesce_buffer(
267     IN lm_device_t      *pdev,
268     IN lm_tx_chain_t    *txq,
269     IN u32_t            buf_size)
270 {
271     lm_coalesce_buffer_t *coalesce_buf = NULL;
272     u32_t coalesce_buf_cnt, cnt;
273 
274     if (ERR_IF(CHK_NULL(pdev) || CHK_NULL(txq) || !buf_size)) {
275         DbgBreakFastPath();
276         return NULL;
277     }
278 
279     coalesce_buf_cnt = s_list_entry_cnt(&txq->coalesce_buf_list);
280     for(cnt = 0; cnt < coalesce_buf_cnt; cnt++)
281     {
282         coalesce_buf = (lm_coalesce_buffer_t *) s_list_pop_head(
283             &txq->coalesce_buf_list);
284 
285         DbgBreakIfFastPath(coalesce_buf == NULL);
286         if(NULL == coalesce_buf)
287         {
288             //this case were coalesce buffer in the list is equal to null shouldn't happen.
289             DbgMessage(pdev, FATAL, "lm_get_coalesce_buffer:coalesce buffer was null\n");
290             break;
291         }
292         if(coalesce_buf->buf_size >= buf_size)
293         {
294             txq->coalesce_buf_used++;
295             break;
296         }
297 
298         s_list_push_tail(&txq->coalesce_buf_list, &coalesce_buf->link);
299 
300         coalesce_buf = NULL;
301     }
302 
303     return coalesce_buf;
304 } /* lm_get_coalesce_buffer */
305 
306 /**
307  * @Description:
308  *   returns coalesce_buf into txq list
309  * @Assumptions:
310  *   txq lock is taken by the caller
311 */
312 void
313 lm_put_coalesce_buffer(
314     IN lm_device_t          *pdev,
315     IN lm_tx_chain_t        *txq,
316     IN lm_coalesce_buffer_t *coalesce_buf)
317 {
318     if (ERR_IF(CHK_NULL(pdev) || CHK_NULL(txq) || CHK_NULL(coalesce_buf))) {
319         DbgBreakFastPath();
320         return;
321     }
322 
323     s_list_push_tail(&txq->coalesce_buf_list, &coalesce_buf->link);
324 
325     return;
326 } /* lm_put_coalesce_buffer */
327 
328 /**
329  * @Description:
330  *   copy given packet into available coalesce buffer of given txq
331  * @Assumptions:
332  *   txq lock is taken by the caller
333  * @Returns:
334  *   - SUCCESS -
335  *      - The OUT parameter coal_buf will be set to point the allocated
336  *        coalesce buffer
337  *      - The coalesce buffer frag size will be set to the given packet size
338  *   - RESOURCE - no available coalecse buffer for given packet
339  *                (according to packet size)
340  */
341 static lm_status_t
342 lm_copy_packet_to_coalesce_buffer(
343     IN  lm_device_t             *pdev,
344     IN  lm_tx_chain_t           *txq,
345     IN  lm_packet_t             *lmpkt,
346     IN  lm_frag_list_t          *frags,
347     OUT lm_coalesce_buffer_t    **coal_buf
348     )
349 {
350     lm_coalesce_buffer_t *coalesce_buf;
351     lm_frag_t*            frag;
352     u32_t                 pkt_size      = 0;
353     u32_t                 copied_bytes;
354     u32_t                 cnt;
355 
356     if (ERR_IF(CHK_NULL(pdev) || CHK_NULL(txq) ||
357                CHK_NULL(lmpkt) || CHK_NULL(frags)))
358     {
359         DbgBreakFastPath();
360         return LM_STATUS_FAILURE;
361     }
362 
363     /* Determine packet size. */
364     frag = &frags->frag_arr[0];
365     for (cnt = 0; cnt < frags->cnt; cnt++, frag++) {
366         pkt_size += frag->size;
367     }
368 
369     /* Find a buffer large enough for copying this packet.  In the case
370      * of an LSO frame, we should have at least one 64k coalesce buffer. */
371     coalesce_buf = lm_get_coalesce_buffer(pdev, txq, pkt_size);
372     if(coalesce_buf == NULL)
373     {
374         DbgMessage(pdev, INFORMl2tx,
375                     "#copy to coalesce buffer FAILED, (lmpkt=0x%p,pkt_size=%d)\n",
376                     lmpkt, pkt_size);
377         LM_COMMON_DRV_STATS_ATOMIC_INC_ETH(pdev, tx_no_coalesce_buf);
378         return LM_STATUS_RESOURCE;
379     }
380 
381     /* copy the packet into the coalesce buffer */
382     copied_bytes = mm_copy_packet_buf(
383         pdev, lmpkt, coalesce_buf->mem_virt, pkt_size);
384     if (ERR_IF(copied_bytes != pkt_size)) {
385         DbgBreakFastPath();
386         lm_put_coalesce_buffer(pdev, txq, coalesce_buf);
387         return LM_STATUS_FAILURE;
388     }
389 
390     /* adjust frag size in coalesce buf */
391     coalesce_buf->frags.frag_arr[0].size = pkt_size;
392 
393     *coal_buf = coalesce_buf;
394     return LM_STATUS_SUCCESS;
395 } /* lm_copy_packet_to_coalesce_buffer */
396 
397 /**
398  * @Description:
399  *   check if packet requires copying to coalesce buf (packet too fregmented)
400  * @Returns:
401  *   TRUE or FALSE
402 */
403 static u8_t
404 lm_is_packet_coalescing_required(
405     IN     lm_device_t    *pdev,
406     IN     lm_packet_t    *lmpkt,
407     IN     lm_frag_list_t *frags,
408     IN     u8_t           num_parsing_bds
409     )
410 {
411     u8_t to_copy                    = FALSE;
412     u8_t wnd_size                   = 0;
413     static u32_t const MAX_FETCH_BD = 13;  /* HW max bds per packet capabitily */
414 
415     // each window size consective TCP payload BDs, must hold payload size
416     // which is greater than, or equal to MSS size.
417     wnd_size  = MAX_FETCH_BD - lmpkt->u1.tx.hdr_nbds - num_parsing_bds - 1;
418 
419     if (frags->cnt > wnd_size)
420     {
421         if GET_FLAGS(lmpkt->l2pkt_tx_info->flags, LM_TX_FLAG_TCP_LSO_FRAME)
422         {
423             /* Too fragmented LSO packet, check if it needs to be copied: */
424             u8_t num_frags = (u8_t)frags->cnt;
425             u8_t wnd_idx   = 0;
426             u8_t frag_idx  = 0;
427             u32_t wnd_sum  = 0;
428 
429             for (wnd_idx = lmpkt->u1.tx.hdr_nbds; wnd_idx <= (num_frags - wnd_size); wnd_idx++)
430             {
431                 for (frag_idx = 0; frag_idx < wnd_size; frag_idx++)
432                 {
433                     wnd_sum += frags->frag_arr[wnd_idx + frag_idx].size;
434                 }
435 
436                 if (wnd_sum < lmpkt->l2pkt_tx_info->lso_mss)
437                 {
438                     DbgMessage(pdev, WARNl2tx,
439                                 "#copy to coalesce buffer IS REQUIRED for LSO packet, (lmpkt=0x%p,num_frags=%d)\n",
440                                 lmpkt, num_frags);
441                     to_copy = TRUE;
442                     break;
443                 }
444                 wnd_sum = 0;
445             }
446         }
447         else
448         {
449             /* in non LSO, too fragmented packet should always
450                be copied to coalesce buffer */
451             DbgMessage(pdev, INFORMl2tx,
452                         "#copy to coalesce buffer IS REQUIRED for NON LSO packet, (lmpkt=0x%p,num_frags=%d)\n",
453                         lmpkt, frags->cnt);
454             to_copy = TRUE;
455         }
456     }
457 
458     return to_copy;
459 } /* lm_is_packet_coalescing_required */
460 
461 #define LM_VLAN_PRI_BIT_LOCATION            (13)
462 #define LM_GET_PRI_FROM_VLAN(_vlan)         ((_vlan) >> LM_VLAN_PRI_BIT_LOCATION)
463 /**
464  * @description
465  * Check if VLAN exist and if the VLAN exists get priority.
466  * @param pdev
467  * @param packet
468  *
469  * @return u32_t
470  */
471 u8_t
472 lm_get_pri_from_send_packet_param(
473     lm_device_t *pdev,
474     lm_packet_t *packet)
475 {
476     //untagged packets should be treated as priority 0
477     u8_t pri = 0;
478 
479     if GET_FLAGS(packet->l2pkt_tx_info->flags , (LM_TX_FLAG_INSERT_VLAN_TAG | LM_TX_FLAG_VLAN_TAG_EXISTS))
480     {
481         DbgMessage(pdev, INFORMl2, "Outband vlan 0X%x\n",packet->l2pkt_tx_info->vlan_tag);
482 
483         pri = LM_GET_PRI_FROM_VLAN(packet->l2pkt_tx_info->vlan_tag);
484     }
485 
486     return pri;
487 }
488 
489 void
490 fill_bds_for_encapsulated_packet(
491     lm_device_t                *pdev,
492     lm_packet_t                *packet,
493     struct eth_tunnel_data     *tunnel_data,
494     struct eth_tx_parse_2nd_bd *parse_bd_2nd_ptr,
495     u8_t                       eth_hlen)
496 {
497     DbgBreakIf(CHIP_IS_E1x(pdev));
498 
499     ecore_set_fw_mac_addr(&tunnel_data->dst_hi,
500                           &tunnel_data->dst_mid,
501                           &tunnel_data->dst_lo,
502                           packet->l2pkt_tx_info->dst_mac_addr);
503 
504     // Inner IP header offset in WORDs (16-bit) from start of packet
505     tunnel_data->ip_hdr_start_inner_w = (packet->l2pkt_tx_info->encap_packet_inner_frame_offset +
506                                          packet->l2pkt_tx_info->encap_packet_inner_ip_relative_offset) >> 1;
507 
508     // Checksum of pseudo header with length field = 0
509     tunnel_data->pseudo_csum = mm_cpu_to_le16(packet->l2pkt_tx_info->tcp_pseudo_csum);
510     // Outer ip header checksum (with ALL ip header fields) for non-lso encaulated packet
511     tunnel_data->fw_ip_hdr_csum = mm_cpu_to_le16(packet->l2pkt_tx_info->fw_ip_csum);
512 
513     if (GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_IPV6_PACKET))
514     {
515         // Set in case outer IP header is ipV6
516         SET_FLAGS(tunnel_data->flags, ETH_TUNNEL_DATA_IP_HDR_TYPE_OUTER);
517     }
518 
519     if (!parse_bd_2nd_ptr)
520     {
521         return;
522     }
523 
524     // Outer IP header offset in WORDs (16-bit) from start of packet
525     parse_bd_2nd_ptr->global_data |= ( ((eth_hlen) >> 1) << ETH_TX_PARSE_2ND_BD_IP_HDR_START_OUTER_W_SHIFT);
526 
527     if (!(GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_IPV6_PACKET)))
528     {
529         // Outer ipV4 header length in words
530         parse_bd_2nd_ptr->global_data |= ( ((packet->l2pkt_tx_info->lso_ip_hdr_len) >> 1) << ETH_TX_PARSE_2ND_BD_IP_HDR_LEN_OUTER_W_SHIFT);
531     }
532 
533     // An optional addition to ECN that protects against accidental or malicious concealment of marked packets from the TCP sender
534     parse_bd_2nd_ptr->global_data |= (packet->l2pkt_tx_info->tcp_nonce_sum_bit << ETH_TX_PARSE_2ND_BD_NS_FLG_SHIFT);
535 
536     // Checksum of pseudo header with length field=0
537     parse_bd_2nd_ptr->tcp_send_seq    = mm_cpu_to_le32(packet->l2pkt_tx_info->lso_tcp_send_seq);
538     parse_bd_2nd_ptr->tcp_flags       = packet->l2pkt_tx_info->lso_tcp_flags; // no endianity since it is u8_t
539 
540     /* We set tunnel_lso_inc_ip_id as constant, INT_HEADER, so the "HW IP header" is the inner header.
541        Assuming "FW IP header" is the outer IP header, and "HW IP header" is the inner IP header:
542        fw_ip_csum_wo_len_flags_frag - is the IP checksum without length, flags and fragment offset of the outer ip header
543        hw_ip_id - is the ip id of the inner ip id */
544     parse_bd_2nd_ptr->fw_ip_csum_wo_len_flags_frag = mm_cpu_to_le16(packet->l2pkt_tx_info->fw_ip_csum);
545     parse_bd_2nd_ptr->hw_ip_id                     = mm_cpu_to_le16(packet->l2pkt_tx_info->lso_ipid);
546 
547     parse_bd_2nd_ptr->fw_ip_hdr_to_payload_w = (packet->l2pkt_tx_info->encap_packet_inner_frame_offset +
548                                                 packet->l2pkt_tx_info->encap_packet_inner_ip_relative_offset +
549                                                 packet->l2pkt_tx_info->encap_packet_inner_tcp_relative_offset +
550                                                 packet->l2pkt_tx_info->lso_tcp_hdr_len -
551                                                 eth_hlen) >> 1;
552 
553     if (GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_IPV6_PACKET))
554     {
555 /* In IpV4, the length (in WORDs) from the FW IpV4 header start to the payload start. In IpV6, the length (in WORDs) from the FW IpV6 header end to the payload start. However, if extension headers are included, their length is counted here as well. */;
556 
557         // if the outer header (fw header) is ipv4 than fw_ip_hdr_to_payload_w will be set to:
558         // the length in words from start of outer IP header to start of payload
559         // = outer ip header + gre header + inner mac header + inner ip header + tcp header length
560         //
561         // If the outer header is ipv6 than fw_ip_hdr_to_payload_w will be set to:
562         // the length in words from end of inner IP header to start of payload + extension headers (if exists)
563         // = outer ip header - fixed ip header + gre header + inner mac header + inner ip header + tcp header length
564         // fixed ipv6 header length is 40 bytes = 20 words
565         parse_bd_2nd_ptr->fw_ip_hdr_to_payload_w -= 20;
566     }
567 }
568 
569 /*******************************************************************************
570  * Description:
571  *
572  * Return:
573  ******************************************************************************/
574 lm_status_t
575 lm_send_packet(
576     lm_device_t *pdev,
577     u32_t chain_idx,
578     lm_packet_t *packet,
579     lm_frag_list_t *frags)
580 {
581     lm_tx_chain_t              *tx_chain         = NULL;
582     struct eth_tx_start_bd     *start_bd         = NULL;
583     struct eth_tx_parse_bd_e1x *parse_bd_e1x     = NULL;
584     struct eth_tx_parse_bd_e2  *parse_bd_e2      = NULL;
585     struct eth_tx_parse_2nd_bd *parse_bd_2nd_ptr = NULL;
586     struct eth_tx_bd           *prod_bd          = NULL;
587     lm_frag_t                  *frag             = NULL;
588     u16_t                      old_prod_idx      = 0;
589     u32_t                      cnt               = 0;
590 #if defined(__BIG_ENDIAN)
591     struct doorbell_set_prod  dq_msg   = {0, 0, {0}};
592 #elif defined(__LITTLE_ENDIAN)
593     struct doorbell_set_prod  dq_msg   = {{0}, 0, 0};
594 #endif
595 
596     u8_t eth_hlen                                = ETHERNET_PACKET_HEADER_SIZE;
597     u8_t split_required                          = FALSE;
598     u8_t eth_addr_type                           = UNKNOWN_ADDRESS;
599     u16_t total_hlen_bytes                       = 0;
600     u16_t start_bd_nbd                           = 0;
601     u16_t vlan_tag                               = 0;
602     void* parse_bd_ptr                           = NULL;
603     u8_t  is_encapsulated_offload                = 0;
604     u8_t  num_parsing_bds                        = 1;
605 
606     //DbgBreakIfFastPath(chain_idx >= pdev->params.rss_chain_cnt);
607 
608     DbgMessage(pdev, VERBOSEl2tx | VERBOSEl4tx, "### lm_send_packet\n");
609 
610     tx_chain = &LM_TXQ(pdev, chain_idx);
611     old_prod_idx = lm_bd_chain_prod_idx(&tx_chain->bd_chain);
612 
613     // Compute Ethernet Header Len
614     if GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_VLAN_TAG_EXISTS)
615     {
616         eth_hlen += ETHERNET_VLAN_TAG_SIZE;
617     }
618 
619     if GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_TCP_LSO_SNAP_FRAME)
620     {
621         eth_hlen += ETHERNET_LLC_SNAP_SIZE;
622     }
623 
624     is_encapsulated_offload = (GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_IS_ENCAP_PACKET) &&
625                                GET_FLAGS(packet->l2pkt_tx_info->flags, (LM_TX_FLAG_COMPUTE_IP_CKSUM | LM_TX_FLAG_COMPUTE_TCP_UDP_CKSUM | LM_TX_FLAG_TCP_LSO_FRAME)));
626 
627     if (is_encapsulated_offload)
628     {
629         if (GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_TCP_LSO_FRAME))
630         {
631             // only for encapsulated packet with lso offload we need second parsing bd
632             num_parsing_bds = 2;
633         }
634         // encapsulated packet header size includes both outer and inner headers
635         total_hlen_bytes = packet->l2pkt_tx_info->encap_packet_inner_frame_offset +
636                            packet->l2pkt_tx_info->encap_packet_inner_ip_relative_offset +
637                            packet->l2pkt_tx_info->encap_packet_inner_tcp_relative_offset +
638                            packet->l2pkt_tx_info->lso_tcp_hdr_len;
639     }
640     else
641     {
642         //calculate the total sum of ETH + IP + TCP headers in term of bytes
643         total_hlen_bytes = packet->l2pkt_tx_info->lso_ip_hdr_len + packet->l2pkt_tx_info->lso_tcp_hdr_len + eth_hlen;
644     }
645 
646     if (GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_TCP_LSO_FRAME))
647     {
648         lm_pre_process_lso_packet(pdev, packet, frags, &split_required, total_hlen_bytes);
649     }
650 
651     /* handle packet coalescing - if required, copy the too fregmented packet
652        into a pre-allocated coalesce buffer */
653     if (lm_is_packet_coalescing_required(pdev, packet, frags, num_parsing_bds))
654     {
655         lm_coalesce_buffer_t *coalesce_buf = NULL;
656         lm_status_t lm_status;
657 
658         if (ERR_IF(packet->u1.tx.coalesce_buf != NULL))
659         {
660             /* pkt coal buf can't already be set */
661             DbgBreakFastPath();
662             return LM_STATUS_FAILURE;
663         }
664 
665         lm_status = lm_copy_packet_to_coalesce_buffer(
666             pdev, tx_chain, packet, frags, &coalesce_buf);
667 
668         if (lm_status == LM_STATUS_SUCCESS)
669         {
670             LM_COMMON_DRV_STATS_ATOMIC_INC_ETH(pdev, tx_l2_assembly_buf_use);
671 
672             packet->u1.tx.coalesce_buf = coalesce_buf; /* saved to be freed upon completion */
673 
674             packet->u1.tx.hdr_nbds = 1;
675             split_required = 1;
676 
677             /* from here on, use the coalesce buf frags list
678                instead of the frags list given by the caller */
679             frags = &coalesce_buf->frags;
680         }
681         else
682         {
683             return lm_status; /* no coalesce buf available, can't continue */
684         }
685     }
686 
687     // stringent heuristic - number of parsing bds + a split of hdr & data
688     if ((frags->cnt + num_parsing_bds + 1) > lm_bd_chain_avail_bds(&tx_chain->bd_chain))
689     {
690         LM_COMMON_DRV_STATS_ATOMIC_INC_ETH(pdev, tx_no_l2_bd);
691         if (packet->u1.tx.coalesce_buf)
692         {
693             /* TODO: change this to "goto out_err:" */
694             lm_put_coalesce_buffer(pdev, tx_chain, packet->u1.tx.coalesce_buf);
695             packet->u1.tx.coalesce_buf = NULL;
696         }
697         return LM_STATUS_RESOURCE;
698     }
699 
700     packet->size = 0;
701     start_bd = (struct eth_tx_start_bd *)lm_bd_chain_produce_bd(&tx_chain->bd_chain);
702     mm_mem_zero(start_bd, sizeof(union eth_tx_bd_types));
703     //initialize the start BD
704     frag = frags->frag_arr;
705     start_bd->addr_lo              = mm_cpu_to_le32(frag->addr.as_u32.low);
706     start_bd->addr_hi              = mm_cpu_to_le32(frag->addr.as_u32.high);
707     start_bd->nbytes               = mm_cpu_to_le16((u16_t) frag->size);
708     start_bd->bd_flags.as_bitfield = (u8_t) ETH_TX_BD_FLAGS_START_BD;
709     start_bd->nbd = 0;
710     // set the number of parsing BDs in packet.
711     // parse_nbds is set to: the number of parsing BDs in packet - 1
712     start_bd->general_data |= ((num_parsing_bds - 1) << ETH_TX_START_BD_PARSE_NBDS_SHIFT);
713     if (is_encapsulated_offload)
714     {
715         // tunnel_exist should be set iff the packet is encapsulated
716         start_bd->general_data |= ETH_TX_START_BD_TUNNEL_EXIST;
717 
718         // for encapsulated packets ETH_TX_BD_FLAGS_IPV6 refers to the inner header
719         if (GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_ENCAP_PACKET_IS_INNER_IPV6))
720         {
721             start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_IPV6;
722         }
723     }
724     else
725     {
726         // set in case ipV6 packet
727         if (GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_IPV6_PACKET))
728         {
729             start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_IPV6;
730         }
731     }
732 
733     if (GET_FLAGS(packet->l2pkt_tx_info->flags , LM_TX_FLAG_INSERT_VLAN_TAG))
734     {
735         DbgMessage(pdev, INFORMl2, "Outband vlan 0X%x\n",packet->l2pkt_tx_info->vlan_tag);
736         start_bd->bd_flags.as_bitfield |= (ETH_TX_BD_FLAGS_VLAN_MODE & (X_ETH_OUTBAND_VLAN << ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT));
737 
738         vlan_tag = packet->l2pkt_tx_info->vlan_tag;
739     }
740     else if (GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_VLAN_TAG_EXISTS))
741     {
742         DbgMessage(pdev, INFORMl2, "Inband vlan 0X%x\n",packet->l2pkt_tx_info->vlan_tag);
743         start_bd->bd_flags.as_bitfield |= (ETH_TX_BD_FLAGS_VLAN_MODE & (X_ETH_INBAND_VLAN << ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT));
744 
745         vlan_tag = packet->l2pkt_tx_info->vlan_tag;
746     }
747     else
748     {
749         if (IS_VFDEV(pdev)) {
750             ((u8_t*)&vlan_tag)[0] = packet->l2pkt_tx_info->eth_type[1]; //VF is in secure mode
751             ((u8_t*)&vlan_tag)[1] = packet->l2pkt_tx_info->eth_type[0]; //VF is in secure mode
752             if (vlan_tag == VLAN_TAGGED_FRAME_ETH_TYPE) {
753                 ((u8_t*)&vlan_tag)[0] = packet->l2pkt_tx_info->eth_type[3]; //VF is in secure mode
754                 ((u8_t*)&vlan_tag)[1] = packet->l2pkt_tx_info->eth_type[2]; //VF is in secure mode
755                 DbgMessage(pdev, INFORMl2, "Inband vlan (from packet) 0X%x\n",vlan_tag);
756                 start_bd->bd_flags.as_bitfield |= (ETH_TX_BD_FLAGS_VLAN_MODE & (X_ETH_INBAND_VLAN << ETH_TX_BD_FLAGS_VLAN_MODE_SHIFT));
757             }
758         } else {
759             /* for debug only - to discover driver/fw lack of synchronization */
760             vlan_tag = (u16_t)(pdev->tx_info.chain[chain_idx].eth_tx_prods.packets_prod);
761         }
762     }
763     start_bd->vlan_or_ethertype = mm_cpu_to_le16(vlan_tag);
764 
765     if (GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_FORCE_VLAN_MODE))
766     {
767         //force vlan mode according to bds (vlan mode can change accroding to global configuration)
768         SET_FLAGS(start_bd->general_data, ETH_TX_START_BD_FORCE_VLAN_MODE);
769     }
770 
771     packet->size += frag->size;
772     frag++;
773 
774     //SNAP
775     //parse bd is always present for FW simplicity
776     //adjust the parse BD pointer
777     /////////////////start parse BD handling ////////////////////////////////////////////
778     parse_bd_ptr = lm_bd_chain_produce_bd(&tx_chain->bd_chain);
779     mm_mem_zero(parse_bd_ptr, sizeof(union eth_tx_bd_types));
780 
781     if (CHIP_IS_E1x(pdev))
782     {
783         parse_bd_e1x = parse_bd_ptr;
784         parse_bd_e1x->global_data = (UNICAST_ADDRESS << ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE_SHIFT);
785     }
786     else
787     {
788         parse_bd_e2 = parse_bd_ptr;
789         parse_bd_e2->parsing_data = (UNICAST_ADDRESS << ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT);
790     }
791     // first parse BD taken into account
792     start_bd_nbd++;
793 
794     if (num_parsing_bds > 1)
795     {
796         // lso offload for encapsulated packet - two parsing bds are required
797         parse_bd_2nd_ptr = lm_bd_chain_produce_bd(&tx_chain->bd_chain);
798         mm_mem_zero(parse_bd_2nd_ptr, sizeof(union eth_tx_bd_types));
799         //second parse BD taken into account
800         start_bd_nbd++;
801     }
802 
803     if (is_encapsulated_offload)
804     {
805         fill_bds_for_encapsulated_packet(pdev, packet, &parse_bd_e2->data.tunnel_data, parse_bd_2nd_ptr, eth_hlen);
806     }
807     /////////////////end parse BD handling ////////////////////////////////////////////
808 
809     if (IS_PFDEV(pdev) && (tx_chain->idx == FWD_CID(pdev)))
810     {
811         pdev->tx_info.forward_packets++;
812     }
813     if GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_TCP_LSO_FRAME)
814     {
815         start_bd->nbd = mm_cpu_to_le16(start_bd_nbd);
816         lm_process_lso_packet(packet, pdev, tx_chain, frags, parse_bd_ptr, start_bd,
817                               &frag, total_hlen_bytes, split_required);
818         start_bd_nbd = mm_cpu_to_le16(start_bd->nbd);
819         if (IS_PFDEV(pdev) && (tx_chain->idx == FWD_CID(pdev)))
820         {
821             pdev->tx_info.lso_forward_packets++;
822         }
823 
824     }
825     else //This is the regular path in case we're not LSO
826     {
827         // In non-LSO packets, if there are more than 1 data bds, the second data bd (the one after
828         // the parsing bd) will be of the above type.total_pkt_bytes will hold the total packet length,
829         // without outer vlan and without vlan in case there is vlan offload.
830         struct eth_tx_bd *total_pkt_bytes_bd        = NULL;
831 
832         //pass on all frags except the first one
833         for(cnt = 1; cnt < frags->cnt; cnt++)
834         {
835             DbgMessage(pdev, VERBOSEl2tx | VERBOSEl4tx, "   frag %d, hi 0x%x, lo 0x%x, size %d\n",
836                 cnt, frag->addr.as_u32.high, frag->addr.as_u32.low, frag->size);
837 
838             DbgBreakIfFastPath(frag->size >= 0x10000 || frag->size == 0);
839             // TODO: assert/ fixup if to many SGE's per MTU
840 
841             //Advance to the next BD.
842             prod_bd = (struct eth_tx_bd *)lm_bd_chain_produce_bd(&tx_chain->bd_chain);
843 
844             prod_bd->addr_lo              = mm_cpu_to_le32(frag->addr.as_u32.low);
845             prod_bd->addr_hi              = mm_cpu_to_le32(frag->addr.as_u32.high);
846             prod_bd->nbytes               = mm_cpu_to_le16((u16_t) frag->size);
847             if (NULL == total_pkt_bytes_bd)
848             {
849                 //second data bd saved for updating total_pkt_bytes.
850                 total_pkt_bytes_bd = prod_bd;
851             }
852             packet->size += frag->size;
853 
854             frag++;
855         }
856 
857         if (NULL != total_pkt_bytes_bd)
858         {
859             //we have a second data bd
860             total_pkt_bytes_bd->total_pkt_bytes = mm_cpu_to_le16((u16_t) packet->size);
861         }
862     }
863 
864     //we might have IP csum, TCP csum, both or none.
865     //It is definitely legit for a packet to be csum offloaded with or without LSO!
866     //If the packet is LSO, we must enter here!!!!
867     if (GET_FLAGS(packet->l2pkt_tx_info->flags, (LM_TX_FLAG_COMPUTE_IP_CKSUM | LM_TX_FLAG_COMPUTE_TCP_UDP_CKSUM)))
868     {
869         // non-encapsulated packet: set bit if LM_TX_FLAG_COMPUTE_IP_CKSUM is on (LM_TX_FLAG_ENCAP_PACKET_IS_INNER_IPV6 is always equal to zero)
870         // encapsulated packet: set bit if LM_TX_FLAG_COMPUTE_IP_CKSUM is on and inner ip header is ipv4
871         if (GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_COMPUTE_IP_CKSUM) &&
872            (!GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_ENCAP_PACKET_IS_INNER_IPV6)))
873         {
874             start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_IP_CSUM;
875         }
876 
877         if (GET_FLAGS(packet->l2pkt_tx_info->flags, LM_TX_FLAG_COMPUTE_TCP_UDP_CKSUM))
878         {
879             start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_L4_CSUM;
880             if(packet->l2pkt_tx_info->cs_any_offset)
881             {
882                 start_bd->bd_flags.as_bitfield |= ETH_TX_BD_FLAGS_IS_UDP;
883             }
884         }
885 
886         if (CHIP_IS_E1x(pdev)) {
887             struct eth_tx_parse_bd_e1x *parse_bd_e1x = parse_bd_ptr;
888 
889             if (CHK_NULL(parse_bd_ptr)) {
890                 DbgBreakIfFastPath( !parse_bd_ptr ) ;
891                 return LM_STATUS_FAILURE ;
892             }
893 
894             parse_bd_e1x->ip_hlen_w    = packet->l2pkt_tx_info->lso_ip_hdr_len >> 1;
895             parse_bd_e1x->global_data |= (( (eth_hlen) >> 1) << ETH_TX_PARSE_BD_E1X_IP_HDR_START_OFFSET_W_SHIFT);
896             parse_bd_e1x->total_hlen_w = mm_cpu_to_le16((packet->l2pkt_tx_info->lso_ip_hdr_len >> 1) + ( (eth_hlen) >> 1));
897 
898             if(packet->l2pkt_tx_info->flags & LM_TX_FLAG_TCP_LSO_SNAP_FRAME) {
899                 parse_bd_e1x->global_data |= ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN;
900             }
901 
902             if (packet->l2pkt_tx_info->flags & LM_TX_FLAG_COMPUTE_TCP_UDP_CKSUM)
903             {
904                 parse_bd_e1x->tcp_pseudo_csum = mm_cpu_to_le16(packet->l2pkt_tx_info->tcp_pseudo_csum);
905                 parse_bd_e1x->global_data     |= (packet->l2pkt_tx_info->tcp_nonce_sum_bit << ETH_TX_PARSE_BD_E1X_NS_FLG_SHIFT);
906                 parse_bd_e1x->total_hlen_w     = mm_cpu_to_le16((total_hlen_bytes) >> 1);
907             }
908 
909         } else {
910             struct eth_tx_parse_bd_e2 *parse_bd_e2 = parse_bd_ptr;
911             u32_t val;
912 
913             // TCP header Offset in WORDs from start of packet
914             if (is_encapsulated_offload)
915             {
916                 val = (( packet->l2pkt_tx_info->encap_packet_inner_frame_offset +
917                          packet->l2pkt_tx_info->encap_packet_inner_ip_relative_offset +
918                          packet->l2pkt_tx_info->encap_packet_inner_tcp_relative_offset ) >> 1 );
919 
920                 /* set if the inner ip header is ipv6 with extension headers */
921                 if (packet->l2pkt_tx_info->encap_packet_inner_tcp_relative_offset > 40) {
922                     parse_bd_e2->parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
923                 }
924             }
925             else
926             {
927                 val = ((packet->l2pkt_tx_info->lso_ip_hdr_len + eth_hlen) >> 1);
928 
929                 if (packet->l2pkt_tx_info->lso_ip_hdr_len > 40) {
930                     parse_bd_e2->parsing_data |= ETH_TX_PARSE_BD_E2_IPV6_WITH_EXT_HDR;
931                 }
932             }
933 
934             parse_bd_e2->parsing_data |= ETH_TX_PARSE_BD_E2_L4_HDR_START_OFFSET_W & (val << ETH_TX_PARSE_BD_E2_L4_HDR_START_OFFSET_W_SHIFT);
935 
936             val = (packet->l2pkt_tx_info->lso_tcp_hdr_len >> 2);
937             parse_bd_e2->parsing_data |= ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW & (val << ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT);
938 
939             parse_bd_e2->parsing_data = mm_cpu_to_le32(parse_bd_e2->parsing_data);
940         }
941     }
942 
943     if  ((!is_encapsulated_offload) &&
944         ((!CHIP_IS_E1x(pdev) || IS_VFDEV(pdev))))
945     {
946         struct eth_tx_parse_bd_e2 *parse_bd_e2 = parse_bd_ptr;
947 
948         ecore_set_fw_mac_addr(&parse_bd_e2->data.mac_addr.dst_hi,
949                               &parse_bd_e2->data.mac_addr.dst_mid,
950                               &parse_bd_e2->data.mac_addr.dst_lo,
951                               packet->l2pkt_tx_info->dst_mac_addr);
952         ecore_set_fw_mac_addr(&parse_bd_e2->data.mac_addr.src_hi,
953                               &parse_bd_e2->data.mac_addr.src_mid,
954                               &parse_bd_e2->data.mac_addr.src_lo,
955                               packet->l2pkt_tx_info->src_mac_addr);
956         if (pdev->params.mac_spoof_test) {
957             parse_bd_e2->data.mac_addr.src_lo++;
958         }
959 
960     }
961 
962     /* set dst addr type, if different from unicast */
963     if (IS_ETH_MULTICAST(packet->l2pkt_tx_info->dst_mac_addr))
964     {
965         if (IS_ETH_BROADCAST(packet->l2pkt_tx_info->dst_mac_addr))
966         {
967             eth_addr_type = BROADCAST_ADDRESS;
968         }
969         else
970         {
971             eth_addr_type = MULTICAST_ADDRESS;
972         }
973 
974         if (CHIP_IS_E1x(pdev))
975         {
976             struct eth_tx_parse_bd_e1x *parse_bd_e1x = parse_bd_ptr;
977             RESET_FLAGS(parse_bd_e1x->global_data, ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE);
978             parse_bd_e1x->global_data |= (eth_addr_type << ETH_TX_PARSE_BD_E1X_ETH_ADDR_TYPE_SHIFT);
979         }
980         else
981         {
982             struct eth_tx_parse_bd_e2 *parse_bd_e2 = parse_bd_ptr;
983             RESET_FLAGS(parse_bd_e2->parsing_data, ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE);
984             parse_bd_e2->parsing_data |= (eth_addr_type << ETH_TX_PARSE_BD_E2_ETH_ADDR_TYPE_SHIFT);
985         }
986     }
987 
988     // Save the number of BDs used.  Later we need to add this value back
989     // to tx_chain->bd_left when the packet is sent.
990     packet->u1.tx.bd_used = start_bd_nbd += (u16_t)frags->cnt;
991 
992     packet->u1.tx.next_bd_idx = lm_bd_chain_prod_idx(&tx_chain->bd_chain);
993     tx_chain->prod_bseq += packet->size;
994 
995     /* There is a PBF limitation on minimum packet size (9B)
996      * We assert since we do not expect packet length < 14 */
997     DbgBreakIfFastPath(packet->size < ETHERNET_PACKET_HEADER_SIZE);
998 
999 #if DBG
1000     for(cnt = 0; cnt < start_bd_nbd; cnt++)
1001     {
1002         if (parse_bd_ptr && (cnt == 1))
1003         {
1004             if (CHIP_IS_E1x(pdev))
1005             {
1006                 DbgMessage(pdev, VERBOSEl2tx,
1007                             "   parse_bd: global_data 0x%x",
1008                             ((struct eth_tx_parse_bd_e1x *)(&start_bd[cnt]))->global_data);
1009             }
1010             else /* E2 */
1011             {
1012                 DbgMessage(pdev, VERBOSEl2tx,
1013                             "   parse_bd: parsing_data 0x%08x",
1014                             mm_le32_to_cpu(((struct eth_tx_parse_bd_e2 *)(&start_bd[cnt]))->parsing_data));
1015             }
1016         }
1017         else
1018     {
1019         DbgMessage(pdev, VERBOSEl2tx,
1020                         "-> frag: %d, bd_flags: %d, nbytes: %d, hi: 0x%x, lo: 0x%x",
1021                         cnt, start_bd[cnt].bd_flags.as_bitfield, mm_le16_to_cpu(start_bd[cnt].nbytes),
1022                         mm_le32_to_cpu(start_bd[cnt].addr_hi), mm_le32_to_cpu(start_bd[cnt].addr_lo));
1023         if (cnt == 0)
1024         {
1025             DbgMessage(pdev, VERBOSEl2tx,
1026                             "      start bd info: nbds: %d, vlan: 0x%x, hdr_nbds: %d",
1027                             start_bd_nbd, mm_le16_to_cpu(start_bd->vlan_or_ethertype),
1028                             (start_bd->general_data & ETH_TX_START_BD_HDR_NBDS));
1029             }
1030         }
1031     }
1032 #endif
1033 
1034     start_bd->nbd = mm_cpu_to_le16(start_bd_nbd);
1035 
1036     s_list_push_tail(&tx_chain->active_descq, &packet->link);
1037 
1038     //in case of a packet consisting of 1 frag only, but with the use of parsing info BD,
1039     //the last_bd will point to the START BD!
1040     //this is since we need to mark both the START & END on the START BD.
1041     //Only the start BD can fill the flags and we always have 2 BDs.
1042 
1043     // Debug message on the parsed_bd
1044     //DbgMessage(pdev, INFORM, "lm_send_packet() parse_bd: total_hlen %d ip_hlen %d lso_mss %d tcp_flags 0x%x\n",
1045     //        parse_bd->total_hlen, parse_bd->ip_hlen, parse_bd->lso_mss, parse_bd->tcp_flags);
1046     //DbgMessage(pdev, INFORM, "lm_send_packet() start_bd: bd_flags 0x%x\n",start_bd->bd_flags);
1047 
1048     // Make sure that the BD data is updated before updating the producer
1049     // since FW might read the BD right after the producer is updated.
1050     // This is only applicable for weak-ordered memory model archs such
1051     // as IA-64, The following barrier is also mandatory since FW will
1052     // assumes packets must have BDs
1053     //order is crucial in case of preemption
1054     pdev->tx_info.chain[chain_idx].eth_tx_prods.bds_prod = pdev->tx_info.chain[chain_idx].eth_tx_prods.bds_prod +
1055                                 S16_SUB(lm_bd_chain_prod_idx(&tx_chain->bd_chain), old_prod_idx);
1056     pdev->tx_info.chain[chain_idx].eth_tx_prods.packets_prod = pdev->tx_info.chain[chain_idx].eth_tx_prods.packets_prod + 1;
1057 
1058     //DB
1059     dq_msg.header.data  = DOORBELL_HDR_T_DB_TYPE; /* tx doorbell normal doorbell type eth */
1060     dq_msg.zero_fill1   = 0;
1061     dq_msg.prod         = pdev->tx_info.chain[chain_idx].eth_tx_prods.bds_prod;
1062 
1063     // Make sure that the BD data is updated before updating the producer
1064     // since FW might read the BD right after the producer is updated.
1065     // This is only applicable for weak-ordered memory model archs such
1066     // as IA-64, The following barrier is also mandatory since FW will
1067     // assumes packets must have BDs
1068     //order is crucial in case of preemption
1069     mm_write_barrier();
1070     DOORBELL(pdev, chain_idx, *((u32_t *)&dq_msg));
1071 
1072     return LM_STATUS_SUCCESS;
1073 } /* lm_send_packet */
1074 
1075 /*******************************************************************************
1076  * Description:
1077  *
1078  * Return:
1079  ******************************************************************************/
1080 u32_t
1081 lm_get_packets_sent( struct _lm_device_t* pdev,
1082     u32_t chain_idx,
1083     s_list_t *sent_list)
1084 {
1085     lm_tx_chain_t* tx_chain = &LM_TXQ(pdev, chain_idx);
1086     lm_packet_t*   pkt      = 0;
1087     u32_t          pkt_cnt  = 0;
1088     u16_t          old_idx  = lm_bd_chain_cons_idx(&tx_chain->bd_chain);
1089 
1090     /* Get the new consumer idx.  The bd's between new_idx and old_idx
1091      * are bd's that have been consumered by the chip. */
1092     u16_t new_idx = mm_le16_to_cpu(*(tx_chain->hw_con_idx_ptr));
1093     u16_t pkt_num = S16_SUB(new_idx,tx_chain->pkt_idx);
1094 
1095     //We work here with packets granularity(pkt_idx) as opposed to Teton which
1096     //work in BDs granularity. the cons_idx is not relevant anymore in Tx chain, but
1097     //we keep it for debugging as the firmware still maintains a BD consumer.
1098 
1099 
1100 
1101     DbgBreakIfFastPath(pkt_num == 0);
1102 
1103     while(pkt_num > 0)
1104     {
1105         pkt = (lm_packet_t *) s_list_peek_head(&tx_chain->active_descq);
1106 
1107         //instead of the assert, lets check the db counter in the hw!
1108         //DbgBreakIfFastPath(pkt == NULL);
1109         if (pkt == NULL)
1110         {
1111 
1112             lm_collect_idle_storms_dorrbell_asserts(PFDEV(pdev), TRUE, TRUE, TRUE);
1113 
1114             DbgBreakIfFastPath(pkt == NULL);
1115 
1116             return pkt_cnt;
1117         }
1118 
1119         // TODO check LSO condition as in teton
1120         pkt = (lm_packet_t *) s_list_pop_head(&tx_chain->active_descq);
1121 
1122         /* Advance the old_idx to the start bd_idx of the next packet. */
1123         old_idx = pkt->u1.tx.next_bd_idx;
1124 
1125         pkt->status = LM_STATUS_SUCCESS;
1126 
1127         lm_bd_chain_bds_consumed(&tx_chain->bd_chain, pkt->u1.tx.bd_used);
1128 
1129         if (pkt->u1.tx.coalesce_buf) {
1130             /* return coalesce buffer to the chain's pool */
1131             lm_put_coalesce_buffer(pdev, tx_chain, pkt->u1.tx.coalesce_buf);
1132             pkt->u1.tx.coalesce_buf = NULL;
1133         }
1134 
1135         /* Get an updated new_idx from the status block.  The index may
1136          * end at the last BD of a page.  This BD is a pointer to the next
1137          * BD page which we need to skip over. */
1138         //TODO: need to verify that we have fairness among other protocols since we are also using the
1139         //      in_dpc_loop_cnt - so don't starve!
1140         new_idx = mm_le16_to_cpu(*(tx_chain->hw_con_idx_ptr));
1141         tx_chain->pkt_idx++;
1142         pkt_num = S16_SUB(new_idx,tx_chain->pkt_idx);
1143         pkt_cnt++;
1144         s_list_push_tail(sent_list, &pkt->link);
1145     }
1146 
1147     // TODO: currently bd_chain doesn't maintain the cons_idx...
1148     tx_chain->bd_chain.cons_idx = old_idx;
1149 
1150     DbgMessage(pdev, INFORMl2tx , "lm_get_packets_sent()- func: %d, txidx: %d, txbd con: %d txbd prod: %d \n",
1151         FUNC_ID(pdev), chain_idx , lm_bd_chain_cons_idx(&tx_chain->bd_chain), lm_bd_chain_prod_idx(&tx_chain->bd_chain));
1152 
1153     return pkt_cnt;
1154 } /* lm_get_packets_sent */
1155