LDLIBS += -lrte_bus_vdev
LDLIBS += -lrte_bus_dpaa
LDLIBS += -lrte_common_dpaax
-LDLIBS += -lrte_eal
+LDLIBS += -lrte_eal -lrte_mbuf -lrte_mempool
LDLIBS += -lrte_ethdev -lrte_kvargs
include $(RTE_SDK)/mk/rte.lib.mk
struct pfe_eth_priv_s {
struct pfe *pfe;
+ struct hif_client_s client;
int low_tmu_q;
int high_tmu_q;
struct rte_eth_dev *ndev;
fclose(svr_file);
}
+static int pfe_eth_start(struct pfe_eth_priv_s *priv)
+{
+ gpi_enable(priv->GPI_baseaddr);
+ gemac_enable(priv->EMAC_baseaddr);
+
+ return 0;
+}
+
+static void
+pfe_eth_flush_txQ(struct pfe_eth_priv_s *priv, int tx_q_num, int
+ __rte_unused from_tx, __rte_unused int n_desc)
+{
+ struct rte_mbuf *mbuf;
+ unsigned int flags;
+
+ /* Clean HIF and client queue */
+ while ((mbuf = hif_lib_tx_get_next_complete(&priv->client,
+ tx_q_num, &flags,
+ HIF_TX_DESC_NT))) {
+ if (mbuf) {
+ mbuf->next = NULL;
+ mbuf->nb_segs = 1;
+ rte_pktmbuf_free(mbuf);
+ }
+ }
+}
+
+
+static void
+pfe_eth_flush_tx(struct pfe_eth_priv_s *priv)
+{
+ unsigned int ii;
+
+ for (ii = 0; ii < emac_txq_cnt; ii++)
+ pfe_eth_flush_txQ(priv, ii, 0, 0);
+}
+
+static int
+pfe_eth_event_handler(void *data, int event, __rte_unused int qno)
+{
+ struct pfe_eth_priv_s *priv = data;
+
+ switch (event) {
+ case EVENT_TXDONE_IND:
+ pfe_eth_flush_tx(priv);
+ hif_lib_event_handler_start(&priv->client, EVENT_TXDONE_IND, 0);
+ break;
+ case EVENT_HIGH_RX_WM:
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int
+pfe_eth_open(struct rte_eth_dev *dev)
+{
+ struct pfe_eth_priv_s *priv = dev->data->dev_private;
+ struct hif_client_s *client;
+ struct hif_shm *hif_shm;
+ int rc;
+
+ /* Register client driver with HIF */
+ client = &priv->client;
+
+ if (client->pfe) {
+ hif_shm = client->pfe->hif.shm;
+ /* TODO please remove the below code of if block, once we add
+ * the proper cleanup in eth_close
+ */
+ if (!test_bit(PFE_CL_GEM0 + priv->id,
+ &hif_shm->g_client_status[0])) {
+ /* Register client driver with HIF */
+ memset(client, 0, sizeof(*client));
+ client->id = PFE_CL_GEM0 + priv->id;
+ client->tx_qn = emac_txq_cnt;
+ client->rx_qn = EMAC_RXQ_CNT;
+ client->priv = priv;
+ client->pfe = priv->pfe;
+ client->port_id = dev->data->port_id;
+ client->event_handler = pfe_eth_event_handler;
+
+ client->tx_qsize = EMAC_TXQ_DEPTH;
+ client->rx_qsize = EMAC_RXQ_DEPTH;
+
+ rc = hif_lib_client_register(client);
+ if (rc) {
+ PFE_PMD_ERR("hif_lib_client_register(%d)"
+ " failed", client->id);
+ goto err0;
+ }
+ }
+ } else {
+ /* Register client driver with HIF */
+ memset(client, 0, sizeof(*client));
+ client->id = PFE_CL_GEM0 + priv->id;
+ client->tx_qn = emac_txq_cnt;
+ client->rx_qn = EMAC_RXQ_CNT;
+ client->priv = priv;
+ client->pfe = priv->pfe;
+ client->port_id = dev->data->port_id;
+ client->event_handler = pfe_eth_event_handler;
+
+ client->tx_qsize = EMAC_TXQ_DEPTH;
+ client->rx_qsize = EMAC_RXQ_DEPTH;
+
+ rc = hif_lib_client_register(client);
+ if (rc) {
+ PFE_PMD_ERR("hif_lib_client_register(%d) failed",
+ client->id);
+ goto err0;
+ }
+ }
+ rc = pfe_eth_start(priv);
+
+err0:
+ return rc;
+}
+
static int
pfe_eth_open_cdev(struct pfe_eth_priv_s *priv)
{
}
}
+static void
+pfe_eth_stop(struct rte_eth_dev *dev/*, int wake*/)
+{
+ struct pfe_eth_priv_s *priv = dev->data->dev_private;
+
+ gemac_disable(priv->EMAC_baseaddr);
+ gpi_disable(priv->GPI_baseaddr);
+}
+
static void
pfe_eth_exit(struct rte_eth_dev *dev, struct pfe *pfe)
{
PMD_INIT_FUNC_TRACE();
+ pfe_eth_stop(dev);
/* Close the device file for link status */
pfe_eth_close_cdev(dev->data->dev_private);
pfe->nb_devs--;
}
+static void
+pfe_eth_close(struct rte_eth_dev *dev)
+{
+ if (!dev)
+ return;
+
+ if (!g_pfe)
+ return;
+
+ pfe_eth_exit(dev, g_pfe);
+
+ if (g_pfe->nb_devs == 0) {
+ pfe_hif_exit(g_pfe);
+ pfe_hif_lib_exit(g_pfe);
+ rte_free(g_pfe);
+ g_pfe = NULL;
+ }
+}
+
+static int
+pfe_eth_configure(struct rte_eth_dev *dev __rte_unused)
+{
+ return 0;
+}
+
+static int
+pfe_eth_info(struct rte_eth_dev *dev,
+ struct rte_eth_dev_info *dev_info)
+{
+ struct pfe_eth_priv_s *internals = dev->data->dev_private;
+
+ dev_info->if_index = internals->id;
+ dev_info->max_mac_addrs = PFE_MAX_MACS;
+ dev_info->max_rx_queues = dev->data->nb_rx_queues;
+ dev_info->max_tx_queues = dev->data->nb_tx_queues;
+ dev_info->min_rx_bufsize = HIF_RX_PKT_MIN_SIZE;
+ if (pfe_svr == SVR_LS1012A_REV1)
+ dev_info->max_rx_pktlen = MAX_MTU_ON_REV1 + PFE_ETH_OVERHEAD;
+ else
+ dev_info->max_rx_pktlen = JUMBO_FRAME_SIZE;
+
+ return 0;
+}
+
+static const struct eth_dev_ops ops = {
+ .dev_start = pfe_eth_open,
+ .dev_stop = pfe_eth_stop,
+ .dev_close = pfe_eth_close,
+ .dev_configure = pfe_eth_configure,
+ .dev_infos_get = pfe_eth_info,
+};
+
static int
pfe_eth_init(struct rte_vdev_device *vdev, struct pfe *pfe, int id)
{
}
eth_dev->data->mtu = 1500;
+ eth_dev->dev_ops = &ops;
+ pfe_eth_stop(eth_dev);
pfe_gemac_init(priv);
eth_dev->data->nb_rx_queues = 1;
rte_free(hif->descr_baseaddr_v);
}
+/*
+ * pfe_hif_client_register
+ *
+ * This function used to register a client driver with the HIF driver.
+ *
+ * Return value:
+ * 0 - on Successful registration
+ */
+static int
+pfe_hif_client_register(struct pfe_hif *hif, u32 client_id,
+ struct hif_client_shm *client_shm)
+{
+ struct hif_client *client = &hif->client[client_id];
+ u32 i, cnt;
+ struct rx_queue_desc *rx_qbase;
+ struct tx_queue_desc *tx_qbase;
+ struct hif_rx_queue *rx_queue;
+ struct hif_tx_queue *tx_queue;
+ int err = 0;
+
+ PMD_INIT_FUNC_TRACE();
+
+ rte_spinlock_lock(&hif->tx_lock);
+
+ if (test_bit(client_id, &hif->shm->g_client_status[0])) {
+ PFE_PMD_ERR("client %d already registered", client_id);
+ err = -1;
+ goto unlock;
+ }
+
+ memset(client, 0, sizeof(struct hif_client));
+
+ /* Initialize client Rx queues baseaddr, size */
+
+ cnt = CLIENT_CTRL_RX_Q_CNT(client_shm->ctrl);
+ /* Check if client is requesting for more queues than supported */
+ if (cnt > HIF_CLIENT_QUEUES_MAX)
+ cnt = HIF_CLIENT_QUEUES_MAX;
+
+ client->rx_qn = cnt;
+ rx_qbase = (struct rx_queue_desc *)client_shm->rx_qbase;
+ for (i = 0; i < cnt; i++) {
+ rx_queue = &client->rx_q[i];
+ rx_queue->base = rx_qbase + i * client_shm->rx_qsize;
+ rx_queue->size = client_shm->rx_qsize;
+ rx_queue->write_idx = 0;
+ }
+
+ /* Initialize client Tx queues baseaddr, size */
+ cnt = CLIENT_CTRL_TX_Q_CNT(client_shm->ctrl);
+
+ /* Check if client is requesting for more queues than supported */
+ if (cnt > HIF_CLIENT_QUEUES_MAX)
+ cnt = HIF_CLIENT_QUEUES_MAX;
+
+ client->tx_qn = cnt;
+ tx_qbase = (struct tx_queue_desc *)client_shm->tx_qbase;
+ for (i = 0; i < cnt; i++) {
+ tx_queue = &client->tx_q[i];
+ tx_queue->base = tx_qbase + i * client_shm->tx_qsize;
+ tx_queue->size = client_shm->tx_qsize;
+ tx_queue->ack_idx = 0;
+ }
+
+ set_bit(client_id, &hif->shm->g_client_status[0]);
+
+unlock:
+ rte_spinlock_unlock(&hif->tx_lock);
+
+ return err;
+}
+
+/*
+ * pfe_hif_client_unregister
+ *
+ * This function used to unregister a client from the HIF driver.
+ *
+ */
+static void
+pfe_hif_client_unregister(struct pfe_hif *hif, u32 client_id)
+{
+ PMD_INIT_FUNC_TRACE();
+
+ /*
+ * Mark client as no longer available (which prevents further packet
+ * receive for this client)
+ */
+ rte_spinlock_lock(&hif->tx_lock);
+
+ if (!test_bit(client_id, &hif->shm->g_client_status[0])) {
+ PFE_PMD_ERR("client %d not registered", client_id);
+
+ rte_spinlock_unlock(&hif->tx_lock);
+ return;
+ }
+
+ clear_bit(client_id, &hif->shm->g_client_status[0]);
+
+ rte_spinlock_unlock(&hif->tx_lock);
+}
+
+void
+hif_process_client_req(struct pfe_hif *hif, int req,
+ int data1, __rte_unused int data2)
+{
+ unsigned int client_id = data1;
+
+ if (client_id >= HIF_CLIENTS_MAX) {
+ PFE_PMD_ERR("client id %d out of bounds", client_id);
+ return;
+ }
+
+ switch (req) {
+ case REQUEST_CL_REGISTER:
+ /* Request for register a client */
+ PFE_PMD_INFO("register client_id %d", client_id);
+ pfe_hif_client_register(hif, client_id, (struct
+ hif_client_shm *)&hif->shm->client[client_id]);
+ break;
+
+ case REQUEST_CL_UNREGISTER:
+ PFE_PMD_INFO("unregister client_id %d", client_id);
+
+ /* Request for unregister a client */
+ pfe_hif_client_unregister(hif, client_id);
+
+ break;
+
+ default:
+ PFE_PMD_ERR("unsupported request %d", req);
+ break;
+ }
+
+ /*
+ * Process client Tx queues
+ * Currently we don't have checking for tx pending
+ */
+}
+
#if defined(LS1012A_PFE_RESET_WA)
static void
pfe_hif_disable_rx_desc(struct pfe_hif *hif)
#define HIF_RX_DESC_NT 64
#define HIF_TX_DESC_NT 2048
+#define HIF_FIRST_BUFFER BIT(0)
+#define HIF_LAST_BUFFER BIT(1)
+#define HIF_DONT_DMA_MAP BIT(2)
+#define HIF_DATA_VALID BIT(3)
+#define HIF_TSO BIT(4)
+
enum {
PFE_CL_GEM0 = 0,
PFE_CL_GEM1,
u16 flags;
};
+struct hif_hdr {
+ u8 client_id;
+ u8 q_num;
+ u16 client_ctrl;
+ u16 client_ctrl1;
+};
+
+struct __hif_hdr {
+ union {
+ struct hif_hdr hdr;
+ u32 word[2];
+ };
+};
+
+struct hif_ipsec_hdr {
+ u16 sa_handle[2];
+} __packed;
+
+struct pfe_parse {
+ unsigned int packet_type;
+ uint16_t hash;
+ uint16_t parse_incomplete;
+ unsigned long long ol_flags;
+};
+
+/* HIF_CTRL_TX... defines */
+#define HIF_CTRL_TX_CHECKSUM BIT(2)
+
+/* HIF_CTRL_RX... defines */
+#define HIF_CTRL_RX_OFFSET_OFST (24)
+#define HIF_CTRL_RX_CHECKSUMMED BIT(2)
+#define HIF_CTRL_RX_CONTINUED BIT(1)
+
struct pfe_hif {
/* To store registered clients in hif layer */
struct hif_client client[HIF_CLIENTS_MAX];
struct rte_device *dev;
};
+void hif_process_client_req(struct pfe_hif *hif, int req, int data1, int
+ data2);
int pfe_hif_init(struct pfe *pfe);
void pfe_hif_exit(struct pfe *pfe);
void pfe_hif_rx_idle(struct pfe_hif *hif);
#include "pfe_logs.h"
#include "pfe_mod.h"
+unsigned int emac_txq_cnt;
+
+/*
+ * @pfe_hal_lib.c
+ * Common functions used by HIF client drivers
+ */
+
+/*HIF shared memory Global variable */
+struct hif_shm ghif_shm;
+
+/*This function sends indication to HIF driver
+ *
+ * @param[in] hif hif context
+ */
+static void
+hif_lib_indicate_hif(struct pfe_hif *hif, int req, int data1, int
+ data2)
+{
+ hif_process_client_req(hif, req, data1, data2);
+}
+
+void
+hif_lib_indicate_client(struct hif_client_s *client, int event_type,
+ int qno)
+{
+ if (!client || event_type >= HIF_EVENT_MAX ||
+ qno >= HIF_CLIENT_QUEUES_MAX)
+ return;
+
+ if (!test_and_set_bit(qno, &client->queue_mask[event_type]))
+ client->event_handler(client->priv, event_type, qno);
+}
+
+/*This function releases Rx queue descriptors memory and pre-filled buffers
+ *
+ * @param[in] client hif_client context
+ */
+static void
+hif_lib_client_release_rx_buffers(struct hif_client_s *client)
+{
+ struct rte_mempool *pool;
+ struct rte_pktmbuf_pool_private *mb_priv;
+ struct rx_queue_desc *desc;
+ unsigned int qno, ii;
+ void *buf;
+
+ pool = client->pfe->hif.shm->pool;
+ mb_priv = rte_mempool_get_priv(pool);
+ for (qno = 0; qno < client->rx_qn; qno++) {
+ desc = client->rx_q[qno].base;
+
+ for (ii = 0; ii < client->rx_q[qno].size; ii++) {
+ buf = (void *)desc->data;
+ if (buf) {
+ /* Data pointor to mbuf pointor calculation:
+ * "Data - User private data - headroom - mbufsize"
+ * Actual data pointor given to HIF BDs was
+ * "mbuf->data_offset - PFE_PKT_HEADER_SZ"
+ */
+ buf = buf + PFE_PKT_HEADER_SZ
+ - sizeof(struct rte_mbuf)
+ - RTE_PKTMBUF_HEADROOM
+ - mb_priv->mbuf_priv_size;
+ rte_pktmbuf_free((struct rte_mbuf *)buf);
+ desc->ctrl = 0;
+ }
+ desc++;
+ }
+ }
+ rte_free(client->rx_qbase);
+}
+
+/*This function allocates memory for the rxq descriptors and pre-fill rx queues
+ * with buffers.
+ * @param[in] client client context
+ * @param[in] q_size size of the rxQ, all queues are of same size
+ */
+static int
+hif_lib_client_init_rx_buffers(struct hif_client_s *client,
+ int q_size)
+{
+ struct rx_queue_desc *desc;
+ struct hif_client_rx_queue *queue;
+ unsigned int ii, qno;
+
+ /*Allocate memory for the client queues */
+ client->rx_qbase = rte_malloc(NULL, client->rx_qn * q_size *
+ sizeof(struct rx_queue_desc), RTE_CACHE_LINE_SIZE);
+ if (!client->rx_qbase)
+ goto err;
+
+ for (qno = 0; qno < client->rx_qn; qno++) {
+ queue = &client->rx_q[qno];
+
+ queue->base = client->rx_qbase + qno * q_size * sizeof(struct
+ rx_queue_desc);
+ queue->size = q_size;
+ queue->read_idx = 0;
+ queue->write_idx = 0;
+ queue->queue_id = 0;
+ queue->port_id = client->port_id;
+ queue->priv = client->priv;
+ PFE_PMD_DEBUG("rx queue: %d, base: %p, size: %d\n", qno,
+ queue->base, queue->size);
+ }
+
+ for (qno = 0; qno < client->rx_qn; qno++) {
+ queue = &client->rx_q[qno];
+ desc = queue->base;
+
+ for (ii = 0; ii < queue->size; ii++) {
+ desc->ctrl = CL_DESC_OWN;
+ desc++;
+ }
+ }
+
+ return 0;
+
+err:
+ return 1;
+}
+
+
+static void
+hif_lib_client_cleanup_tx_queue(struct hif_client_tx_queue *queue)
+{
+ /*
+ * Check if there are any pending packets. Client must flush the tx
+ * queues before unregistering, by calling by calling
+ * hif_lib_tx_get_next_complete()
+ *
+ * Hif no longer calls since we are no longer registered
+ */
+ if (queue->tx_pending)
+ PFE_PMD_ERR("pending transmit packet");
+}
+
+static void
+hif_lib_client_release_tx_buffers(struct hif_client_s *client)
+{
+ unsigned int qno;
+
+ for (qno = 0; qno < client->tx_qn; qno++)
+ hif_lib_client_cleanup_tx_queue(&client->tx_q[qno]);
+
+ rte_free(client->tx_qbase);
+}
+
+static int
+hif_lib_client_init_tx_buffers(struct hif_client_s *client, int
+ q_size)
+{
+ struct hif_client_tx_queue *queue;
+ unsigned int qno;
+
+ client->tx_qbase = rte_malloc(NULL, client->tx_qn * q_size *
+ sizeof(struct tx_queue_desc), RTE_CACHE_LINE_SIZE);
+ if (!client->tx_qbase)
+ return 1;
+
+ for (qno = 0; qno < client->tx_qn; qno++) {
+ queue = &client->tx_q[qno];
+
+ queue->base = client->tx_qbase + qno * q_size * sizeof(struct
+ tx_queue_desc);
+ queue->size = q_size;
+ queue->read_idx = 0;
+ queue->write_idx = 0;
+ queue->tx_pending = 0;
+ queue->nocpy_flag = 0;
+ queue->prev_tmu_tx_pkts = 0;
+ queue->done_tmu_tx_pkts = 0;
+ queue->priv = client->priv;
+ queue->queue_id = 0;
+ queue->port_id = client->port_id;
+
+ PFE_PMD_DEBUG("tx queue: %d, base: %p, size: %d", qno,
+ queue->base, queue->size);
+ }
+
+ return 0;
+}
+
+static int
+hif_lib_event_dummy(__rte_unused void *priv,
+ __rte_unused int event_type, __rte_unused int qno)
+{
+ return 0;
+}
+
int
-pfe_hif_lib_init(__rte_unused struct pfe *pfe)
+hif_lib_client_register(struct hif_client_s *client)
{
+ struct hif_shm *hif_shm;
+ struct hif_client_shm *client_shm;
+ int err, i;
+
PMD_INIT_FUNC_TRACE();
+ /*Allocate memory before spin_lock*/
+ if (hif_lib_client_init_rx_buffers(client, client->rx_qsize)) {
+ err = -ENOMEM;
+ goto err_rx;
+ }
+
+ if (hif_lib_client_init_tx_buffers(client, client->tx_qsize)) {
+ err = -ENOMEM;
+ goto err_tx;
+ }
+
+ rte_spinlock_lock(&client->pfe->hif.lock);
+ if (!(client->pfe) || client->id >= HIF_CLIENTS_MAX ||
+ client->pfe->hif_client[client->id]) {
+ err = -EINVAL;
+ goto err;
+ }
+
+ hif_shm = client->pfe->hif.shm;
+
+ if (!client->event_handler)
+ client->event_handler = hif_lib_event_dummy;
+
+ /*Initialize client specific shared memory */
+ client_shm = (struct hif_client_shm *)&hif_shm->client[client->id];
+ client_shm->rx_qbase = (unsigned long)client->rx_qbase;
+ client_shm->rx_qsize = client->rx_qsize;
+ client_shm->tx_qbase = (unsigned long)client->tx_qbase;
+ client_shm->tx_qsize = client->tx_qsize;
+ client_shm->ctrl = (client->tx_qn << CLIENT_CTRL_TX_Q_CNT_OFST) |
+ (client->rx_qn << CLIENT_CTRL_RX_Q_CNT_OFST);
+
+ for (i = 0; i < HIF_EVENT_MAX; i++) {
+ client->queue_mask[i] = 0; /*
+ * By default all events are
+ * unmasked
+ */
+ }
+
+ /*Indicate to HIF driver*/
+ hif_lib_indicate_hif(&client->pfe->hif, REQUEST_CL_REGISTER,
+ client->id, 0);
+
+ PFE_PMD_DEBUG("client: %p, client_id: %d, tx_qsize: %d, rx_qsize: %d",
+ client, client->id, client->tx_qsize, client->rx_qsize);
+
+ client->cpu_id = -1;
+
+ client->pfe->hif_client[client->id] = client;
+ rte_spinlock_unlock(&client->pfe->hif.lock);
+
+ return 0;
+
+err:
+ rte_spinlock_unlock(&client->pfe->hif.lock);
+ hif_lib_client_release_tx_buffers(client);
+
+err_tx:
+ hif_lib_client_release_rx_buffers(client);
+
+err_rx:
+ return err;
+}
+
+int
+hif_lib_client_unregister(struct hif_client_s *client)
+{
+ struct pfe *pfe = client->pfe;
+ u32 client_id = client->id;
+
+ PFE_PMD_INFO("client: %p, client_id: %d, txQ_depth: %d, rxQ_depth: %d",
+ client, client->id, client->tx_qsize, client->rx_qsize);
+
+ rte_spinlock_lock(&pfe->hif.lock);
+ hif_lib_indicate_hif(&pfe->hif, REQUEST_CL_UNREGISTER, client->id, 0);
+
+ hif_lib_client_release_tx_buffers(client);
+ hif_lib_client_release_rx_buffers(client);
+ pfe->hif_client[client_id] = NULL;
+ rte_spinlock_unlock(&pfe->hif.lock);
+
+ return 0;
+}
+
+int
+hif_lib_event_handler_start(struct hif_client_s *client, int event,
+ int qno)
+{
+ struct hif_client_rx_queue *queue = &client->rx_q[qno];
+ struct rx_queue_desc *desc = queue->base + queue->read_idx;
+
+ if (event >= HIF_EVENT_MAX || qno >= HIF_CLIENT_QUEUES_MAX) {
+ PFE_PMD_WARN("Unsupported event : %d queue number : %d",
+ event, qno);
+ return -1;
+ }
+
+ test_and_clear_bit(qno, &client->queue_mask[event]);
+
+ switch (event) {
+ case EVENT_RX_PKT_IND:
+ if (!(desc->ctrl & CL_DESC_OWN))
+ hif_lib_indicate_client(client,
+ EVENT_RX_PKT_IND, qno);
+ break;
+
+ case EVENT_HIGH_RX_WM:
+ case EVENT_TXDONE_IND:
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+void *
+hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno,
+ unsigned int *flags, __rte_unused int count)
+{
+ struct hif_client_tx_queue *queue = &client->tx_q[qno];
+ struct tx_queue_desc *desc = queue->base + queue->read_idx;
+
+ PFE_DP_LOG(DEBUG, "qno : %d rd_indx: %d pending:%d",
+ qno, queue->read_idx, queue->tx_pending);
+
+ if (!queue->tx_pending)
+ return NULL;
+
+ if (queue->nocpy_flag && !queue->done_tmu_tx_pkts) {
+ u32 tmu_tx_pkts = 0;
+
+ if (queue->prev_tmu_tx_pkts > tmu_tx_pkts)
+ queue->done_tmu_tx_pkts = UINT_MAX -
+ queue->prev_tmu_tx_pkts + tmu_tx_pkts;
+ else
+ queue->done_tmu_tx_pkts = tmu_tx_pkts -
+ queue->prev_tmu_tx_pkts;
+
+ queue->prev_tmu_tx_pkts = tmu_tx_pkts;
+
+ if (!queue->done_tmu_tx_pkts)
+ return NULL;
+ }
+
+ if (desc->ctrl & CL_DESC_OWN)
+ return NULL;
+
+ queue->read_idx = (queue->read_idx + 1) & (queue->size - 1);
+ queue->tx_pending--;
+
+ *flags = CL_DESC_GET_FLAGS(desc->ctrl);
+
+ if (queue->done_tmu_tx_pkts && (*flags & HIF_LAST_BUFFER))
+ queue->done_tmu_tx_pkts--;
+
+ return desc->data;
+}
+
+int
+pfe_hif_lib_init(struct pfe *pfe)
+{
+ PMD_INIT_FUNC_TRACE();
+
+ emac_txq_cnt = EMAC_TXQ_CNT;
+ pfe->hif.shm = &ghif_shm;
+
return 0;
}
#ifndef _PFE_HIF_LIB_H_
#define _PFE_HIF_LIB_H_
+#include "pfe_hif.h"
+
#define HIF_CL_REQ_TIMEOUT 10
#define GFP_DMA_PFE 0
int pfe_hif_lib_init(struct pfe *pfe);
void pfe_hif_lib_exit(struct pfe *pfe);
+int hif_lib_client_register(struct hif_client_s *client);
+int hif_lib_client_unregister(struct hif_client_s *client);
+void hif_lib_indicate_client(struct hif_client_s *client, int event, int data);
+int hif_lib_event_handler_start(struct hif_client_s *client, int event, int
+ data);
+void *hif_lib_tx_get_next_complete(struct hif_client_s *client, int qno,
+ unsigned int *flags, int count);
+int pfe_hif_shm_init(struct hif_shm *hif_shm, struct rte_mempool *mb_pool);
+void pfe_hif_shm_clean(struct hif_shm *hif_shm);
#endif /* _PFE_HIF_LIB_H_ */
struct ls1012a_pfe_platform_data platform_data;
struct pfe_hif hif;
struct pfe_eth eth;
+ struct hif_client_s *hif_client[HIF_CLIENTS_MAX];
int mdio_muxval[PHYID_MAX_VAL];
uint8_t nb_devs;
uint8_t max_intf;