static void vmxnet3_process_tx_queue(VMXNET3State *s, int qidx)

{

    struct Vmxnet3_TxDesc txd;

    uint32_t txd_idx;

    uint32_t data_len;

    hwaddr data_pa;



    for (;;) {

        if (!vmxnet3_pop_next_tx_descr(s, qidx, &txd, &txd_idx)) {

            break;

        }



        vmxnet3_dump_tx_descr(&txd);



        if (!s->skip_current_tx_pkt) {

            data_len = (txd.len > 0) ? txd.len : VMXNET3_MAX_TX_BUF_SIZE;

            data_pa = le64_to_cpu(txd.addr);



            if (!net_tx_pkt_add_raw_fragment(s->tx_pkt,

                                                data_pa,

                                                data_len)) {

                s->skip_current_tx_pkt = true;

            }

        }



        if (s->tx_sop) {

            vmxnet3_tx_retrieve_metadata(s, &txd);

            s->tx_sop = false;

        }



        if (txd.eop) {

            if (!s->skip_current_tx_pkt && net_tx_pkt_parse(s->tx_pkt)) {

                if (s->needs_vlan) {

                    net_tx_pkt_setup_vlan_header(s->tx_pkt, s->tci);

                }



                vmxnet3_send_packet(s, qidx);

            } else {

                vmxnet3_on_tx_done_update_stats(s, qidx,

                                                VMXNET3_PKT_STATUS_ERROR);

            }



            vmxnet3_complete_packet(s, qidx, txd_idx);

            s->tx_sop = true;

            s->skip_current_tx_pkt = false;

            net_tx_pkt_reset(s->tx_pkt);

        }

    }

}
