int rx_produce(World *world, uint32_t pport,

               const struct iovec *iov, int iovcnt, uint8_t copy_to_cpu)

{

    Rocker *r = world_rocker(world);

    PCIDevice *dev = (PCIDevice *)r;

    DescRing *ring = rocker_get_rx_ring_by_pport(r, pport);

    DescInfo *info = desc_ring_fetch_desc(ring);

    char *data;

    size_t data_size = iov_size(iov, iovcnt);

    char *buf;

    uint16_t rx_flags = 0;

    uint16_t rx_csum = 0;

    size_t tlv_size;

    RockerTlv *tlvs[ROCKER_TLV_RX_MAX + 1];

    hwaddr frag_addr;

    uint16_t frag_max_len;

    int pos;

    int err;



    if (!info) {

        return -ROCKER_ENOBUFS;

    }



    buf = desc_get_buf(info, false);

    if (!buf) {

        err = -ROCKER_ENXIO;

        goto out;

    }

    rocker_tlv_parse(tlvs, ROCKER_TLV_RX_MAX, buf, desc_tlv_size(info));



    if (!tlvs[ROCKER_TLV_RX_FRAG_ADDR] ||

        !tlvs[ROCKER_TLV_RX_FRAG_MAX_LEN]) {

        err = -ROCKER_EINVAL;

        goto out;

    }



    frag_addr = rocker_tlv_get_le64(tlvs[ROCKER_TLV_RX_FRAG_ADDR]);

    frag_max_len = rocker_tlv_get_le16(tlvs[ROCKER_TLV_RX_FRAG_MAX_LEN]);



    if (data_size > frag_max_len) {

        err = -ROCKER_EMSGSIZE;

        goto out;

    }



    if (copy_to_cpu) {

        rx_flags |= ROCKER_RX_FLAGS_FWD_OFFLOAD;

    }



    /* XXX calc rx flags/csum */



    tlv_size = rocker_tlv_total_size(sizeof(uint16_t)) + /* flags */

               rocker_tlv_total_size(sizeof(uint16_t)) + /* scum */

               rocker_tlv_total_size(sizeof(uint64_t)) + /* frag addr */

               rocker_tlv_total_size(sizeof(uint16_t)) + /* frag max len */

               rocker_tlv_total_size(sizeof(uint16_t));  /* frag len */



    if (tlv_size > desc_buf_size(info)) {

        err = -ROCKER_EMSGSIZE;

        goto out;

    }



    /* TODO:

     * iov dma write can be optimized in similar way e1000 does it in

     * e1000_receive_iov. But maybe if would make sense to introduce

     * generic helper iov_dma_write.

     */



    data = g_malloc(data_size);

    if (!data) {

        err = -ROCKER_ENOMEM;

        goto out;

    }

    iov_to_buf(iov, iovcnt, 0, data, data_size);

    pci_dma_write(dev, frag_addr, data, data_size);

    g_free(data);



    pos = 0;

    rocker_tlv_put_le16(buf, &pos, ROCKER_TLV_RX_FLAGS, rx_flags);

    rocker_tlv_put_le16(buf, &pos, ROCKER_TLV_RX_CSUM, rx_csum);

    rocker_tlv_put_le64(buf, &pos, ROCKER_TLV_RX_FRAG_ADDR, frag_addr);

    rocker_tlv_put_le16(buf, &pos, ROCKER_TLV_RX_FRAG_MAX_LEN, frag_max_len);

    rocker_tlv_put_le16(buf, &pos, ROCKER_TLV_RX_FRAG_LEN, data_size);



    err = desc_set_buf(info, tlv_size);



out:

    if (desc_ring_post_desc(ring, err)) {

        rocker_msix_irq(r, ROCKER_MSIX_VEC_RX(pport - 1));

    }



    return err;

}

int rx_produce(World *world, uint32_t pport,

               const struct iovec *iov, int iovcnt, uint8_t copy_to_cpu)

