Commit 7ec0596f authored by Ioana Radulescu's avatar Ioana Radulescu Committed by Greg Kroah-Hartman

staging: fsl-dpaa2/eth: Use affine DPIO services

Use the newly added DPIO service API to map cpu-affine DPIO services
to channels.

The DPAA2 Ethernet driver already had mappings of frame queues and
channels to cpus, but had no control over the DPIOs used. We can
now ensure full affinity of hotpath hardware resources to cores,
which improves performance and almost eliminates some resource
contentions (e.g. enqueue/dequeue busy counters should be close to
zero from now on).

Making the pull channel operation core affine brings the most
significant benefits. This ensures the same DPIO service will be
used for all dequeue commands issued for a certain frame queue,
which is in line with the way hardware is optimized.

Additionally, we also use affine DPIOs for the frame enqueue and
buffer release operations in order to avoid resource contention.
dpaa2_io_service_register() and dpaa2_io_service_rearm()
functions receive an affine DPIO as argument mostly for uniformity,
but this doesn't change the previous functionality.
Signed-off-by: default avatarIoana Radulescu <ruxandra.radulescu@nxp.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1f495383
...@@ -597,7 +597,8 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev) ...@@ -597,7 +597,8 @@ static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
queue_mapping = skb_get_queue_mapping(skb); queue_mapping = skb_get_queue_mapping(skb);
fq = &priv->fq[queue_mapping]; fq = &priv->fq[queue_mapping];
for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) { for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) {
err = dpaa2_io_service_enqueue_qd(NULL, priv->tx_qdid, 0, err = dpaa2_io_service_enqueue_qd(fq->channel->dpio,
priv->tx_qdid, 0,
fq->tx_qdbin, &fd); fq->tx_qdbin, &fd);
if (err != -EBUSY) if (err != -EBUSY)
break; break;
...@@ -719,7 +720,8 @@ static void free_bufs(struct dpaa2_eth_priv *priv, u64 *buf_array, int count) ...@@ -719,7 +720,8 @@ static void free_bufs(struct dpaa2_eth_priv *priv, u64 *buf_array, int count)
/* Perform a single release command to add buffers /* Perform a single release command to add buffers
* to the specified buffer pool * to the specified buffer pool
*/ */
static int add_bufs(struct dpaa2_eth_priv *priv, u16 bpid) static int add_bufs(struct dpaa2_eth_priv *priv,
struct dpaa2_eth_channel *ch, u16 bpid)
{ {
struct device *dev = priv->net_dev->dev.parent; struct device *dev = priv->net_dev->dev.parent;
u64 buf_array[DPAA2_ETH_BUFS_PER_CMD]; u64 buf_array[DPAA2_ETH_BUFS_PER_CMD];
...@@ -753,7 +755,7 @@ static int add_bufs(struct dpaa2_eth_priv *priv, u16 bpid) ...@@ -753,7 +755,7 @@ static int add_bufs(struct dpaa2_eth_priv *priv, u16 bpid)
release_bufs: release_bufs:
/* In case the portal is busy, retry until successful */ /* In case the portal is busy, retry until successful */
while ((err = dpaa2_io_service_release(NULL, bpid, while ((err = dpaa2_io_service_release(ch->dpio, bpid,
buf_array, i)) == -EBUSY) buf_array, i)) == -EBUSY)
cpu_relax(); cpu_relax();
...@@ -794,7 +796,7 @@ static int seed_pool(struct dpaa2_eth_priv *priv, u16 bpid) ...@@ -794,7 +796,7 @@ static int seed_pool(struct dpaa2_eth_priv *priv, u16 bpid)
for (j = 0; j < priv->num_channels; j++) { for (j = 0; j < priv->num_channels; j++) {
for (i = 0; i < DPAA2_ETH_NUM_BUFS; for (i = 0; i < DPAA2_ETH_NUM_BUFS;
i += DPAA2_ETH_BUFS_PER_CMD) { i += DPAA2_ETH_BUFS_PER_CMD) {
new_count = add_bufs(priv, bpid); new_count = add_bufs(priv, priv->channel[j], bpid);
priv->channel[j]->buf_count += new_count; priv->channel[j]->buf_count += new_count;
if (new_count < DPAA2_ETH_BUFS_PER_CMD) { if (new_count < DPAA2_ETH_BUFS_PER_CMD) {
...@@ -852,7 +854,7 @@ static int refill_pool(struct dpaa2_eth_priv *priv, ...@@ -852,7 +854,7 @@ static int refill_pool(struct dpaa2_eth_priv *priv,
return 0; return 0;
do { do {
new_count = add_bufs(priv, bpid); new_count = add_bufs(priv, ch, bpid);
if (unlikely(!new_count)) { if (unlikely(!new_count)) {
/* Out of memory; abort for now, we'll try later on */ /* Out of memory; abort for now, we'll try later on */
break; break;
...@@ -873,7 +875,8 @@ static int pull_channel(struct dpaa2_eth_channel *ch) ...@@ -873,7 +875,8 @@ static int pull_channel(struct dpaa2_eth_channel *ch)
/* Retry while portal is busy */ /* Retry while portal is busy */
do { do {
err = dpaa2_io_service_pull_channel(NULL, ch->ch_id, ch->store); err = dpaa2_io_service_pull_channel(ch->dpio, ch->ch_id,
ch->store);
dequeues++; dequeues++;
cpu_relax(); cpu_relax();
} while (err == -EBUSY); } while (err == -EBUSY);
...@@ -923,7 +926,7 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget) ...@@ -923,7 +926,7 @@ static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
if (cleaned < budget && napi_complete_done(napi, cleaned)) { if (cleaned < budget && napi_complete_done(napi, cleaned)) {
/* Re-enable data available notifications */ /* Re-enable data available notifications */
do { do {
err = dpaa2_io_service_rearm(NULL, &ch->nctx); err = dpaa2_io_service_rearm(ch->dpio, &ch->nctx);
cpu_relax(); cpu_relax();
} while (err == -EBUSY); } while (err == -EBUSY);
WARN_ONCE(err, "CDAN notifications rearm failed on core %d", WARN_ONCE(err, "CDAN notifications rearm failed on core %d",
...@@ -1531,7 +1534,8 @@ static int setup_dpio(struct dpaa2_eth_priv *priv) ...@@ -1531,7 +1534,8 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
nctx->desired_cpu = i; nctx->desired_cpu = i;
/* Register the new context */ /* Register the new context */
err = dpaa2_io_service_register(NULL, nctx); channel->dpio = dpaa2_io_service_select(i);
err = dpaa2_io_service_register(channel->dpio, nctx);
if (err) { if (err) {
dev_dbg(dev, "No affine DPIO for cpu %d\n", i); dev_dbg(dev, "No affine DPIO for cpu %d\n", i);
/* If no affine DPIO for this core, there's probably /* If no affine DPIO for this core, there's probably
...@@ -1571,7 +1575,7 @@ static int setup_dpio(struct dpaa2_eth_priv *priv) ...@@ -1571,7 +1575,7 @@ static int setup_dpio(struct dpaa2_eth_priv *priv)
return 0; return 0;
err_set_cdan: err_set_cdan:
dpaa2_io_service_deregister(NULL, nctx); dpaa2_io_service_deregister(channel->dpio, nctx);
err_service_reg: err_service_reg:
free_channel(priv, channel); free_channel(priv, channel);
err_alloc_ch: err_alloc_ch:
...@@ -1594,7 +1598,7 @@ static void free_dpio(struct dpaa2_eth_priv *priv) ...@@ -1594,7 +1598,7 @@ static void free_dpio(struct dpaa2_eth_priv *priv)
/* deregister CDAN notifications and free channels */ /* deregister CDAN notifications and free channels */
for (i = 0; i < priv->num_channels; i++) { for (i = 0; i < priv->num_channels; i++) {
ch = priv->channel[i]; ch = priv->channel[i];
dpaa2_io_service_deregister(NULL, &ch->nctx); dpaa2_io_service_deregister(ch->dpio, &ch->nctx);
free_channel(priv, ch); free_channel(priv, ch);
} }
} }
......
...@@ -288,6 +288,7 @@ struct dpaa2_eth_channel { ...@@ -288,6 +288,7 @@ struct dpaa2_eth_channel {
int ch_id; int ch_id;
int dpio_id; int dpio_id;
struct napi_struct napi; struct napi_struct napi;
struct dpaa2_io *dpio;
struct dpaa2_io_store *store; struct dpaa2_io_store *store;
struct dpaa2_eth_priv *priv; struct dpaa2_eth_priv *priv;
int buf_count; int buf_count;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment