static void ldpaa_eth_rx(struct ldpaa_eth_priv *priv, const struct dpaa_fd *fd) { u64 fd_addr; uint16_t fd_offset; uint32_t fd_length; struct ldpaa_fas *fas; uint32_t status, err; u32 timeo = (CONFIG_SYS_HZ * 2) / 1000; u32 time_start; struct qbman_release_desc releasedesc; struct qbman_swp *swp = dflt_dpio->sw_portal; fd_addr = ldpaa_fd_get_addr(fd); fd_offset = ldpaa_fd_get_offset(fd); fd_length = ldpaa_fd_get_len(fd); debug("Rx frame:data addr=0x%p size=0x%x\n", (u64 *)fd_addr, fd_length); if (fd->simple.frc & LDPAA_FD_FRC_FASV) { /* Read the frame annotation status word and check for errors */ fas = (struct ldpaa_fas *) ((uint8_t *)(fd_addr) + dflt_dpni->buf_layout.private_data_size); status = le32_to_cpu(fas->status); if (status & LDPAA_ETH_RX_ERR_MASK) { printf("Rx frame error(s): 0x%08x\n", status & LDPAA_ETH_RX_ERR_MASK); goto error; } else if (status & LDPAA_ETH_RX_UNSUPP_MASK) { printf("Unsupported feature in bitmask: 0x%08x\n", status & LDPAA_ETH_RX_UNSUPP_MASK); goto error; } } debug("Rx frame: To Upper layer\n"); net_process_received_packet((uint8_t *)(fd_addr) + fd_offset, fd_length); error: flush_dcache_range(fd_addr, fd_addr + LDPAA_ETH_RX_BUFFER_SIZE); qbman_release_desc_clear(&releasedesc); qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); time_start = get_timer(0); do { /* Release buffer into the QBMAN */ err = qbman_swp_release(swp, &releasedesc, &fd_addr, 1); } while (get_timer(time_start) < timeo && err == -EBUSY); if (err == -EBUSY) printf("Rx frame: QBMAN buffer release fails\n"); return; }
/** * dpaa2_io_service_release() - Release buffers to a buffer pool. * @d: the given DPIO object. * @bpid: the buffer pool id. * @buffers: the buffers to be released. * @num_buffers: the number of the buffers to be released. * * Return 0 for success, and negative error code for failure. */ int dpaa2_io_service_release(struct dpaa2_io *d, u32 bpid, const u64 *buffers, unsigned int num_buffers) { struct qbman_release_desc rd; d = service_select(d); if (!d) return -ENODEV; qbman_release_desc_clear(&rd); qbman_release_desc_set_bpid(&rd, bpid); return qbman_swp_release(d->swp, &rd, buffers, num_buffers); }
static int ldpaa_bp_add_7(uint16_t bpid) { uint64_t buf_array[7]; u8 *addr; int i; struct qbman_release_desc rd; for (i = 0; i < 7; i++) { addr = memalign(LDPAA_ETH_BUF_ALIGN, LDPAA_ETH_RX_BUFFER_SIZE); if (!addr) { printf("addr allocation failed\n"); goto err_alloc; } memset(addr, 0x00, LDPAA_ETH_RX_BUFFER_SIZE); flush_dcache_range((u64)addr, (u64)(addr + LDPAA_ETH_RX_BUFFER_SIZE)); buf_array[i] = (uint64_t)addr; debug("Release: buffer addr =0x%p\n", addr); } release_bufs: /* In case the portal is busy, retry until successful. * This function is guaranteed to succeed in a reasonable amount * of time. */ do { mdelay(1); qbman_release_desc_clear(&rd); qbman_release_desc_set_bpid(&rd, bpid); } while (qbman_swp_release(dflt_dpio->sw_portal, &rd, buf_array, i)); return i; err_alloc: if (i) goto release_bufs; return 0; }
static int ldpaa_eth_tx(struct eth_device *net_dev, void *buf, int len) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; struct dpaa_fd fd; u64 buffer_start; int data_offset, err; u32 timeo = (CONFIG_SYS_HZ * 10) / 1000; u32 time_start; struct qbman_swp *swp = dflt_dpio->sw_portal; struct qbman_eq_desc ed; struct qbman_release_desc releasedesc; /* Setup the FD fields */ memset(&fd, 0, sizeof(fd)); data_offset = priv->tx_data_offset; do { err = qbman_swp_acquire(dflt_dpio->sw_portal, dflt_dpbp->dpbp_attr.bpid, &buffer_start, 1); } while (err == -EBUSY); if (err < 0) { printf("qbman_swp_acquire() failed\n"); return -ENOMEM; } debug("TX data: malloc buffer start=0x%p\n", (u64 *)buffer_start); memcpy(((uint8_t *)(buffer_start) + data_offset), buf, len); flush_dcache_range(buffer_start, buffer_start + LDPAA_ETH_RX_BUFFER_SIZE); ldpaa_fd_set_addr(&fd, (u64)buffer_start); ldpaa_fd_set_offset(&fd, (uint16_t)(data_offset)); ldpaa_fd_set_bpid(&fd, dflt_dpbp->dpbp_attr.bpid); ldpaa_fd_set_len(&fd, len); fd.simple.ctrl = LDPAA_FD_CTRL_ASAL | LDPAA_FD_CTRL_PTA | LDPAA_FD_CTRL_PTV1; qbman_eq_desc_clear(&ed); qbman_eq_desc_set_no_orp(&ed, 0); qbman_eq_desc_set_qd(&ed, priv->tx_qdid, priv->tx_flow_id, 0); time_start = get_timer(0); while (get_timer(time_start) < timeo) { err = qbman_swp_enqueue(swp, &ed, (const struct qbman_fd *)(&fd)); if (err != -EBUSY) break; } if (err < 0) { printf("error enqueueing Tx frame\n"); goto error; } return err; error: qbman_release_desc_clear(&releasedesc); qbman_release_desc_set_bpid(&releasedesc, dflt_dpbp->dpbp_attr.bpid); time_start = get_timer(0); do { /* Release buffer into the QBMAN */ err = qbman_swp_release(swp, &releasedesc, &buffer_start, 1); } while (get_timer(time_start) < timeo && err == -EBUSY); if (err == -EBUSY) printf("TX data: QBMAN buffer release fails\n"); return err; }