{

    Rocker *r = world_rocker(world);

    PCIDevice *dev = (PCIDevice *)r;

    DescRing *ring = rocker_get_rx_ring_by_pport(r, pport);

    DescInfo *info = desc_ring_fetch_desc(ring);

    char *data;

    size_t data_size = iov_size(iov, iovcnt);

    char *buf;

    uint16_t rx_flags = 0;

    uint16_t rx_csum = 0;

    size_t tlv_size;

    RockerTlv *tlvs[ROCKER_TLV_RX_MAX + 1];

    hwaddr frag_addr;

    uint16_t frag_max_len;

    int pos;

    int err;



    if (!info) {

        return -ROCKER_ENOBUFS;

    }



    buf = desc_get_buf(info, false);

    if (!buf) {

        err = -ROCKER_ENXIO;

        goto out;

    }

    rocker_tlv_parse(tlvs, ROCKER_TLV_RX_MAX, buf, desc_tlv_size(info));



    if (!tlvs[ROCKER_TLV_RX_FRAG_ADDR] ||

        !tlvs[ROCKER_TLV_RX_FRAG_MAX_LEN]) {

        err = -ROCKER_EINVAL;

        goto out;

    }



    frag_addr = rocker_tlv_get_le64(tlvs[ROCKER_TLV_RX_FRAG_ADDR]);

    frag_max_len = rocker_tlv_get_le16(tlvs[ROCKER_TLV_RX_FRAG_MAX_LEN]);



    if (data_size > frag_max_len) {

        err = -ROCKER_EMSGSIZE;

        goto out;

    }



    if (copy_to_cpu) {

        rx_flags |= ROCKER_RX_FLAGS_FWD_OFFLOAD;

    }



    



    tlv_size = rocker_tlv_total_size(sizeof(uint16_t)) + 

               rocker_tlv_total_size(sizeof(uint16_t)) + 

               rocker_tlv_total_size(sizeof(uint64_t)) + 

               rocker_tlv_total_size(sizeof(uint16_t)) + 

               rocker_tlv_total_size(sizeof(uint16_t));  



    if (tlv_size > desc_buf_size(info)) {

        err = -ROCKER_EMSGSIZE;

        goto out;

    }



    











    data = g_malloc(data_size);

    if (!data) {

        err = -ROCKER_ENOMEM;

        goto out;

    }

    iov_to_buf(iov, iovcnt, 0, data, data_size);

    pci_dma_write(dev, frag_addr, data, data_size);

    g_free(data);



    pos = 0;

    rocker_tlv_put_le16(buf, &pos, ROCKER_TLV_RX_FLAGS, rx_flags);

    rocker_tlv_put_le16(buf, &pos, ROCKER_TLV_RX_CSUM, rx_csum);

    rocker_tlv_put_le64(buf, &pos, ROCKER_TLV_RX_FRAG_ADDR, frag_addr);

    rocker_tlv_put_le16(buf, &pos, ROCKER_TLV_RX_FRAG_MAX_LEN, frag_max_len);

    rocker_tlv_put_le16(buf, &pos, ROCKER_TLV_RX_FRAG_LEN, data_size);



    err = desc_set_buf(info, tlv_size);



out:

    if (desc_ring_post_desc(ring, err)) {

        rocker_msix_irq(r, ROCKER_MSIX_VEC_RX(pport - 1));

    }



    return err;

}

    if (!data) {         err = -ROCKER_ENOMEM;         goto out;     if (!buf) {         err = -ROCKER_ENOMEM;
int FUNC_0(World *VAR_0, uint32_t VAR_1,

               const struct iovec *VAR_2, int VAR_3, uint8_t VAR_4)

{

    Rocker *r = world_rocker(VAR_0);

    PCIDevice *dev = (PCIDevice *)r;

    DescRing *ring = rocker_get_rx_ring_by_pport(r, VAR_1);

    DescInfo *info = desc_ring_fetch_desc(ring);

    char *VAR_5;

    size_t data_size = iov_size(VAR_2, VAR_3);

    char *VAR_6;

    uint16_t rx_flags = 0;

    uint16_t rx_csum = 0;

    size_t tlv_size;

    RockerTlv *tlvs[ROCKER_TLV_RX_MAX + 1];

    hwaddr frag_addr;

    uint16_t frag_max_len;

    int VAR_7;

    int VAR_8;



    if (!info) {

        return -ROCKER_ENOBUFS;

    }



    VAR_6 = desc_get_buf(info, false);

    if (!VAR_6) {

        VAR_8 = -ROCKER_ENXIO;

        goto out;

    }

    rocker_tlv_parse(tlvs, ROCKER_TLV_RX_MAX, VAR_6, desc_tlv_size(info));



    if (!tlvs[ROCKER_TLV_RX_FRAG_ADDR] ||

        !tlvs[ROCKER_TLV_RX_FRAG_MAX_LEN]) {

        VAR_8 = -ROCKER_EINVAL;

        goto out;

    }



    frag_addr = rocker_tlv_get_le64(tlvs[ROCKER_TLV_RX_FRAG_ADDR]);

    frag_max_len = rocker_tlv_get_le16(tlvs[ROCKER_TLV_RX_FRAG_MAX_LEN]);



    if (data_size > frag_max_len) {

        VAR_8 = -ROCKER_EMSGSIZE;

        goto out;

    }



    if (VAR_4) {

        rx_flags |= ROCKER_RX_FLAGS_FWD_OFFLOAD;

    }



    



    tlv_size = rocker_tlv_total_size(sizeof(uint16_t)) + 

               rocker_tlv_total_size(sizeof(uint16_t)) + 

               rocker_tlv_total_size(sizeof(uint64_t)) + 

               rocker_tlv_total_size(sizeof(uint16_t)) + 

               rocker_tlv_total_size(sizeof(uint16_t));  



    if (tlv_size > desc_buf_size(info)) {

        VAR_8 = -ROCKER_EMSGSIZE;

        goto out;

    }



    











    VAR_5 = g_malloc(data_size);

    if (!VAR_5) {

        VAR_8 = -ROCKER_ENOMEM;

        goto out;

    }

    iov_to_buf(VAR_2, VAR_3, 0, VAR_5, data_size);

    pci_dma_write(dev, frag_addr, VAR_5, data_size);

    g_free(VAR_5);



    VAR_7 = 0;

    rocker_tlv_put_le16(VAR_6, &VAR_7, ROCKER_TLV_RX_FLAGS, rx_flags);

    rocker_tlv_put_le16(VAR_6, &VAR_7, ROCKER_TLV_RX_CSUM, rx_csum);

    rocker_tlv_put_le64(VAR_6, &VAR_7, ROCKER_TLV_RX_FRAG_ADDR, frag_addr);

    rocker_tlv_put_le16(VAR_6, &VAR_7, ROCKER_TLV_RX_FRAG_MAX_LEN, frag_max_len);

    rocker_tlv_put_le16(VAR_6, &VAR_7, ROCKER_TLV_RX_FRAG_LEN, data_size);



    VAR_8 = desc_set_buf(info, tlv_size);



out:

    if (desc_ring_post_desc(ring, VAR_8)) {

        rocker_msix_irq(r, ROCKER_MSIX_VEC_RX(VAR_1 - 1));

    }



    return VAR_8;

}

int FUNC_0(World *VAR_0, uint32_t VAR_1,
const struct iovec *VAR_2, int VAR_3, uint8_t VAR_4)
{ Rocker *r = world_rocker(VAR_0); PCIDevice *dev = (PCIDevice *)r; DescRing *ring = rocker_get_rx_ring_by_pport(r, VAR_1); DescInfo *info = desc_ring_fetch_desc(ring); char *VAR_5; size_t data_size = iov_size(VAR_2, VAR_3); char *VAR_6; uint16_t rx_flags = 0; uint16_t rx_csum = 0; size_t tlv_size; RockerTlv *tlvs[ROCKER_TLV_RX_MAX + 1]; hwaddr frag_addr; uint16_t frag_max_len; int VAR_7; int VAR_8; if (!info) { return -ROCKER_ENOBUFS; } VAR_6 = desc_get_buf(info, false); if (!VAR_6) { VAR_8 = -ROCKER_ENXIO; goto out; } rocker_tlv_parse(tlvs, ROCKER_TLV_RX_MAX, VAR_6, desc_tlv_size(info)); if (!tlvs[ROCKER_TLV_RX_FRAG_ADDR] ||
!tlvs[ROCKER_TLV_RX_FRAG_MAX_LEN]) { VAR_8 = -ROCKER_EINVAL; goto out; } frag_addr = rocker_tlv_get_le64(tlvs[ROCKER_TLV_RX_FRAG_ADDR]); frag_max_len = rocker_tlv_get_le16(tlvs[ROCKER_TLV_RX_FRAG_MAX_LEN]); if (data_size > frag_max_len) { VAR_8 = -ROCKER_EMSGSIZE; goto out; } if (VAR_4) { rx_flags |= ROCKER_RX_FLAGS_FWD_OFFLOAD; } tlv_size = rocker_tlv_total_size(sizeof(uint16_t)) +
rocker_tlv_total_size(sizeof(uint16_t)) +
rocker_tlv_total_size(sizeof(uint64_t)) +
rocker_tlv_total_size(sizeof(uint16_t)) +
rocker_tlv_total_size(sizeof(uint16_t)); if (tlv_size > desc_buf_size(info)) { VAR_8 = -ROCKER_EMSGSIZE; goto out; } VAR_5 = g_malloc(data_size); if (!VAR_5) { VAR_8 = -ROCKER_ENOMEM; goto out; } iov_to_buf(VAR_2, VAR_3, 0, VAR_5, data_size); pci_dma_write(dev, frag_addr, VAR_5, data_size); g_free(VAR_5); VAR_7 = 0; rocker_tlv_put_le16(VAR_6, &VAR_7, ROCKER_TLV_RX_FLAGS, rx_flags); rocker_tlv_put_le16(VAR_6, &VAR_7, ROCKER_TLV_RX_CSUM, rx_csum); rocker_tlv_put_le64(VAR_6, &VAR_7, ROCKER_TLV_RX_FRAG_ADDR, frag_addr); rocker_tlv_put_le16(VAR_6, &VAR_7, ROCKER_TLV_RX_FRAG_MAX_LEN, frag_max_len); rocker_tlv_put_le16(VAR_6, &VAR_7, ROCKER_TLV_RX_FRAG_LEN, data_size); VAR_8 = desc_set_buf(info, tlv_size); out:
if (desc_ring_post_desc(ring, VAR_8)) { rocker_msix_irq(r, ROCKER_MSIX_VEC_RX(VAR_1 - 1)); } return VAR_8; }