From e588172442093fe22374dc1bfc88a7da751d6b30 Mon Sep 17 00:00:00 2001
From: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Date: Tue, 15 Sep 2015 10:14:16 -0500
Subject: [PATCH 201/226] staging: dpaa2-eth: initial commit of dpaa2-eth
 driver

commit 3106ece5d96784b63a4eabb26661baaefedd164f
[context adjustment]

This is a commit of a squash of the cumulative dpaa2-eth patches
in the sdk 2.0 kernel as of 3/7/2016.

flib,dpaa2-eth: flib header update (Rebasing onto kernel 3.19, MC 0.6)

this patch was moved from 4.0 branch

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
[Stuart: split into multiple patches]
Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>
Integrated-by: Jilong Guo <jilong.guo@nxp.com>

flib,dpaa2-eth: updated Eth (was: Rebasing onto kernel 3.19, MC 0.6)

updated Ethernet driver from 4.0 branch

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
[Stuart: cherry-picked patch from 4.0 and split it up]
Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>

Conflicts:

	drivers/staging/Makefile

Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>

dpaa2-eth: Adjust 'options' size

The 'options' field of various MC configuration structures has changed
from u64 to u32 as of MC firmware version 7.0.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I9ba0c19fc22f745e6be6cc40862afa18fa3ac3db
Reviewed-on: http://git.am.freescale.net:8181/35579
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Selectively disable preemption

Temporary workaround for a MC Bus API quirk which only allows us to
specify exclusively, either a spinlock-protected MC Portal, or a
mutex-protected one, but then tries to match the runtime context in
order to enforce their usage.

Te Be Reverted.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: Ida2ec1fdbdebfd2e427f96ddad7582880146fda9
Reviewed-on: http://git.am.freescale.net:8181/35580
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Fix ethtool bug

We were writing beyond the end of the allocated data area for ethtool
statistics.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Change-Id: I6b77498a78dad06970508ebbed7144be73854f7f
Reviewed-on: http://git.am.freescale.net:8181/35583
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Retry read if store unexpectedly empty

After we place a volatile dequeue command, we might get to inquire the
store before the DMA has actually completed. In such cases, we must
retry, lest we'll have the store overwritten by the next legitimate
volatile dequeue.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I314fbb8b4d9f589715e42d35fc6677d726b8f5ba
Reviewed-on: http://git.am.freescale.net:8181/35584
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

flib: Fix "missing braces around initializer" warning

Gcc does not support (yet?) the ={0} initializer in the case of an array
of structs. Fixing the Flib in order to make the warning go away.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I8782ecb714c032cfeeecf4c8323cf9dbb702b10f
Reviewed-on: http://git.am.freescale.net:8181/35586
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
Tested-by: Stuart Yoder <stuart.yoder@freescale.com>

Revert "dpaa2-eth: Selectively disable preemption"

This reverts commit e1455823c33b8dd48b5d2d50a7e8a11d3934cc0d.

dpaa2-eth: Fix memory leak

A buffer kmalloc'ed at probe time was not freed after it was no
longer needed.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Change-Id: Iba197209e9203ed306449729c6dcd23ec95f094d
Reviewed-on: http://git.am.freescale.net:8181/35756
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Remove unused field in ldpaa_eth_priv structure

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Change-Id: I124c3e4589b6420b1ea5cc05a03a51ea938b2bea
Reviewed-on: http://git.am.freescale.net:8181/35757
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Fix "NOHZ: local_softirq_pending" warning

Explicitly run softirqs after we enable NAPI. This in particular gets us
rid of the "NOHZ: local_softirq_pending" warnings, but it also solves a
couple of other problems, among which fluctuating performance and high
ping latencies.

Notes:
 - This will prevent us from timely processing notifications and
other "non-frame events" coming into the software portal. So far,
though, we only expect Dequeue Available Notifications, so this patch
is good enough for now.
 - A degradation in console responsiveness is expected, especially in
cases where the bottom-half runs on the same CPU as the console.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Change-Id: Ia6f11da433024e80ee59e821c9eabfa5068df5e5
Reviewed-on: http://git.am.freescale.net:8181/35830
Reviewed-by: Alexandru Marginean <Alexandru.Marginean@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
Tested-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Add polling mode for link state changes

Add the Kconfigurable option of using a thread for polling on
the link state instead of relying on interrupts from the MC.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Change-Id: If2fe66fc5c0fbee2568d7afa15d43ea33f92e8e2
Reviewed-on: http://git.am.freescale.net:8181/35967
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Update copyright years.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I7e00eecfc5569027c908124726edaf06be357c02
Reviewed-on: http://git.am.freescale.net:8181/37666
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Ruxandra Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Drain bpools when netdev is down

In a data path layout with potentially a dozen interfaces, not all of
them may be up at the same time, yet they may consume a fair amount of
buffer space.
Drain the buffer pool upon ifdown and re-seed it at ifup.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I24a379b643c8b5161a33b966c3314cf91024ed4a
Reviewed-on: http://git.am.freescale.net:8181/37667
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Ruxandra Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Interrupts cleanup

Add the code for cleaning up interrupts on driver removal.
This was lost during transition from kernel 3.16 to 3.19.

Also, there's no need to call devm_free_irq() if probe fails
as the kernel will release all driver resources.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Change-Id: Ifd404bbf399d5ba62e2896371076719c1d6b4214
Reviewed-on: http://git.am.freescale.net:8181/36199
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Reviewed-by: Bharat Bhushan <Bharat.Bhushan@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
Reviewed-on: http://git.am.freescale.net:8181/37690

dpaa2-eth: Ethtool support for hashing

Only one set of header fields is supported for all protocols, the driver
silently replaces previous configuration regardless of user selected
protocol.
Following fields are supported:
	L2DA
	VLAN tag
	L3 proto
	IP SA
	IP DA
	L4 bytes 0 & 1 [TCP/UDP src port]
	L4 bytes 2 & 3 [TCP/UDP dst port]

Signed-off-by: Alex Marginean <alexandru.marginean@freescale.com>

Change-Id: I97c9dac1b842fe6bc7115e40c08c42f67dee8c9c
Reviewed-on: http://git.am.freescale.net:8181/37260
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Fix maximum number of FQs

The maximum number of Rx/Tx conf FQs associated to a DPNI was not
updated when the implementation changed. It just happened to work
by accident.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I03e30e0121a40d0d15fcdc4bee1fb98caa17c0ef
Reviewed-on: http://git.am.freescale.net:8181/37668
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Fix Rx buffer address alignment

We need to align the start address of the Rx buffers to
LDPAA_ETH_BUF_ALIGN bytes. We were using SMP_CACHE_BYTES instead.
It happened to work because both defines have the value of 64,
but this may change at some point.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I08a0f3f18f82c5581c491bd395e3ad066b25bcf5
Reviewed-on: http://git.am.freescale.net:8181/37669
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Add buffer count to ethtool statistics

Print the number of buffers available in the pool for a certain DPNI
along with the rest of the ethtool -S stats.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: Ia1f5cf341c8414ae2058a73f6bc81490ef134592
Reviewed-on: http://git.am.freescale.net:8181/37671
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Add Rx error queue

Add a Kconfigurable option that allows Rx error frames to be
enqueued on an error FQ. By default error frames are discarded,
but for debug purposes we may want to process them at driver
level.

Note: Checkpatch issues a false positive about complex macros that
should be parenthesized.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I7d19d00b5d5445514ebd112c886ce8ccdbb1f0da
Reviewed-on: http://git.am.freescale.net:8181/37672
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
Tested-by: Stuart Yoder <stuart.yoder@freescale.com>

staging: fsl-dpaa2: FLib headers cleanup

Going with the flow of moving fsl-dpaa2 headers into the drivers'
location rather than keeping them all in one place.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: Ia2870cd019a4934c7835d38752a46b2a0045f30e
Reviewed-on: http://git.am.freescale.net:8181/37674
Reviewed-by: Ruxandra Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
Tested-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Klocwork fixes

Fix several issues reported by Klocwork.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I1e23365765f3b0ff9b6474d8207df7c1f2433ccd
Reviewed-on: http://git.am.freescale.net:8181/37675
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Probe devices with no hash support

Don't fail at probe if the DPNI doesn't have the hash distribution
option enabled. Instead, initialize a single Rx frame queue and
use it for all incoming traffic.

Rx flow hashing configuration through ethtool will not work
in this case.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: Iaf17e05b15946e6901c39a21b5344b89e9f1d797
Reviewed-on: http://git.am.freescale.net:8181/37676
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Process frames in IRQ context

Stop using threaded IRQs and move back to hardirq top-halves.
This is the first patch of a small series adapting the DPIO and Ethernet
code to these changes.

Signed-off-by: Roy Pledge <roy.pledge@freescale.com>
Tested-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Tested-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
[Stuart: split dpio and eth into separate patches, updated subject]
Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Fix bug in NAPI poll

We incorrectly rearmed FQDAN notifications at the end of a NAPI cycle,
regardless of whether the NAPI budget was consumed or not. We only need
to rearm notifications if the NAPI cycle cleaned less frames than its
budget, otherwise a new NAPI poll will be scheduled anyway.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: Ib55497bdbd769047420b3150668f2e2aef3c93f6
Reviewed-on: http://git.am.freescale.net:8181/38317
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Use dma_map_sg on Tx

Use the simpler dma_map_sg() along with the scatterlist API if the
egress frame is scatter-gather, at the cost of keeping some extra
information in the frame's software annotation area.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: If293aeabbd58d031f21456704357d4ff7e53c559
Reviewed-on: http://git.am.freescale.net:8181/37681
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Reduce retries if Tx portal busy

Too many retries due to Tx portal contention led to a significant cycle
waste and reduction in performance.
Reducing the number of enqueue retries and dropping frame if eventually
unsuccessful.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: Ib111ec61cd4294a7632348c25fa3d7f4002be0c0
Reviewed-on: http://git.am.freescale.net:8181/37682
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Add sysfs support for TxConf affinity change

This adds support in sysfs for affining Tx Confirmation queues to GPPs,
via the affine DPIO objects.

The user can specify a cpu list in /sys/class/net/ni<X>/txconf_affinity
to which the Ethernet driver will affine the TxConf FQs, in round-robin
fashion. This is naturally a bit coarse, because there is no "official"
mapping of the transmitting CPUs to Tx Confirmation queues.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I4b3da632e202ceeb22986c842d746aafe2a87a81
Reviewed-on: http://git.am.freescale.net:8181/37684
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Implement ndo_select_queue

Use a very simple selection function for the egress FQ. The purpose
behind this is to more evenly distribute Tx Confirmation traffic,
especially in the case of multiple egress flows, when bundling it all on
CPU 0 would make that CPU a bottleneck.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: Ibfe8aad7ad5c719cc95d7817d7de6d2094f0f7ed
Reviewed-on: http://git.am.freescale.net:8181/37685
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Reduce TxConf NAPI weight back to 64

It turns out that not only the kernel frowned upon the old budget of 256,
but the measured values were well below that anyway.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I62ddd3ea1dbfd8b51e2bcb2286e0d5eb10ac7f27
Reviewed-on: http://git.am.freescale.net:8181/37688
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Try refilling the buffer pool less often

We used to check if the buffer pool needs refilling at each Rx
frame. Instead, do that check (and the actual buffer release if
needed) only after a pull dequeue.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Change-Id: Id52fab83873c40a711b8cadfcf909eb7e2e210f3
Reviewed-on: http://git.am.freescale.net:8181/38318
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Stay in NAPI if exact budget is met

An off-by-one bug would cause premature exiting from the NAPI cycle.
Performance degradation is particularly severe in IPFWD cases.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Tested-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I9de2580c7ff8e46cbca9613890b03737add35e26
Reviewed-on: http://git.am.freescale.net:8181/37908
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Minor changes to FQ stats

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Change-Id: I0ced0e7b2eee28599cdea79094336c0d44f0d32b
Reviewed-on: http://git.am.freescale.net:8181/38319
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Support fewer DPIOs than CPUs

The previous DPIO functions would transparently choose a (perhaps
non-affine) CPU if the required CPU was not available. Now that their API
contract is enforced, we must make an explicit request for *any* DPIO if
the request for an *affine* DPIO has failed.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: Ib08047ffa33518993b1ffa4671d0d4f36d6793d0
Reviewed-on: http://git.am.freescale.net:8181/38320
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Roy Pledge <roy.pledge@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: cosmetic changes in hashing code

Signed-off-by: Alex Marginean <alexandru.marginean@freescale.com>
Change-Id: I79e21a69a6fb68cdbdb8d853c059661f8988dbf9
Reviewed-on: http://git.am.freescale.net:8181/37258
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Prefetch data before initial access

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Change-Id: Ie8f0163651aea7e3e197a408f89ca98d296d4b8b
Reviewed-on: http://git.am.freescale.net:8181/38753
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Use netif_receive_skb

netif_rx() is a leftover since our pre-NAPI codebase.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Change-Id: I02ff0a059862964df1bf81b247853193994c2dfe
Reviewed-on: http://git.am.freescale.net:8181/38754
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Use napi_alloc_frag() on Rx.

A bit better-suited than netdev_alloc_frag().

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Change-Id: I8863a783502db963e5dc968f049534c36ad484e2
Reviewed-on: http://git.am.freescale.net:8181/38755
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Silence skb_realloc_headroom() warning

pktgen tests tend to be too noisy because pktgen does not observe the
net device's needed_headroom specification and we used to be pretty loud
about that. We'll print the warning message just once.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I3c12eba29c79aa9c487307d367f6d9f4dbe447a3
Reviewed-on: http://git.am.freescale.net:8181/38756
Reviewed-by: Ruxandra Ioana Radulescu <ruxandra.radulescu@freescale.com>
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Print message upon device unplugging

Give a console notification when a DPNI is unplugged. This is useful for
automated tests to know the operation (which is not instantaneous) has
finished.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: If33033201fcee7671ad91c2b56badf3fb56a9e3e
Reviewed-on: http://git.am.freescale.net:8181/38757
Reviewed-by: Ruxandra Ioana Radulescu <ruxandra.radulescu@freescale.com>
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Add debugfs support

Add debugfs entries for showing detailed per-CPU and per-FQ
counters for each network interface. Also add a knob for
resetting these stats.
The agregated interface statistics were already available through
ethtool -S.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I55f5bfe07a15b0d1bf0c6175d8829654163a4318
Reviewed-on: http://git.am.freescale.net:8181/38758
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
Tested-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: limited support for flow steering

Steering is supported on a sub-set of fields, including DMAC, IP SRC
and DST, L4 ports.
Steering and hashing configurations depend on each other, that makes
the whole thing tricky to configure.  Currently FS can be configured
using only the fields selected for hashing and all the hashing fields
must be included in the match key - masking doesn't work yet.

Signed-off-by: Alex Marginean <alexandru.marginean@freescale.com>
Change-Id: I9fa3199f7818a9a5f9d69d3483ffd839056cc468
Reviewed-on: http://git.am.freescale.net:8181/38759
Reviewed-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Ruxandra Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Rename files into the dpaa2 nomenclature

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I1c3d62e2f19a59d4b65727234fd7df2dfd8683d9
Reviewed-on: http://git.am.freescale.net:8181/38965
Reviewed-by: Alexandru Marginean <Alexandru.Marginean@freescale.com>
Reviewed-by: Ruxandra Ioana Radulescu <ruxandra.radulescu@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>
Tested-by: Stuart Yoder <stuart.yoder@freescale.com>

staging: dpaa2-eth: migrated remaining flibs for MC fw 8.0.0

Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
[Stuart: split eth part into separate patch, updated subject]
Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Clear 'backup_pool' attribute

New MC-0.7 firmware allows specifying an alternate buffer pool, but we
are momentarily not using that feature.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Change-Id: I0a6e6626512b7bbddfef732c71f1400b67f3e619
Reviewed-on: http://git.am.freescale.net:8181/39149
Tested-by: Review Code-CDREVIEW <CDREVIEW@freescale.com>
Reviewed-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Do programing of MSIs in devm_request_threaded_irq()

With the new dprc_set_obj_irq() we can now program MSIS in the device
in the callback invoked from devm_request_threaded_irq().
Since this callback is invoked with interrupts disabled, we need to
use an atomic portal, instead of the root DPRC's built-in portal
which is non-atomic.

Signed-off-by: Itai Katz <itai.katz@freescale.com>
Signed-off-by: J. German Rivera <German.Rivera@freescale.com>
[Stuart: split original patch into multiple patches]
Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com>

dpaa2-eth: Do not map beyond skb tail

On Tx do dma_map only until skb->tail, rather than skb->end.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Declare NETIF_F_LLTX as a capability

We are effectively doing lock-less Tx.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Avoid bitcopy of 'backpointers' struct

Make 'struct ldpaa_eth_swa bps' a pointer and void copying it on both Tx
and TxConf.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Use CDANs instead of FQDANs

Use Channel Dequeue Available Notifications (CDANs) instead of
Frame Queue notifications. We allocate a QMan channel (or DPCON
object) for each available cpu and assign to it the Rx and Tx conf
queues associated with that cpu.

We usually want to have affine DPIOs and DPCONs (one for each core).
If this is not possible due to insufficient resources, we distribute
all ingress traffic on the cores with affine DPIOs.

NAPI instances are now one per channel instead of one per FQ, as the
interrupt source changes. Statistics counters change accordingly.

Note that after this commit is applied, one needs to provide sufficient
DPCON objects (either through DPL on restool) in order for the Ethernet
interfaces to work.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Cleanup debugfs statistics

Several minor changes to statistics reporting:
* Fix print alignment of statistics counters
* Fix a naming ambiguity in the cpu_stats debugfs ops
* Add Rx/Tx error counters; these were already used, but not
reported in the per-CPU stats

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Add tx shaping configuration in sysfs

Egress traffic can be shaped via a per-DPNI SysFS entry:
  echo M N > /sys/class/net/ni<X>/tx_shaping
where:
  M is the maximum throughput, expressed in Mbps.
  N is the maximum burst size, expressed in bytes, at most 64000.

To remove shaping, use M=0, N=0.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Fix "Tx busy" counter

Under heavy egress load, when a large number of the transmitted packets
cannot be sent because of high portal contention, the "Tx busy" counter
was not properly incremented.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Fix memory cleanup in case of Tx congestion

The error path of ldpaa_eth_tx() was not properly freeing the SGT buffer
if the enqueue had failed because of congestion. DMA unmapping was
missing, too.

Factor the code originally inside the TxConf callback out into a
separate function that would be called on both TxConf and Tx paths.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Use napi_gro_receive()

Call napi_gro_receive(), effectively enabling GRO.
NOTE: We could further optimize this by looking ahead in the parse results
received from hardware and only using GRO when the L3+L4 combination is
appropriate.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Fix compilation of Rx Error FQ code

Conditionally-compiled code slipped between cracks when FLibs were
updated.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

fsl-dpaa2: Add Kconfig dependency on DEBUG_FS

The driver's debugfs support depends on the generic CONFIG_DEBUG_FS.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Fix interface down/up bug

If a networking interface was brought down while still receiving
ingress traffic, the delay between DPNI disable and NAPI disable
was not enough to ensure all in-flight frames got processed.
Instead, some frames were left pending in the Rx queues. If the
net device was then removed (i.e. restool unbind/unplug), the
call to dpni_reset() silently failed and the kernel crashed on
device replugging.

Fix this by increasing the FQ drain time. Also, at ifconfig up
we enable NAPI before starting the DPNI, to make sure we don't
miss any early CDANs.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Iterate only through initialized channels

The number of DPIO objects available to a DPNI may be fewer than the
number of online cores. A typical example would be a DPNI with a
distribution size smaller than 8. Since we only initialize as many
channels (DPCONs) as there are DPIOs, iterating through all online cpus
would produce a nasty oops when retrieving ethtool stats.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

net: pktgen: Observe needed_headroom of the device

Allocate enough space so as not to force the outgoing net device to do
skb_realloc_headroom().

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

dpaa2-eth: Trace buffer pool seeding

Add ftrace support for buffer pool seeding. Individual buffers are
described by virtual and dma addresses and sizes, as well as by bpid.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Explicitly set carrier off at ifconfig up

If we don't, netif_carrier_ok() will still return true even if the link
state is marked as LINKWATCH_PENDING, which in a dpni-2-dpni case may
last indefinitely long. This will cause "ifconfig up" followed by "ip
link show" to report LOWER_UP when the peer DPNI is still down (and in
fact before we've even received any link notification at all).

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Fix FQ type in stats print

Fix a bug where the type of the Rx error queue was printed
incorrectly in the debugfs statistics

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Don't build debugfs support as a separate module

Instead have module init and exit functions declared explicitly for
the Ethernet driver and initialize/destroy the debugfs directory there.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Remove debugfs #ifdefs from dpaa2-eth.c

Instead of conditionally compiling the calls to debugfs init
functions in dpaa2-eth.c, define no-op stubs for these functions
in case the debugfs Kconfig option is not enabled. This makes
the code more readable.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Use napi_complete_done()

Replace napi_complete() with napi_complete_done().

Together with setting /sys/class/net/ethX/gro_flush_timeout, this
allows us to take better advantage of GRO coalescing and improves
throughput and cpu load in TCP termination tests.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Fix error path in probe

NAPI delete was called at the wrong place when exiting probe
function on an error path

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Allocate channels based on queue count

Limit the number of channels allocated per DPNI to the maximum
between the number of Rx queues per traffic class (distribution size)
and Tx confirmation queues (number of tx flows).
If this happens to be larger than the number of available cores, only
allocate one channel for each core and distribute the frame queues on
the cores/channels in a round robin fashion.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Use DPNI setting for number of Tx flows

Instead of creating one Tx flow for each online cpu, use the DPNI
attributes for deciding how many senders we have.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Renounce sentinel in enum dpni_counter

Bring back the Flib header dpni.h to its initial content by removing the
sentinel value in enum dpni_counter.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Fix Rx queue count

We were missing a roundup to the next power of 2 in order to be in sync
with the MC implementation.
Actually, moved that logic in a separate function which we'll remove
once the MC API is updated.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Unmap the S/G table outside ldpaa_eth_free_rx_fd

The Scatter-Gather table is already unmapped outside ldpaa_eth_free_rx_fd
so no need to try to unmap it once more.

Signed-off-by: Cristian Sovaiala <cristian.sovaiala@freescale.com>

dpaa2-eth: Use napi_schedule_irqoff()

At the time we schedule NAPI, the Dequeue Available Notifications (which
are the de facto triggers of NAPI processing) are already disabled.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

net: Fix ethernet Kconfig

Re-add missing 'source' directive. This exists on the integration
branch, but was mistakenly removed by an earlier dpaa2-eth rebase.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Manually update link state at ifup

The DPMAC may have handled the link state notification before the DPNI
is up. A new PHY state transision may not subsequently occur, so the
DPNI must initiate a read of the DPMAC state.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Stop carrier upon ifdown

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Fix print messages in link state handling code

Avoid an "(uninitialized)" message during DPNI probe by replacing
netdev_info() with its corresponding dev_info().
Purge some related comments and add some netdev messages to assist
link state debugging.
Remove an excessively defensive assertion.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Do not allow ethtool settings change while the NI is up

Due to a MC limitation, link state changes while the DPNI is enabled
will fail. For now, we'll just prevent the call from going down to the MC
if we know it will fail.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Reduce ethtool messages verbosity

Transform a couple of netdev_info() calls into netdev_dbg().

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Only unmask IRQs that we actually handle

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Produce fewer boot log messages

No longer print one line for each all-zero hwaddr that was replaced with
a random MAC address; just inform the user once that this has occurred.
And reduce redundancy of some printouts in the bootlog.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Fix big endian issue

We were not doing any endianness conversions on the scatter gather
table entries, which caused problems on big endian kernels.

For frame descriptors the QMan driver takes care of this transparently,
but in the case of SG entries we need to do it ourselves.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Force atomic context for lazy bpool seeding

We use the same ldpaa_bp_add_7() function for initial buffer pool
seeding (from .ndo_open) and for hotpath pool replenishing. The function
is using napi_alloc_frag() as an optimization for the Rx datapath, but
that turns out to require atomic execution because of a this_cpu_ptr()
call down its stack.
This patch temporarily disables preemption around the initial seeding of
the Rx buffer pool.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa-eth: Integrate Flib version 0.7.1.2

Although API-compatible with 0.7.1.1, there are some ABI changes
that warrant a new integration.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: No longer adjust max_dist_per_tc

The MC firmware until version 0.7.1.1/8.0.2 requires that
max_dist_per_tc have the value expected by the hardware, which would be
different from what the user expects. MC firmware 0.7.1.2/8.0.5 fixes
that, so we remove our transparent conversion.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Enforce 256-byte Rx alignment

Hardware erratum enforced by MC requires that Rx buffer lengths and
addresses be 265-byte aligned.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Rename Tx buf alignment macro

The existing "BUF_ALIGN" macro remained confined to Tx usage, after
separate alignment was introduced for Rx. Renaming accordingly.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Fix hashing distribution size

Commit be3fb62623e4338e60fb60019f134b6055cbc127
Author: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
Date:   Fri Oct 23 18:26:44 2015 +0300

    dpaa2-eth: No longer adjust max_dist_per_tc

missed one usage of the ldpaa_queue_count() function, making
distribution size inadvertenly lower.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Remove ndo_select_queue

Our implementation of ndo_select_queue would lead to questions regarding
our support for qdiscs. Until we find an optimal way to select the txq
without breaking future qdisc integration, just remove the
ndo_select_queue callback entirely and leave the stack figure out the
flow.
This incurs a ~2-3% penalty on some performance tests.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Select TxConf FQ based on processor id

Use smp_processor_id instead of skb queue mapping to determine the tx
flow id and implicitly the confirmation queue.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com>

dpaa2-eth: Reduce number of buffers in bpool

Reduce the maximum number of buffers in each buffer pool associated
with a DPNI. This in turn reduces the number of memory allocations
performed in a single batch when buffers fall below a certain
threshold.

Provides a significant performance boost (~5-10% increase) on both
termination and forwarding scenarios, while also reducing the driver
memory footprint.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Replace "ldpaa" with "dpaa2"

Replace all instances of "ldpaa"/"LDPAA" in the Ethernet driver
(names of functions, structures, macros, etc), with "dpaa2"/"DPAA2",
except for DPIO API function calls.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: rename ldpaa to dpaa2

Signed-off-by: Haiying Wang <Haiying.wang@freescale.com>
(Stuart: this patch was split out from the origin global rename patch)
Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>

dpaa2-eth: Rename dpaa_io_query_fq_count to dpaa2_io_query_fq_count

Signed-off-by: Cristian Sovaiala <cristian.sovaiala@freescale.com>

fsl-dpio: rename dpaa_* structure to dpaa2_*

Signed-off-by: Haiying Wang <Haiying.wang@freescale.com>

dpaa2-eth, dpni, fsl-mc: Updates for MC0.8.0

Several changes need to be performed in sync for supporting
the newest MC version:
* Update mc-cmd.h
* Update the dpni binary interface to v6.0
* Update the DPAA2 Eth driver to account for several API changes

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

staging: fsl-dpaa2: ethernet: add support for hardware timestamping

Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>

fsl-dpaa2: eth: Do not set bpid in egress fd

We don't do FD recycling on egress, BPID is therefore not necessary.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: eth: Amend buffer refill comment

A change request has been pending for placing an upper bound to the
buffer replenish logic on Rx. However, short of practical alternatives,
resort to amending the relevant comment and rely on ksoftirqd to
guarantee interactivity.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: eth: Configure a taildrop threshold for each Rx frame queue.

The selected value allows for Rx jumbo (10K) frames processing
while at the same time helps balance the system in the case of
IP forwarding.

Also compute the number of buffers in the pool based on the TD
threshold to avoid starving some of the ingress queues in small
frames, high throughput scenarios.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

fsl-dpaa2: eth: Check objects' FLIB version

Make sure we support the DPNI, DPCON and DPBP version, otherwise
abort probing early on and provide an error message.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

fsl-dpaa2: eth: Remove likely/unlikely from cold paths

Signed-off-by: Cristian Sovaiala <cristi.sovaiala@nxp.com>
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: eth: Remove __cold attribute

Signed-off-by: Cristian Sovaiala <cristi.sovaiala@nxp.com>

fsl-dpaa2: eth: Replace netdev_XXX with dev_XXX before register_netdevice()

Signed-off-by: Cristian Sovaiala <cristi.sovaiala@nxp.com>
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: eth: Fix coccinelle issue

drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c:687:1-36: WARNING:
Assignment of bool to 0/1

Signed-off-by: Cristian Sovaiala <cristi.sovaiala@nxp.com>

fsl-dpaa2: eth: Fix minor spelling issue

Signed-off-by: Cristian Sovaiala <cristi.sovaiala@nxp.com>

fsl-dpaa2: eth: Add a couple of 'unlikely' on hot path

Signed-off-by: Cristian Sovaiala <cristi.sovaiala@nxp.com>
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: eth: Fix a bunch of minor issues found by static analysis tools

As found by Klocworks and Checkpatch:
 - Unused variables
 - Integer type replacements
 - Unchecked memory allocations
 - Whitespace, alignment and newlining

Signed-off-by: Cristian Sovaiala <cristi.sovaiala@nxp.com>
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: eth: Remove "inline" keyword from static functions

Signed-off-by: Cristian Sovaiala <cristi.sovaiala@nxp.com>

fsl-dpaa2: eth: Remove BUG/BUG_ONs

Signed-off-by: Cristian Sovaiala <cristi.sovaiala@nxp.com>
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: eth: Use NAPI_POLL_WEIGHT

No need to define our own macro as long as we're using the
default value of 64.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Move dpaa2_eth_swa structure to header file

It was the only structure defined inside dpaa2-eth.c

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

fsl-dpaa2: eth: Replace uintX_t with uX

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>
Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: eth: Minor fixes & cosmetics

- Make driver log level an int, because this is what
  netif_msg_init expects.
- Remove driver description macro as it was used only once,
  immediately after being defined
- Remove include comment

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Move bcast address setup to dpaa2_eth_netdev_init

It seems to fit better there than directly in probe.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Fix DMA mapping bug

During hashing/flow steering configuration via ethtool, we were
doing a DMA unmap from the wrong address. Fix the issue by using
the DMA address that was initially mapped.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

dpaa2-eth: Associate buffer counting to queues instead of cpu

Move the buffer counters from being percpu variables to being
associated with QMan channels. This is more natural as we need
to dimension the buffer pool count based on distribution size
rather than number of online cores.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

fsl-dpaa2: eth: Provide driver and fw version to ethtool

Read fw version from the MC and interpret DPNI FLib major.minor as the
driver's version. Report these in 'ethool -i'.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: eth: Remove dependency on GCOV_KERNEL

Signed-off-by: Cristian Sovaiala <cristi.sovaiala@nxp.com>

fsl-dpaa2: eth: Remove FIXME/TODO comments from the code

Some of the concerns had already been addressed, a couple are being
fixed in place.
Left a few TODOs related to the flow-steering code, which needs to be
revisited before upstreaming anyway.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

fsl-dpaa2: eth: Remove forward declarations

Instead move the functions such that they are defined prior to
being used.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

fsl-dpaa2: eth: Remove dead code in IRQ handler

If any of those conditions were met, it is unlikely we'd ever be there
in the first place.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: eth: Remove dpaa2_dpbp_drain()

Its sole caller was __dpaa2_dpbp_free(), so move its content and get rid
of one function call.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: eth: Remove duplicate define

We somehow ended up with two defines for the maximum number
of tx queues.

Signed-off-by: Ioana Radulescu <ruxandra.radulescu@freescale.com>

fsl-dpaa2: eth: Move header comment to .c file

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

fsl-dpaa2: eth: Make DPCON allocation failure produce a benign message

Number of DPCONs may be smaller than the number of CPUs in a number of
valid scenarios. One such scenario is when the DPNI's distribution width
is smaller than the number of cores and we just don't want to
over-allocate DPCONs.
Make the DPCON allocation failure less menacing by changing the logged
message.

While at it, remove a unused parameter in function prototype.

Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@nxp.com>

dpaa2 eth: irq update

Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com>

Conflicts:
	drivers/staging/Kconfig
	drivers/staging/Makefile
---
 MAINTAINERS                                        |   15 +
 drivers/staging/Kconfig                            |    2 +
 drivers/staging/Makefile                           |    1 +
 drivers/staging/fsl-dpaa2/Kconfig                  |   11 +
 drivers/staging/fsl-dpaa2/Makefile                 |    5 +
 drivers/staging/fsl-dpaa2/ethernet/Kconfig         |   42 +
 drivers/staging/fsl-dpaa2/ethernet/Makefile        |   21 +
 .../staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c |  319 +++
 .../staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.h |   61 +
 .../staging/fsl-dpaa2/ethernet/dpaa2-eth-trace.h   |  185 ++
 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c     | 2793 ++++++++++++++++++++
 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h     |  366 +++
 drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c |  882 +++++++
 drivers/staging/fsl-dpaa2/ethernet/dpkg.h          |  175 ++
 drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h      | 1058 ++++++++
 drivers/staging/fsl-dpaa2/ethernet/dpni.c          | 1907 +++++++++++++
 drivers/staging/fsl-dpaa2/ethernet/dpni.h          | 2581 ++++++++++++++++++
 drivers/staging/fsl-mc/include/mc-cmd.h            |    5 +-
 drivers/staging/fsl-mc/include/net.h               |  481 ++++
 net/core/pktgen.c                                  |    1 +
 20 files changed, 10910 insertions(+), 1 deletion(-)
 create mode 100644 drivers/staging/fsl-dpaa2/Kconfig
 create mode 100644 drivers/staging/fsl-dpaa2/Makefile
 create mode 100644 drivers/staging/fsl-dpaa2/ethernet/Kconfig
 create mode 100644 drivers/staging/fsl-dpaa2/ethernet/Makefile
 create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c
 create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.h
 create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-trace.h
 create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
 create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
 create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
 create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpkg.h
 create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h
 create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpni.c
 create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpni.h
 create mode 100644 drivers/staging/fsl-mc/include/net.h

--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4539,6 +4539,21 @@ L:	linux-kernel@vger.kernel.org
 S:	Maintained
 F:	drivers/staging/fsl-mc/
 
+FREESCALE DPAA2 ETH DRIVER
+M:	Ioana Radulescu <ruxandra.radulescu@freescale.com>
+M:	Bogdan Hamciuc <bogdan.hamciuc@freescale.com>
+M:	Cristian Sovaiala <cristian.sovaiala@freescale.com>
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+F:	drivers/staging/fsl-dpaa2/ethernet/
+
+FREESCALE QORIQ MANAGEMENT COMPLEX RESTOOL DRIVER
+M:	Lijun Pan <Lijun.Pan@freescale.com>
+L:	linux-kernel@vger.kernel.org
+S:	Maintained
+F:	drivers/staging/fsl-mc/bus/mc-ioctl.h
+F:	drivers/staging/fsl-mc/bus/mc-restool.c
+
 FREEVXFS FILESYSTEM
 M:	Christoph Hellwig <hch@infradead.org>
 W:	ftp://ftp.openlinux.org/pub/people/hch/vxfs
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -114,4 +114,6 @@ source "drivers/staging/most/Kconfig"
 
 source "drivers/staging/fsl_ppfe/Kconfig"
 
+source "drivers/staging/fsl-dpaa2/Kconfig"
+
 endif # STAGING
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -49,3 +49,4 @@ obj-$(CONFIG_FSL_DPA)           += fsl_q
 obj-$(CONFIG_WILC1000)		+= wilc1000/
 obj-$(CONFIG_MOST)		+= most/
 obj-$(CONFIG_FSL_PPFE)		+= fsl_ppfe/
+obj-$(CONFIG_FSL_DPAA2)		+= fsl-dpaa2/
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/Kconfig
@@ -0,0 +1,11 @@
+#
+# Freescale device configuration
+#
+
+config FSL_DPAA2
+	bool "Freescale DPAA2 devices"
+	depends on FSL_MC_BUS
+	---help---
+	  Build drivers for Freescale DataPath Acceleration Architecture (DPAA2) family of SoCs.
+# TODO move DPIO driver in-here?
+source "drivers/staging/fsl-dpaa2/ethernet/Kconfig"
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the Freescale network device drivers.
+#
+
+obj-$(CONFIG_FSL_DPAA2_ETH)	+= ethernet/
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/Kconfig
@@ -0,0 +1,42 @@
+#
+# Freescale DPAA Ethernet driver configuration
+#
+# Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
+#
+# This file is released under the GPLv2
+#
+
+menuconfig FSL_DPAA2_ETH
+	tristate "Freescale DPAA2 Ethernet"
+	depends on FSL_DPAA2 && FSL_MC_BUS && FSL_MC_DPIO
+	select FSL_DPAA2_MAC
+	default y
+	---help---
+	  Freescale Data Path Acceleration Architecture Ethernet
+	  driver, using the Freescale MC bus driver.
+
+if FSL_DPAA2_ETH
+config FSL_DPAA2_ETH_LINK_POLL
+	bool "Use polling mode for link state"
+	default n
+	---help---
+	  Poll for detecting link state changes instead of using
+	  interrupts.
+
+config FSL_DPAA2_ETH_USE_ERR_QUEUE
+	bool "Enable Rx error queue"
+	default n
+	---help---
+	  Allow Rx error frames to be enqueued on an error queue
+	  and processed by the driver (by default they are dropped
+	  in hardware).
+	  This may impact performance, recommended for debugging
+	  purposes only.
+
+config FSL_DPAA2_ETH_DEBUGFS
+	depends on DEBUG_FS && FSL_QBMAN_DEBUG
+	bool "Enable debugfs support"
+	default n
+	---help---
+	  Enable advanced statistics through debugfs interface.
+endif
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/Makefile
@@ -0,0 +1,21 @@
+#
+# Makefile for the Freescale DPAA Ethernet controllers
+#
+# Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
+#
+# This file is released under the GPLv2
+#
+
+ccflags-y += -DVERSION=\"\"
+
+obj-$(CONFIG_FSL_DPAA2_ETH) += fsl-dpaa2-eth.o
+
+fsl-dpaa2-eth-objs    := dpaa2-eth.o dpaa2-ethtool.o dpni.o
+fsl-dpaa2-eth-${CONFIG_FSL_DPAA2_ETH_DEBUGFS} += dpaa2-eth-debugfs.o
+
+#Needed by the tracing framework
+CFLAGS_dpaa2-eth.o := -I$(src)
+
+ifeq ($(CONFIG_FSL_DPAA2_ETH_GCOV),y)
+	GCOV_PROFILE := y
+endif
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c
@@ -0,0 +1,319 @@
+
+/* Copyright 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include "dpaa2-eth.h"
+#include "dpaa2-eth-debugfs.h"
+
+#define DPAA2_ETH_DBG_ROOT "dpaa2-eth"
+
+
+static struct dentry *dpaa2_dbg_root;
+
+static int dpaa2_dbg_cpu_show(struct seq_file *file, void *offset)
+{
+	struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
+	struct rtnl_link_stats64 *stats;
+	struct dpaa2_eth_stats *extras;
+	int i;
+
+	seq_printf(file, "Per-CPU stats for %s\n", priv->net_dev->name);
+	seq_printf(file, "%s%16s%16s%16s%16s%16s%16s%16s%16s\n",
+		   "CPU", "Rx", "Rx Err", "Rx SG", "Tx", "Tx Err", "Tx conf",
+		   "Tx SG", "Enq busy");
+
+	for_each_online_cpu(i) {
+		stats = per_cpu_ptr(priv->percpu_stats, i);
+		extras = per_cpu_ptr(priv->percpu_extras, i);
+		seq_printf(file, "%3d%16llu%16llu%16llu%16llu%16llu%16llu%16llu%16llu\n",
+			   i,
+			   stats->rx_packets,
+			   stats->rx_errors,
+			   extras->rx_sg_frames,
+			   stats->tx_packets,
+			   stats->tx_errors,
+			   extras->tx_conf_frames,
+			   extras->tx_sg_frames,
+			   extras->tx_portal_busy);
+	}
+
+	return 0;
+}
+
+static int dpaa2_dbg_cpu_open(struct inode *inode, struct file *file)
+{
+	int err;
+	struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private;
+
+	err = single_open(file, dpaa2_dbg_cpu_show, priv);
+	if (err < 0)
+		netdev_err(priv->net_dev, "single_open() failed\n");
+
+	return err;
+}
+
+static const struct file_operations dpaa2_dbg_cpu_ops = {
+	.open = dpaa2_dbg_cpu_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static char *fq_type_to_str(struct dpaa2_eth_fq *fq)
+{
+	switch (fq->type) {
+	case DPAA2_RX_FQ:
+		return "Rx";
+	case DPAA2_TX_CONF_FQ:
+		return "Tx conf";
+	case DPAA2_RX_ERR_FQ:
+		return "Rx err";
+	default:
+		return "N/A";
+	}
+}
+
+static int dpaa2_dbg_fqs_show(struct seq_file *file, void *offset)
+{
+	struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
+	struct dpaa2_eth_fq *fq;
+	u32 fcnt, bcnt;
+	int i, err;
+
+	seq_printf(file, "FQ stats for %s:\n", priv->net_dev->name);
+	seq_printf(file, "%s%16s%16s%16s%16s\n",
+		   "VFQID", "CPU", "Type", "Frames", "Pending frames");
+
+	for (i = 0; i <  priv->num_fqs; i++) {
+		fq = &priv->fq[i];
+		err = dpaa2_io_query_fq_count(NULL, fq->fqid, &fcnt, &bcnt);
+		if (err)
+			fcnt = 0;
+
+		seq_printf(file, "%5d%16d%16s%16llu%16u\n",
+			   fq->fqid,
+			   fq->target_cpu,
+			   fq_type_to_str(fq),
+			   fq->stats.frames,
+			   fcnt);
+	}
+
+	return 0;
+}
+
+static int dpaa2_dbg_fqs_open(struct inode *inode, struct file *file)
+{
+	int err;
+	struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private;
+
+	err = single_open(file, dpaa2_dbg_fqs_show, priv);
+	if (err < 0)
+		netdev_err(priv->net_dev, "single_open() failed\n");
+
+	return err;
+}
+
+static const struct file_operations dpaa2_dbg_fq_ops = {
+	.open = dpaa2_dbg_fqs_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static int dpaa2_dbg_ch_show(struct seq_file *file, void *offset)
+{
+	struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
+	struct dpaa2_eth_channel *ch;
+	int i;
+
+	seq_printf(file, "Channel stats for %s:\n", priv->net_dev->name);
+	seq_printf(file, "%s%16s%16s%16s%16s%16s\n",
+		   "CHID", "CPU", "Deq busy", "Frames", "CDANs",
+		   "Avg frm/CDAN");
+
+	for (i = 0; i < priv->num_channels; i++) {
+		ch = priv->channel[i];
+		seq_printf(file, "%4d%16d%16llu%16llu%16llu%16llu\n",
+			   ch->ch_id,
+			   ch->nctx.desired_cpu,
+			   ch->stats.dequeue_portal_busy,
+			   ch->stats.frames,
+			   ch->stats.cdan,
+			   ch->stats.frames / ch->stats.cdan);
+	}
+
+	return 0;
+}
+
+static int dpaa2_dbg_ch_open(struct inode *inode, struct file *file)
+{
+	int err;
+	struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private;
+
+	err = single_open(file, dpaa2_dbg_ch_show, priv);
+	if (err < 0)
+		netdev_err(priv->net_dev, "single_open() failed\n");
+
+	return err;
+}
+
+static const struct file_operations dpaa2_dbg_ch_ops = {
+	.open = dpaa2_dbg_ch_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static ssize_t dpaa2_dbg_reset_write(struct file *file, const char __user *buf,
+				     size_t count, loff_t *offset)
+{
+	struct dpaa2_eth_priv *priv = file->private_data;
+	struct rtnl_link_stats64 *percpu_stats;
+	struct dpaa2_eth_stats *percpu_extras;
+	struct dpaa2_eth_fq *fq;
+	struct dpaa2_eth_channel *ch;
+	int i;
+
+	for_each_online_cpu(i) {
+		percpu_stats = per_cpu_ptr(priv->percpu_stats, i);
+		memset(percpu_stats, 0, sizeof(*percpu_stats));
+
+		percpu_extras = per_cpu_ptr(priv->percpu_extras, i);
+		memset(percpu_extras, 0, sizeof(*percpu_extras));
+	}
+
+	for (i = 0; i < priv->num_fqs; i++) {
+		fq = &priv->fq[i];
+		memset(&fq->stats, 0, sizeof(fq->stats));
+	}
+
+	for_each_cpu(i, &priv->dpio_cpumask) {
+		ch = priv->channel[i];
+		memset(&ch->stats, 0, sizeof(ch->stats));
+	}
+
+	return count;
+}
+
+static const struct file_operations dpaa2_dbg_reset_ops = {
+	.open = simple_open,
+	.write = dpaa2_dbg_reset_write,
+};
+
+void dpaa2_dbg_add(struct dpaa2_eth_priv *priv)
+{
+	if (!dpaa2_dbg_root)
+		return;
+
+	/* Create a directory for the interface */
+	priv->dbg.dir = debugfs_create_dir(priv->net_dev->name,
+					   dpaa2_dbg_root);
+	if (!priv->dbg.dir) {
+		netdev_err(priv->net_dev, "debugfs_create_dir() failed\n");
+		return;
+	}
+
+	/* per-cpu stats file */
+	priv->dbg.cpu_stats = debugfs_create_file("cpu_stats", S_IRUGO,
+						  priv->dbg.dir, priv,
+						  &dpaa2_dbg_cpu_ops);
+	if (!priv->dbg.cpu_stats) {
+		netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
+		goto err_cpu_stats;
+	}
+
+	/* per-fq stats file */
+	priv->dbg.fq_stats = debugfs_create_file("fq_stats", S_IRUGO,
+						 priv->dbg.dir, priv,
+						 &dpaa2_dbg_fq_ops);
+	if (!priv->dbg.fq_stats) {
+		netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
+		goto err_fq_stats;
+	}
+
+	/* per-fq stats file */
+	priv->dbg.ch_stats = debugfs_create_file("ch_stats", S_IRUGO,
+						 priv->dbg.dir, priv,
+						 &dpaa2_dbg_ch_ops);
+	if (!priv->dbg.fq_stats) {
+		netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
+		goto err_ch_stats;
+	}
+
+	/* reset stats */
+	priv->dbg.reset_stats = debugfs_create_file("reset_stats", S_IWUSR,
+						    priv->dbg.dir, priv,
+						    &dpaa2_dbg_reset_ops);
+	if (!priv->dbg.reset_stats) {
+		netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
+		goto err_reset_stats;
+	}
+
+	return;
+
+err_reset_stats:
+	debugfs_remove(priv->dbg.ch_stats);
+err_ch_stats:
+	debugfs_remove(priv->dbg.fq_stats);
+err_fq_stats:
+	debugfs_remove(priv->dbg.cpu_stats);
+err_cpu_stats:
+	debugfs_remove(priv->dbg.dir);
+}
+
+void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv)
+{
+	debugfs_remove(priv->dbg.reset_stats);
+	debugfs_remove(priv->dbg.fq_stats);
+	debugfs_remove(priv->dbg.ch_stats);
+	debugfs_remove(priv->dbg.cpu_stats);
+	debugfs_remove(priv->dbg.dir);
+}
+
+void dpaa2_eth_dbg_init(void)
+{
+	dpaa2_dbg_root = debugfs_create_dir(DPAA2_ETH_DBG_ROOT, NULL);
+	if (!dpaa2_dbg_root) {
+		pr_err("DPAA2-ETH: debugfs create failed\n");
+		return;
+	}
+
+	pr_info("DPAA2-ETH: debugfs created\n");
+}
+
+void __exit dpaa2_eth_dbg_exit(void)
+{
+	debugfs_remove(dpaa2_dbg_root);
+}
+
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.h
@@ -0,0 +1,61 @@
+/* Copyright 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DPAA2_ETH_DEBUGFS_H
+#define DPAA2_ETH_DEBUGFS_H
+
+#include <linux/dcache.h>
+#include "dpaa2-eth.h"
+
+extern struct dpaa2_eth_priv *priv;
+
+struct dpaa2_debugfs {
+	struct dentry *dir;
+	struct dentry *fq_stats;
+	struct dentry *ch_stats;
+	struct dentry *cpu_stats;
+	struct dentry *reset_stats;
+};
+
+#ifdef CONFIG_FSL_DPAA2_ETH_DEBUGFS
+void dpaa2_eth_dbg_init(void);
+void dpaa2_eth_dbg_exit(void);
+void dpaa2_dbg_add(struct dpaa2_eth_priv *priv);
+void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv);
+#else
+static inline void dpaa2_eth_dbg_init(void) {}
+static inline void dpaa2_eth_dbg_exit(void) {}
+static inline void dpaa2_dbg_add(struct dpaa2_eth_priv *priv) {}
+static inline void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv) {}
+#endif /* CONFIG_FSL_DPAA2_ETH_DEBUGFS */
+
+#endif /* DPAA2_ETH_DEBUGFS_H */
+
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-trace.h
@@ -0,0 +1,185 @@
+/* Copyright 2014-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM	dpaa2_eth
+
+#if !defined(_DPAA2_ETH_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _DPAA2_ETH_TRACE_H
+
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include "dpaa2-eth.h"
+#include <linux/tracepoint.h>
+
+#define TR_FMT "[%s] fd: addr=0x%llx, len=%u, off=%u"
+/* trace_printk format for raw buffer event class */
+#define TR_BUF_FMT "[%s] vaddr=%p size=%zu dma_addr=%pad map_size=%zu bpid=%d"
+
+/* This is used to declare a class of events.
+ * individual events of this type will be defined below.
+ */
+
+/* Store details about a frame descriptor */
+DECLARE_EVENT_CLASS(dpaa2_eth_fd,
+		    /* Trace function prototype */
+		    TP_PROTO(struct net_device *netdev,
+			     const struct dpaa2_fd *fd),
+
+		    /* Repeat argument list here */
+		    TP_ARGS(netdev, fd),
+
+		    /* A structure containing the relevant information we want
+		     * to record. Declare name and type for each normal element,
+		     * name, type and size for arrays. Use __string for variable
+		     * length strings.
+		     */
+		    TP_STRUCT__entry(
+				     __field(u64, fd_addr)
+				     __field(u32, fd_len)
+				     __field(u16, fd_offset)
+				     __string(name, netdev->name)
+		    ),
+
+		    /* The function that assigns values to the above declared
+		     * fields
+		     */
+		    TP_fast_assign(
+				   __entry->fd_addr = dpaa2_fd_get_addr(fd);
+				   __entry->fd_len = dpaa2_fd_get_len(fd);
+				   __entry->fd_offset = dpaa2_fd_get_offset(fd);
+				   __assign_str(name, netdev->name);
+		    ),
+
+		    /* This is what gets printed when the trace event is
+		     * triggered.
+		     */
+		    TP_printk(TR_FMT,
+			      __get_str(name),
+			      __entry->fd_addr,
+			      __entry->fd_len,
+			      __entry->fd_offset)
+);
+
+/* Now declare events of the above type. Format is:
+ * DEFINE_EVENT(class, name, proto, args), with proto and args same as for class
+ */
+
+/* Tx (egress) fd */
+DEFINE_EVENT(dpaa2_eth_fd, dpaa2_tx_fd,
+	     TP_PROTO(struct net_device *netdev,
+		      const struct dpaa2_fd *fd),
+
+	     TP_ARGS(netdev, fd)
+);
+
+/* Rx fd */
+DEFINE_EVENT(dpaa2_eth_fd, dpaa2_rx_fd,
+	     TP_PROTO(struct net_device *netdev,
+		      const struct dpaa2_fd *fd),
+
+	     TP_ARGS(netdev, fd)
+);
+
+/* Tx confirmation fd */
+DEFINE_EVENT(dpaa2_eth_fd, dpaa2_tx_conf_fd,
+	     TP_PROTO(struct net_device *netdev,
+		      const struct dpaa2_fd *fd),
+
+	     TP_ARGS(netdev, fd)
+);
+
+/* Log data about raw buffers. Useful for tracing DPBP content. */
+TRACE_EVENT(dpaa2_eth_buf_seed,
+	    /* Trace function prototype */
+	    TP_PROTO(struct net_device *netdev,
+		     /* virtual address and size */
+		     void *vaddr,
+		     size_t size,
+		     /* dma map address and size */
+		     dma_addr_t dma_addr,
+		     size_t map_size,
+		     /* buffer pool id, if relevant */
+		     u16 bpid),
+
+	    /* Repeat argument list here */
+	    TP_ARGS(netdev, vaddr, size, dma_addr, map_size, bpid),
+
+	    /* A structure containing the relevant information we want
+	     * to record. Declare name and type for each normal element,
+	     * name, type and size for arrays. Use __string for variable
+	     * length strings.
+	     */
+	    TP_STRUCT__entry(
+			     __field(void *, vaddr)
+			     __field(size_t, size)
+			     __field(dma_addr_t, dma_addr)
+			     __field(size_t, map_size)
+			     __field(u16, bpid)
+			     __string(name, netdev->name)
+	    ),
+
+	    /* The function that assigns values to the above declared
+	     * fields
+	     */
+	    TP_fast_assign(
+			   __entry->vaddr = vaddr;
+			   __entry->size = size;
+			   __entry->dma_addr = dma_addr;
+			   __entry->map_size = map_size;
+			   __entry->bpid = bpid;
+			   __assign_str(name, netdev->name);
+	    ),
+
+	    /* This is what gets printed when the trace event is
+	     * triggered.
+	     */
+	    TP_printk(TR_BUF_FMT,
+		      __get_str(name),
+		      __entry->vaddr,
+		      __entry->size,
+		      &__entry->dma_addr,
+		      __entry->map_size,
+		      __entry->bpid)
+);
+
+/* If only one event of a certain type needs to be declared, use TRACE_EVENT().
+ * The syntax is the same as for DECLARE_EVENT_CLASS().
+ */
+
+#endif /* _DPAA2_ETH_TRACE_H */
+
+/* This must be outside ifdef _DPAA2_ETH_TRACE_H */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE	dpaa2-eth-trace
+#include <trace/define_trace.h>
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
@@ -0,0 +1,2793 @@
+/* Copyright 2014-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/etherdevice.h>
+#include <linux/of_net.h>
+#include <linux/interrupt.h>
+#include <linux/msi.h>
+#include <linux/debugfs.h>
+#include <linux/kthread.h>
+#include <linux/net_tstamp.h>
+
+#include "../../fsl-mc/include/mc.h"
+#include "../../fsl-mc/include/mc-sys.h"
+#include "dpaa2-eth.h"
+
+/* CREATE_TRACE_POINTS only needs to be defined once. Other dpa files
+ * using trace events only need to #include <trace/events/sched.h>
+ */
+#define CREATE_TRACE_POINTS
+#include "dpaa2-eth-trace.h"
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Freescale Semiconductor, Inc");
+MODULE_DESCRIPTION("Freescale DPAA2 Ethernet Driver");
+
+static int debug = -1;
+module_param(debug, int, S_IRUGO);
+MODULE_PARM_DESC(debug, "Module/Driver verbosity level");
+
+/* Oldest DPAA2 objects version we are compatible with */
+#define DPAA2_SUPPORTED_DPNI_VERSION	6
+#define DPAA2_SUPPORTED_DPBP_VERSION	2
+#define DPAA2_SUPPORTED_DPCON_VERSION	2
+
+/* Iterate through the cpumask in a round-robin fashion. */
+#define cpumask_rr(cpu, maskptr) \
+do { \
+	(cpu) = cpumask_next((cpu), (maskptr)); \
+	if ((cpu) >= nr_cpu_ids) \
+		(cpu) = cpumask_first((maskptr)); \
+} while (0)
+
+static void dpaa2_eth_rx_csum(struct dpaa2_eth_priv *priv,
+			      u32 fd_status,
+			      struct sk_buff *skb)
+{
+	skb_checksum_none_assert(skb);
+
+	/* HW checksum validation is disabled, nothing to do here */
+	if (!(priv->net_dev->features & NETIF_F_RXCSUM))
+		return;
+
+	/* Read checksum validation bits */
+	if (!((fd_status & DPAA2_ETH_FAS_L3CV) &&
+	      (fd_status & DPAA2_ETH_FAS_L4CV)))
+		return;
+
+	/* Inform the stack there's no need to compute L3/L4 csum anymore */
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+}
+
+/* Free a received FD.
+ * Not to be used for Tx conf FDs or on any other paths.
+ */
+static void dpaa2_eth_free_rx_fd(struct dpaa2_eth_priv *priv,
+				 const struct dpaa2_fd *fd,
+				 void *vaddr)
+{
+	struct device *dev = priv->net_dev->dev.parent;
+	dma_addr_t addr = dpaa2_fd_get_addr(fd);
+	u8 fd_format = dpaa2_fd_get_format(fd);
+
+	if (fd_format == dpaa2_fd_sg) {
+		struct dpaa2_sg_entry *sgt = vaddr + dpaa2_fd_get_offset(fd);
+		void *sg_vaddr;
+		int i;
+
+		for (i = 0; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
+			dpaa2_sg_le_to_cpu(&sgt[i]);
+
+			addr = dpaa2_sg_get_addr(&sgt[i]);
+			dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUFFER_SIZE,
+					 DMA_FROM_DEVICE);
+
+			sg_vaddr = phys_to_virt(addr);
+			put_page(virt_to_head_page(sg_vaddr));
+
+			if (dpaa2_sg_is_final(&sgt[i]))
+				break;
+		}
+	}
+
+	put_page(virt_to_head_page(vaddr));
+}
+
+/* Build a linear skb based on a single-buffer frame descriptor */
+static struct sk_buff *dpaa2_eth_build_linear_skb(struct dpaa2_eth_priv *priv,
+						  struct dpaa2_eth_channel *ch,
+						  const struct dpaa2_fd *fd,
+						  void *fd_vaddr)
+{
+	struct sk_buff *skb = NULL;
+	u16 fd_offset = dpaa2_fd_get_offset(fd);
+	u32 fd_length = dpaa2_fd_get_len(fd);
+
+	skb = build_skb(fd_vaddr, DPAA2_ETH_RX_BUFFER_SIZE +
+			SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
+	if (unlikely(!skb)) {
+		netdev_err(priv->net_dev, "build_skb() failed\n");
+		return NULL;
+	}
+
+	skb_reserve(skb, fd_offset);
+	skb_put(skb, fd_length);
+
+	ch->buf_count--;
+
+	return skb;
+}
+
+/* Build a non linear (fragmented) skb based on a S/G table */
+static struct sk_buff *dpaa2_eth_build_frag_skb(struct dpaa2_eth_priv *priv,
+						struct dpaa2_eth_channel *ch,
+						struct dpaa2_sg_entry *sgt)
+{
+	struct sk_buff *skb = NULL;
+	struct device *dev = priv->net_dev->dev.parent;
+	void *sg_vaddr;
+	dma_addr_t sg_addr;
+	u16 sg_offset;
+	u32 sg_length;
+	struct page *page, *head_page;
+	int page_offset;
+	int i;
+
+	for (i = 0; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
+		struct dpaa2_sg_entry *sge = &sgt[i];
+
+		dpaa2_sg_le_to_cpu(sge);
+
+		/* We don't support anything else yet! */
+		if (unlikely(dpaa2_sg_get_format(sge) != dpaa2_sg_single)) {
+			dev_warn_once(dev, "Unsupported S/G entry format: %d\n",
+				      dpaa2_sg_get_format(sge));
+			return NULL;
+		}
+
+		/* Get the address, offset and length from the S/G entry */
+		sg_addr = dpaa2_sg_get_addr(sge);
+		dma_unmap_single(dev, sg_addr, DPAA2_ETH_RX_BUFFER_SIZE,
+				 DMA_FROM_DEVICE);
+		if (unlikely(dma_mapping_error(dev, sg_addr))) {
+			netdev_err(priv->net_dev, "DMA unmap failed\n");
+			return NULL;
+		}
+		sg_vaddr = phys_to_virt(sg_addr);
+		sg_length = dpaa2_sg_get_len(sge);
+
+		if (i == 0) {
+			/* We build the skb around the first data buffer */
+			skb = build_skb(sg_vaddr, DPAA2_ETH_RX_BUFFER_SIZE +
+				SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
+			if (unlikely(!skb)) {
+				netdev_err(priv->net_dev, "build_skb failed\n");
+				return NULL;
+			}
+			sg_offset = dpaa2_sg_get_offset(sge);
+			skb_reserve(skb, sg_offset);
+			skb_put(skb, sg_length);
+		} else {
+			/* Subsequent data in SGEntries are stored at
+			 * offset 0 in their buffers, we don't need to
+			 * compute sg_offset.
+			 */
+			WARN_ONCE(dpaa2_sg_get_offset(sge) != 0,
+				  "Non-zero offset in SGE[%d]!\n", i);
+
+			/* Rest of the data buffers are stored as skb frags */
+			page = virt_to_page(sg_vaddr);
+			head_page = virt_to_head_page(sg_vaddr);
+
+			/* Offset in page (which may be compound) */
+			page_offset = ((unsigned long)sg_vaddr &
+				(PAGE_SIZE - 1)) +
+				(page_address(page) - page_address(head_page));
+
+			skb_add_rx_frag(skb, i - 1, head_page, page_offset,
+					sg_length, DPAA2_ETH_RX_BUFFER_SIZE);
+		}
+
+		if (dpaa2_sg_is_final(sge))
+			break;
+	}
+
+	/* Count all data buffers + sgt buffer */
+	ch->buf_count -= i + 2;
+
+	return skb;
+}
+
+static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
+			 struct dpaa2_eth_channel *ch,
+			 const struct dpaa2_fd *fd,
+			 struct napi_struct *napi)
+{
+	dma_addr_t addr = dpaa2_fd_get_addr(fd);
+	u8 fd_format = dpaa2_fd_get_format(fd);
+	void *vaddr;
+	struct sk_buff *skb;
+	struct rtnl_link_stats64 *percpu_stats;
+	struct dpaa2_eth_stats *percpu_extras;
+	struct device *dev = priv->net_dev->dev.parent;
+	struct dpaa2_fas *fas;
+	u32 status = 0;
+
+	/* Tracing point */
+	trace_dpaa2_rx_fd(priv->net_dev, fd);
+
+	dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUFFER_SIZE, DMA_FROM_DEVICE);
+	vaddr = phys_to_virt(addr);
+
+	prefetch(vaddr + priv->buf_layout.private_data_size);
+	prefetch(vaddr + dpaa2_fd_get_offset(fd));
+
+	percpu_stats = this_cpu_ptr(priv->percpu_stats);
+	percpu_extras = this_cpu_ptr(priv->percpu_extras);
+
+	if (fd_format == dpaa2_fd_single) {
+		skb = dpaa2_eth_build_linear_skb(priv, ch, fd, vaddr);
+	} else if (fd_format == dpaa2_fd_sg) {
+		struct dpaa2_sg_entry *sgt =
+				vaddr + dpaa2_fd_get_offset(fd);
+		skb = dpaa2_eth_build_frag_skb(priv, ch, sgt);
+		put_page(virt_to_head_page(vaddr));
+		percpu_extras->rx_sg_frames++;
+		percpu_extras->rx_sg_bytes += dpaa2_fd_get_len(fd);
+	} else {
+		/* We don't support any other format */
+		netdev_err(priv->net_dev, "Received invalid frame format\n");
+		goto err_frame_format;
+	}
+
+	if (unlikely(!skb)) {
+		dev_err_once(dev, "error building skb\n");
+		goto err_build_skb;
+	}
+
+	prefetch(skb->data);
+
+	if (priv->ts_rx_en) {
+		struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
+		u64 *ns = (u64 *) (vaddr +
+				priv->buf_layout.private_data_size +
+				sizeof(struct dpaa2_fas));
+
+		*ns = DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS * (*ns);
+		memset(shhwtstamps, 0, sizeof(*shhwtstamps));
+		shhwtstamps->hwtstamp = ns_to_ktime(*ns);
+	}
+
+	/* Check if we need to validate the L4 csum */
+	if (likely(fd->simple.frc & DPAA2_FD_FRC_FASV)) {
+		fas = (struct dpaa2_fas *)
+				(vaddr + priv->buf_layout.private_data_size);
+		status = le32_to_cpu(fas->status);
+		dpaa2_eth_rx_csum(priv, status, skb);
+	}
+
+	skb->protocol = eth_type_trans(skb, priv->net_dev);
+
+	percpu_stats->rx_packets++;
+	percpu_stats->rx_bytes += skb->len;
+
+	if (priv->net_dev->features & NETIF_F_GRO)
+		napi_gro_receive(napi, skb);
+	else
+		netif_receive_skb(skb);
+
+	return;
+err_frame_format:
+err_build_skb:
+	dpaa2_eth_free_rx_fd(priv, fd, vaddr);
+	percpu_stats->rx_dropped++;
+}
+
+#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
+static void dpaa2_eth_rx_err(struct dpaa2_eth_priv *priv,
+			     struct dpaa2_eth_channel *ch,
+			     const struct dpaa2_fd *fd,
+			     struct napi_struct *napi __always_unused)
+{
+	struct device *dev = priv->net_dev->dev.parent;
+	dma_addr_t addr = dpaa2_fd_get_addr(fd);
+	void *vaddr;
+	struct rtnl_link_stats64 *percpu_stats;
+	struct dpaa2_fas *fas;
+	u32 status = 0;
+
+	dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUFFER_SIZE, DMA_FROM_DEVICE);
+	vaddr = phys_to_virt(addr);
+
+	if (fd->simple.frc & DPAA2_FD_FRC_FASV) {
+		fas = (struct dpaa2_fas *)
+			(vaddr + priv->buf_layout.private_data_size);
+		status = le32_to_cpu(fas->status);
+
+		/* All frames received on this queue should have at least
+		 * one of the Rx error bits set */
+		WARN_ON_ONCE((status & DPAA2_ETH_RX_ERR_MASK) == 0);
+		netdev_dbg(priv->net_dev, "Rx frame error: 0x%08x\n",
+			   status & DPAA2_ETH_RX_ERR_MASK);
+	}
+	dpaa2_eth_free_rx_fd(priv, fd, vaddr);
+
+	percpu_stats = this_cpu_ptr(priv->percpu_stats);
+	percpu_stats->rx_errors++;
+}
+#endif
+
+/* Consume all frames pull-dequeued into the store. This is the simplest way to
+ * make sure we don't accidentally issue another volatile dequeue which would
+ * overwrite (leak) frames already in the store.
+ *
+ * Observance of NAPI budget is not our concern, leaving that to the caller.
+ */
+static int dpaa2_eth_store_consume(struct dpaa2_eth_channel *ch)
+{
+	struct dpaa2_eth_priv *priv = ch->priv;
+	struct dpaa2_eth_fq *fq;
+	struct dpaa2_dq *dq;
+	const struct dpaa2_fd *fd;
+	int cleaned = 0;
+	int is_last;
+
+	do {
+		dq = dpaa2_io_store_next(ch->store, &is_last);
+		if (unlikely(!dq)) {
+			if (unlikely(!is_last)) {
+				netdev_dbg(priv->net_dev,
+					   "Channel %d reqturned no valid frames\n",
+					   ch->ch_id);
+				/* MUST retry until we get some sort of
+				 * valid response token (be it "empty dequeue"
+				 * or a valid frame).
+				 */
+				continue;
+			}
+			break;
+		}
+
+		/* Obtain FD and process it */
+		fd = dpaa2_dq_fd(dq);
+		fq = (struct dpaa2_eth_fq *)dpaa2_dq_fqd_ctx(dq);
+		fq->stats.frames++;
+
+		fq->consume(priv, ch, fd, &ch->napi);
+		cleaned++;
+	} while (!is_last);
+
+	return cleaned;
+}
+
+static int dpaa2_eth_build_sg_fd(struct dpaa2_eth_priv *priv,
+				 struct sk_buff *skb,
+				 struct dpaa2_fd *fd)
+{
+	struct device *dev = priv->net_dev->dev.parent;
+	void *sgt_buf = NULL;
+	dma_addr_t addr;
+	int nr_frags = skb_shinfo(skb)->nr_frags;
+	struct dpaa2_sg_entry *sgt;
+	int i, j, err;
+	int sgt_buf_size;
+	struct scatterlist *scl, *crt_scl;
+	int num_sg;
+	int num_dma_bufs;
+	struct dpaa2_eth_swa *bps;
+
+	/* Create and map scatterlist.
+	 * We don't advertise NETIF_F_FRAGLIST, so skb_to_sgvec() will not have
+	 * to go beyond nr_frags+1.
+	 * Note: We don't support chained scatterlists
+	 */
+	WARN_ON(PAGE_SIZE / sizeof(struct scatterlist) < nr_frags + 1);
+	scl = kcalloc(nr_frags + 1, sizeof(struct scatterlist), GFP_ATOMIC);
+	if (unlikely(!scl))
+		return -ENOMEM;
+
+	sg_init_table(scl, nr_frags + 1);
+	num_sg = skb_to_sgvec(skb, scl, 0, skb->len);
+	num_dma_bufs = dma_map_sg(dev, scl, num_sg, DMA_TO_DEVICE);
+	if (unlikely(!num_dma_bufs)) {
+		netdev_err(priv->net_dev, "dma_map_sg() error\n");
+		err = -ENOMEM;
+		goto dma_map_sg_failed;
+	}
+
+	/* Prepare the HW SGT structure */
+	sgt_buf_size = priv->tx_data_offset +
+		       sizeof(struct dpaa2_sg_entry) * (1 + num_dma_bufs);
+	sgt_buf = kzalloc(sgt_buf_size + DPAA2_ETH_TX_BUF_ALIGN, GFP_ATOMIC);
+	if (unlikely(!sgt_buf)) {
+		netdev_err(priv->net_dev, "failed to allocate SGT buffer\n");
+		err = -ENOMEM;
+		goto sgt_buf_alloc_failed;
+	}
+	sgt_buf = PTR_ALIGN(sgt_buf, DPAA2_ETH_TX_BUF_ALIGN);
+
+	/* PTA from egress side is passed as is to the confirmation side so
+	 * we need to clear some fields here in order to find consistent values
+	 * on TX confirmation. We are clearing FAS (Frame Annotation Status)
+	 * field here.
+	 */
+	memset(sgt_buf + priv->buf_layout.private_data_size, 0, 8);
+
+	sgt = (struct dpaa2_sg_entry *)(sgt_buf + priv->tx_data_offset);
+
+	/* Fill in the HW SGT structure.
+	 *
+	 * sgt_buf is zeroed out, so the following fields are implicit
+	 * in all sgt entries:
+	 *   - offset is 0
+	 *   - format is 'dpaa2_sg_single'
+	 */
+	for_each_sg(scl, crt_scl, num_dma_bufs, i) {
+		dpaa2_sg_set_addr(&sgt[i], sg_dma_address(crt_scl));
+		dpaa2_sg_set_len(&sgt[i], sg_dma_len(crt_scl));
+	}
+	dpaa2_sg_set_final(&sgt[i - 1], true);
+
+	/* Store the skb backpointer in the SGT buffer.
+	 * Fit the scatterlist and the number of buffers alongside the
+	 * skb backpointer in the SWA. We'll need all of them on Tx Conf.
+	 */
+	bps = (struct dpaa2_eth_swa *)sgt_buf;
+	bps->skb = skb;
+	bps->scl = scl;
+	bps->num_sg = num_sg;
+	bps->num_dma_bufs = num_dma_bufs;
+
+	for (j = 0; j < i; j++)
+		dpaa2_sg_cpu_to_le(&sgt[j]);
+
+	/* Separately map the SGT buffer */
+	addr = dma_map_single(dev, sgt_buf, sgt_buf_size, DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(dev, addr))) {
+		netdev_err(priv->net_dev, "dma_map_single() failed\n");
+		err = -ENOMEM;
+		goto dma_map_single_failed;
+	}
+	dpaa2_fd_set_offset(fd, priv->tx_data_offset);
+	dpaa2_fd_set_format(fd, dpaa2_fd_sg);
+	dpaa2_fd_set_addr(fd, addr);
+	dpaa2_fd_set_len(fd, skb->len);
+
+	fd->simple.ctrl = DPAA2_FD_CTRL_ASAL | DPAA2_FD_CTRL_PTA |
+			 DPAA2_FD_CTRL_PTV1;
+
+	return 0;
+
+dma_map_single_failed:
+	kfree(sgt_buf);
+sgt_buf_alloc_failed:
+	dma_unmap_sg(dev, scl, num_sg, DMA_TO_DEVICE);
+dma_map_sg_failed:
+	kfree(scl);
+	return err;
+}
+
+static int dpaa2_eth_build_single_fd(struct dpaa2_eth_priv *priv,
+				     struct sk_buff *skb,
+				     struct dpaa2_fd *fd)
+{
+	struct device *dev = priv->net_dev->dev.parent;
+	u8 *buffer_start;
+	struct sk_buff **skbh;
+	dma_addr_t addr;
+
+	buffer_start = PTR_ALIGN(skb->data - priv->tx_data_offset -
+				 DPAA2_ETH_TX_BUF_ALIGN,
+				 DPAA2_ETH_TX_BUF_ALIGN);
+
+	/* PTA from egress side is passed as is to the confirmation side so
+	 * we need to clear some fields here in order to find consistent values
+	 * on TX confirmation. We are clearing FAS (Frame Annotation Status)
+	 * field here.
+	 */
+	memset(buffer_start + priv->buf_layout.private_data_size, 0, 8);
+
+	/* Store a backpointer to the skb at the beginning of the buffer
+	 * (in the private data area) such that we can release it
+	 * on Tx confirm
+	 */
+	skbh = (struct sk_buff **)buffer_start;
+	*skbh = skb;
+
+	addr = dma_map_single(dev,
+			      buffer_start,
+			      skb_tail_pointer(skb) - buffer_start,
+			      DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(dev, addr))) {
+		dev_err(dev, "dma_map_single() failed\n");
+		return -EINVAL;
+	}
+
+	dpaa2_fd_set_addr(fd, addr);
+	dpaa2_fd_set_offset(fd, (u16)(skb->data - buffer_start));
+	dpaa2_fd_set_len(fd, skb->len);
+	dpaa2_fd_set_format(fd, dpaa2_fd_single);
+
+	fd->simple.ctrl = DPAA2_FD_CTRL_ASAL | DPAA2_FD_CTRL_PTA |
+			 DPAA2_FD_CTRL_PTV1;
+
+	return 0;
+}
+
+/* DMA-unmap and free FD and possibly SGT buffer allocated on Tx. The skb
+ * back-pointed to is also freed.
+ * This can be called either from dpaa2_eth_tx_conf() or on the error path of
+ * dpaa2_eth_tx().
+ * Optionally, return the frame annotation status word (FAS), which needs
+ * to be checked if we're on the confirmation path.
+ */
+static void dpaa2_eth_free_fd(const struct dpaa2_eth_priv *priv,
+			      const struct dpaa2_fd *fd,
+			      u32 *status)
+{
+	struct device *dev = priv->net_dev->dev.parent;
+	dma_addr_t fd_addr;
+	struct sk_buff **skbh, *skb;
+	unsigned char *buffer_start;
+	int unmap_size;
+	struct scatterlist *scl;
+	int num_sg, num_dma_bufs;
+	struct dpaa2_eth_swa *bps;
+	bool fd_single;
+	struct dpaa2_fas *fas;
+
+	fd_addr = dpaa2_fd_get_addr(fd);
+	skbh = phys_to_virt(fd_addr);
+	fd_single = (dpaa2_fd_get_format(fd) == dpaa2_fd_single);
+
+	if (fd_single) {
+		skb = *skbh;
+		buffer_start = (unsigned char *)skbh;
+		/* Accessing the skb buffer is safe before dma unmap, because
+		 * we didn't map the actual skb shell.
+		 */
+		dma_unmap_single(dev, fd_addr,
+				 skb_tail_pointer(skb) - buffer_start,
+				 DMA_TO_DEVICE);
+	} else {
+		bps = (struct dpaa2_eth_swa *)skbh;
+		skb = bps->skb;
+		scl = bps->scl;
+		num_sg = bps->num_sg;
+		num_dma_bufs = bps->num_dma_bufs;
+
+		/* Unmap the scatterlist */
+		dma_unmap_sg(dev, scl, num_sg, DMA_TO_DEVICE);
+		kfree(scl);
+
+		/* Unmap the SGT buffer */
+		unmap_size = priv->tx_data_offset +
+		       sizeof(struct dpaa2_sg_entry) * (1 + num_dma_bufs);
+		dma_unmap_single(dev, fd_addr, unmap_size, DMA_TO_DEVICE);
+	}
+
+	if (priv->ts_tx_en && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
+		struct skb_shared_hwtstamps shhwtstamps;
+		u64 *ns;
+
+		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+
+		ns = (u64 *)((void *)skbh +
+			priv->buf_layout.private_data_size +
+			sizeof(struct dpaa2_fas));
+		*ns = DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS * (*ns);
+		shhwtstamps.hwtstamp = ns_to_ktime(*ns);
+		skb_tstamp_tx(skb, &shhwtstamps);
+	}
+
+	/* Check the status from the Frame Annotation after we unmap the first
+	 * buffer but before we free it.
+	 */
+	if (status && (fd->simple.frc & DPAA2_FD_FRC_FASV)) {
+		fas = (struct dpaa2_fas *)
+			((void *)skbh + priv->buf_layout.private_data_size);
+		*status = le32_to_cpu(fas->status);
+	}
+
+	/* Free SGT buffer kmalloc'ed on tx */
+	if (!fd_single)
+		kfree(skbh);
+
+	/* Move on with skb release */
+	dev_kfree_skb(skb);
+}
+
+static int dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	struct dpaa2_fd fd;
+	struct rtnl_link_stats64 *percpu_stats;
+	struct dpaa2_eth_stats *percpu_extras;
+	int err, i;
+	/* TxConf FQ selection primarily based on cpu affinity; this is
+	 * non-migratable context, so it's safe to call smp_processor_id().
+	 */
+	u16 queue_mapping = smp_processor_id() % priv->dpni_attrs.max_senders;
+
+	percpu_stats = this_cpu_ptr(priv->percpu_stats);
+	percpu_extras = this_cpu_ptr(priv->percpu_extras);
+
+	/* Setup the FD fields */
+	memset(&fd, 0, sizeof(fd));
+
+	if (unlikely(skb_headroom(skb) < DPAA2_ETH_NEEDED_HEADROOM(priv))) {
+		struct sk_buff *ns;
+
+		dev_info_once(net_dev->dev.parent,
+			      "skb headroom too small, must realloc.\n");
+		ns = skb_realloc_headroom(skb, DPAA2_ETH_NEEDED_HEADROOM(priv));
+		if (unlikely(!ns)) {
+			percpu_stats->tx_dropped++;
+			goto err_alloc_headroom;
+		}
+		dev_kfree_skb(skb);
+		skb = ns;
+	}
+
+	/* We'll be holding a back-reference to the skb until Tx Confirmation;
+	 * we don't want that overwritten by a concurrent Tx with a cloned skb.
+	 */
+	skb = skb_unshare(skb, GFP_ATOMIC);
+	if (unlikely(!skb)) {
+		netdev_err(net_dev, "Out of memory for skb_unshare()");
+		/* skb_unshare() has already freed the skb */
+		percpu_stats->tx_dropped++;
+		return NETDEV_TX_OK;
+	}
+
+	if (skb_is_nonlinear(skb)) {
+		err = dpaa2_eth_build_sg_fd(priv, skb, &fd);
+		percpu_extras->tx_sg_frames++;
+		percpu_extras->tx_sg_bytes += skb->len;
+	} else {
+		err = dpaa2_eth_build_single_fd(priv, skb, &fd);
+	}
+
+	if (unlikely(err)) {
+		percpu_stats->tx_dropped++;
+		goto err_build_fd;
+	}
+
+	/* Tracing point */
+	trace_dpaa2_tx_fd(net_dev, &fd);
+
+	for (i = 0; i < (DPAA2_ETH_MAX_TX_QUEUES << 1); i++) {
+		err = dpaa2_io_service_enqueue_qd(NULL, priv->tx_qdid, 0,
+						 priv->fq[queue_mapping].flowid,
+						 &fd);
+		if (err != -EBUSY)
+			break;
+	}
+	percpu_extras->tx_portal_busy += i;
+	if (unlikely(err < 0)) {
+		netdev_dbg(net_dev, "error enqueueing Tx frame\n");
+		percpu_stats->tx_errors++;
+		/* Clean up everything, including freeing the skb */
+		dpaa2_eth_free_fd(priv, &fd, NULL);
+	} else {
+		percpu_stats->tx_packets++;
+		percpu_stats->tx_bytes += skb->len;
+	}
+
+	return NETDEV_TX_OK;
+
+err_build_fd:
+err_alloc_headroom:
+	dev_kfree_skb(skb);
+
+	return NETDEV_TX_OK;
+}
+
+static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
+			      struct dpaa2_eth_channel *ch,
+			      const struct dpaa2_fd *fd,
+			      struct napi_struct *napi __always_unused)
+{
+	struct rtnl_link_stats64 *percpu_stats;
+	struct dpaa2_eth_stats *percpu_extras;
+	u32 status = 0;
+
+	/* Tracing point */
+	trace_dpaa2_tx_conf_fd(priv->net_dev, fd);
+
+	percpu_extras = this_cpu_ptr(priv->percpu_extras);
+	percpu_extras->tx_conf_frames++;
+	percpu_extras->tx_conf_bytes += dpaa2_fd_get_len(fd);
+
+	dpaa2_eth_free_fd(priv, fd, &status);
+
+	if (unlikely(status & DPAA2_ETH_TXCONF_ERR_MASK)) {
+		netdev_err(priv->net_dev, "TxConf frame error(s): 0x%08x\n",
+			   status & DPAA2_ETH_TXCONF_ERR_MASK);
+		percpu_stats = this_cpu_ptr(priv->percpu_stats);
+		/* Tx-conf logically pertains to the egress path. */
+		percpu_stats->tx_errors++;
+	}
+}
+
+static int dpaa2_eth_set_rx_csum(struct dpaa2_eth_priv *priv, bool enable)
+{
+	int err;
+
+	err = dpni_set_l3_chksum_validation(priv->mc_io, 0, priv->mc_token,
+					    enable);
+	if (err) {
+		netdev_err(priv->net_dev,
+			   "dpni_set_l3_chksum_validation() failed\n");
+		return err;
+	}
+
+	err = dpni_set_l4_chksum_validation(priv->mc_io, 0, priv->mc_token,
+					    enable);
+	if (err) {
+		netdev_err(priv->net_dev,
+			   "dpni_set_l4_chksum_validation failed\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int dpaa2_eth_set_tx_csum(struct dpaa2_eth_priv *priv, bool enable)
+{
+	struct dpaa2_eth_fq *fq;
+	struct dpni_tx_flow_cfg tx_flow_cfg;
+	int err;
+	int i;
+
+	memset(&tx_flow_cfg, 0, sizeof(tx_flow_cfg));
+	tx_flow_cfg.options = DPNI_TX_FLOW_OPT_L3_CHKSUM_GEN |
+			      DPNI_TX_FLOW_OPT_L4_CHKSUM_GEN;
+	tx_flow_cfg.l3_chksum_gen = enable;
+	tx_flow_cfg.l4_chksum_gen = enable;
+
+	for (i = 0; i < priv->num_fqs; i++) {
+		fq = &priv->fq[i];
+		if (fq->type != DPAA2_TX_CONF_FQ)
+			continue;
+
+		/* The Tx flowid is kept in the corresponding TxConf FQ. */
+		err = dpni_set_tx_flow(priv->mc_io, 0, priv->mc_token,
+				       &fq->flowid, &tx_flow_cfg);
+		if (err) {
+			netdev_err(priv->net_dev, "dpni_set_tx_flow failed\n");
+			return err;
+		}
+	}
+
+	return 0;
+}
+
+static int dpaa2_bp_add_7(struct dpaa2_eth_priv *priv, u16 bpid)
+{
+	struct device *dev = priv->net_dev->dev.parent;
+	u64 buf_array[7];
+	void *buf;
+	dma_addr_t addr;
+	int i;
+
+	for (i = 0; i < 7; i++) {
+		/* Allocate buffer visible to WRIOP + skb shared info +
+		 * alignment padding
+		 */
+		buf = napi_alloc_frag(DPAA2_ETH_BUF_RAW_SIZE);
+		if (unlikely(!buf)) {
+			dev_err(dev, "buffer allocation failed\n");
+			goto err_alloc;
+		}
+		buf = PTR_ALIGN(buf, DPAA2_ETH_RX_BUF_ALIGN);
+
+		addr = dma_map_single(dev, buf, DPAA2_ETH_RX_BUFFER_SIZE,
+				      DMA_FROM_DEVICE);
+		if (unlikely(dma_mapping_error(dev, addr))) {
+			dev_err(dev, "dma_map_single() failed\n");
+			goto err_map;
+		}
+		buf_array[i] = addr;
+
+		/* tracing point */
+		trace_dpaa2_eth_buf_seed(priv->net_dev,
+					 buf, DPAA2_ETH_BUF_RAW_SIZE,
+					 addr, DPAA2_ETH_RX_BUFFER_SIZE,
+					 bpid);
+	}
+
+release_bufs:
+	/* In case the portal is busy, retry until successful.
+	 * The buffer release function would only fail if the QBMan portal
+	 * was busy, which implies portal contention (i.e. more CPUs than
+	 * portals, i.e. GPPs w/o affine DPIOs). For all practical purposes,
+	 * there is little we can realistically do, short of giving up -
+	 * in which case we'd risk depleting the buffer pool and never again
+	 * receiving the Rx interrupt which would kick-start the refill logic.
+	 * So just keep retrying, at the risk of being moved to ksoftirqd.
+	 */
+	while (dpaa2_io_service_release(NULL, bpid, buf_array, i))
+		cpu_relax();
+	return i;
+
+err_map:
+	put_page(virt_to_head_page(buf));
+err_alloc:
+	if (i)
+		goto release_bufs;
+
+	return 0;
+}
+
+static int dpaa2_dpbp_seed(struct dpaa2_eth_priv *priv, u16 bpid)
+{
+	int i, j;
+	int new_count;
+
+	/* This is the lazy seeding of Rx buffer pools.
+	 * dpaa2_bp_add_7() is also used on the Rx hotpath and calls
+	 * napi_alloc_frag(). The trouble with that is that it in turn ends up
+	 * calling this_cpu_ptr(), which mandates execution in atomic context.
+	 * Rather than splitting up the code, do a one-off preempt disable.
+	 */
+	preempt_disable();
+	for (j = 0; j < priv->num_channels; j++) {
+		for (i = 0; i < DPAA2_ETH_NUM_BUFS; i += 7) {
+			new_count = dpaa2_bp_add_7(priv, bpid);
+			priv->channel[j]->buf_count += new_count;
+
+			if (new_count < 7) {
+				preempt_enable();
+				goto out_of_memory;
+			}
+		}
+	}
+	preempt_enable();
+
+	return 0;
+
+out_of_memory:
+	return -ENOMEM;
+}
+
+/**
+ * Drain the specified number of buffers from the DPNI's private buffer pool.
+ * @count must not exceeed 7
+ */
+static void dpaa2_dpbp_drain_cnt(struct dpaa2_eth_priv *priv, int count)
+{
+	struct device *dev = priv->net_dev->dev.parent;
+	u64 buf_array[7];
+	void *vaddr;
+	int ret, i;
+
+	do {
+		ret = dpaa2_io_service_acquire(NULL, priv->dpbp_attrs.bpid,
+					      buf_array, count);
+		if (ret < 0) {
+			pr_err("dpaa2_io_service_acquire() failed\n");
+			return;
+		}
+		for (i = 0; i < ret; i++) {
+			/* Same logic as on regular Rx path */
+			dma_unmap_single(dev, buf_array[i],
+					 DPAA2_ETH_RX_BUFFER_SIZE,
+					 DMA_FROM_DEVICE);
+			vaddr = phys_to_virt(buf_array[i]);
+			put_page(virt_to_head_page(vaddr));
+		}
+	} while (ret);
+}
+
+static void __dpaa2_dpbp_free(struct dpaa2_eth_priv *priv)
+{
+	int i;
+
+	dpaa2_dpbp_drain_cnt(priv, 7);
+	dpaa2_dpbp_drain_cnt(priv, 1);
+
+	for (i = 0; i < priv->num_channels; i++)
+		priv->channel[i]->buf_count = 0;
+}
+
+/* Function is called from softirq context only, so we don't need to guard
+ * the access to percpu count
+ */
+static int dpaa2_dpbp_refill(struct dpaa2_eth_priv *priv,
+			     struct dpaa2_eth_channel *ch,
+			     u16 bpid)
+{
+	int new_count;
+	int err = 0;
+
+	if (unlikely(ch->buf_count < DPAA2_ETH_REFILL_THRESH)) {
+		do {
+			new_count = dpaa2_bp_add_7(priv, bpid);
+			if (unlikely(!new_count)) {
+				/* Out of memory; abort for now, we'll
+				 * try later on
+				 */
+				break;
+			}
+			ch->buf_count += new_count;
+		} while (ch->buf_count < DPAA2_ETH_NUM_BUFS);
+
+		if (unlikely(ch->buf_count < DPAA2_ETH_NUM_BUFS))
+			err = -ENOMEM;
+	}
+
+	return err;
+}
+
+static int __dpaa2_eth_pull_channel(struct dpaa2_eth_channel *ch)
+{
+	int err;
+	int dequeues = -1;
+	struct dpaa2_eth_priv *priv = ch->priv;
+
+	/* Retry while portal is busy */
+	do {
+		err = dpaa2_io_service_pull_channel(NULL, ch->ch_id, ch->store);
+		dequeues++;
+	} while (err == -EBUSY);
+	if (unlikely(err))
+		netdev_err(priv->net_dev, "dpaa2_io_service_pull err %d", err);
+
+	ch->stats.dequeue_portal_busy += dequeues;
+	return err;
+}
+
+static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
+{
+	struct dpaa2_eth_channel *ch;
+	int cleaned = 0, store_cleaned;
+	struct dpaa2_eth_priv *priv;
+	int err;
+
+	ch = container_of(napi, struct dpaa2_eth_channel, napi);
+	priv = ch->priv;
+
+	__dpaa2_eth_pull_channel(ch);
+
+	do {
+		/* Refill pool if appropriate */
+		dpaa2_dpbp_refill(priv, ch, priv->dpbp_attrs.bpid);
+
+		store_cleaned = dpaa2_eth_store_consume(ch);
+		cleaned += store_cleaned;
+
+		if (store_cleaned == 0 ||
+		    cleaned > budget - DPAA2_ETH_STORE_SIZE)
+			break;
+
+		/* Try to dequeue some more */
+		err = __dpaa2_eth_pull_channel(ch);
+		if (unlikely(err))
+			break;
+	} while (1);
+
+	if (cleaned < budget) {
+		napi_complete_done(napi, cleaned);
+		err = dpaa2_io_service_rearm(NULL, &ch->nctx);
+		if (unlikely(err))
+			netdev_err(priv->net_dev,
+				   "Notif rearm failed for channel %d\n",
+				   ch->ch_id);
+	}
+
+	ch->stats.frames += cleaned;
+
+	return cleaned;
+}
+
+static void dpaa2_eth_napi_enable(struct dpaa2_eth_priv *priv)
+{
+	struct dpaa2_eth_channel *ch;
+	int i;
+
+	for (i = 0; i < priv->num_channels; i++) {
+		ch = priv->channel[i];
+		napi_enable(&ch->napi);
+	}
+}
+
+static void dpaa2_eth_napi_disable(struct dpaa2_eth_priv *priv)
+{
+	struct dpaa2_eth_channel *ch;
+	int i;
+
+	for (i = 0; i < priv->num_channels; i++) {
+		ch = priv->channel[i];
+		napi_disable(&ch->napi);
+	}
+}
+
+static int dpaa2_link_state_update(struct dpaa2_eth_priv *priv)
+{
+	struct dpni_link_state state;
+	int err;
+
+	err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
+	if (unlikely(err)) {
+		netdev_err(priv->net_dev,
+			   "dpni_get_link_state() failed\n");
+		return err;
+	}
+
+	/* Chech link state; speed / duplex changes are not treated yet */
+	if (priv->link_state.up == state.up)
+		return 0;
+
+	priv->link_state = state;
+	if (state.up) {
+		netif_carrier_on(priv->net_dev);
+		netif_tx_start_all_queues(priv->net_dev);
+	} else {
+		netif_tx_stop_all_queues(priv->net_dev);
+		netif_carrier_off(priv->net_dev);
+	}
+
+	netdev_info(priv->net_dev, "Link Event: state %s",
+		    state.up ? "up" : "down");
+
+	return 0;
+}
+
+static int dpaa2_eth_open(struct net_device *net_dev)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	int err;
+
+	err = dpaa2_dpbp_seed(priv, priv->dpbp_attrs.bpid);
+	if (err) {
+		/* Not much to do; the buffer pool, though not filled up,
+		 * may still contain some buffers which would enable us
+		 * to limp on.
+		 */
+		netdev_err(net_dev, "Buffer seeding failed for DPBP %d (bpid=%d)\n",
+			   priv->dpbp_dev->obj_desc.id, priv->dpbp_attrs.bpid);
+	}
+
+	/* We'll only start the txqs when the link is actually ready; make sure
+	 * we don't race against the link up notification, which may come
+	 * immediately after dpni_enable();
+	 */
+	netif_tx_stop_all_queues(net_dev);
+	dpaa2_eth_napi_enable(priv);
+	/* Also, explicitly set carrier off, otherwise netif_carrier_ok() will
+	 * return true and cause 'ip link show' to report the LOWER_UP flag,
+	 * even though the link notification wasn't even received.
+	 */
+	netif_carrier_off(net_dev);
+
+	err = dpni_enable(priv->mc_io, 0, priv->mc_token);
+	if (err < 0) {
+		dev_err(net_dev->dev.parent, "dpni_enable() failed\n");
+		goto enable_err;
+	}
+
+	/* If the DPMAC object has already processed the link up interrupt,
+	 * we have to learn the link state ourselves.
+	 */
+	err = dpaa2_link_state_update(priv);
+	if (err < 0) {
+		dev_err(net_dev->dev.parent, "Can't update link state\n");
+		goto link_state_err;
+	}
+
+	return 0;
+
+link_state_err:
+enable_err:
+	dpaa2_eth_napi_disable(priv);
+	__dpaa2_dpbp_free(priv);
+	return err;
+}
+
+static int dpaa2_eth_stop(struct net_device *net_dev)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+
+	/* Stop Tx and Rx traffic */
+	netif_tx_stop_all_queues(net_dev);
+	netif_carrier_off(net_dev);
+	dpni_disable(priv->mc_io, 0, priv->mc_token);
+
+	msleep(500);
+
+	dpaa2_eth_napi_disable(priv);
+	msleep(100);
+
+	__dpaa2_dpbp_free(priv);
+
+	return 0;
+}
+
+static int dpaa2_eth_init(struct net_device *net_dev)
+{
+	u64 supported = 0;
+	u64 not_supported = 0;
+	const struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	u32 options = priv->dpni_attrs.options;
+
+	/* Capabilities listing */
+	supported |= IFF_LIVE_ADDR_CHANGE | IFF_PROMISC | IFF_ALLMULTI;
+
+	if (options & DPNI_OPT_UNICAST_FILTER)
+		supported |= IFF_UNICAST_FLT;
+	else
+		not_supported |= IFF_UNICAST_FLT;
+
+	if (options & DPNI_OPT_MULTICAST_FILTER)
+		supported |= IFF_MULTICAST;
+	else
+		not_supported |= IFF_MULTICAST;
+
+	net_dev->priv_flags |= supported;
+	net_dev->priv_flags &= ~not_supported;
+
+	/* Features */
+	net_dev->features = NETIF_F_RXCSUM |
+			    NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+			    NETIF_F_SG | NETIF_F_HIGHDMA |
+			    NETIF_F_LLTX;
+	net_dev->hw_features = net_dev->features;
+
+	return 0;
+}
+
+static int dpaa2_eth_set_addr(struct net_device *net_dev, void *addr)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	struct device *dev = net_dev->dev.parent;
+	int err;
+
+	err = eth_mac_addr(net_dev, addr);
+	if (err < 0) {
+		dev_err(dev, "eth_mac_addr() failed with error %d\n", err);
+		return err;
+	}
+
+	err = dpni_set_primary_mac_addr(priv->mc_io, 0, priv->mc_token,
+					net_dev->dev_addr);
+	if (err) {
+		dev_err(dev, "dpni_set_primary_mac_addr() failed (%d)\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+/** Fill in counters maintained by the GPP driver. These may be different from
+ * the hardware counters obtained by ethtool.
+ */
+static struct rtnl_link_stats64
+*dpaa2_eth_get_stats(struct net_device *net_dev,
+		     struct rtnl_link_stats64 *stats)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	struct rtnl_link_stats64 *percpu_stats;
+	u64 *cpustats;
+	u64 *netstats = (u64 *)stats;
+	int i, j;
+	int num = sizeof(struct rtnl_link_stats64) / sizeof(u64);
+
+	for_each_possible_cpu(i) {
+		percpu_stats = per_cpu_ptr(priv->percpu_stats, i);
+		cpustats = (u64 *)percpu_stats;
+		for (j = 0; j < num; j++)
+			netstats[j] += cpustats[j];
+	}
+
+	return stats;
+}
+
+static int dpaa2_eth_change_mtu(struct net_device *net_dev, int mtu)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	int err;
+
+	if (mtu < 68 || mtu > DPAA2_ETH_MAX_MTU) {
+		netdev_err(net_dev, "Invalid MTU %d. Valid range is: 68..%d\n",
+			   mtu, DPAA2_ETH_MAX_MTU);
+		return -EINVAL;
+	}
+
+	/* Set the maximum Rx frame length to match the transmit side;
+	 * account for L2 headers when computing the MFL
+	 */
+	err = dpni_set_max_frame_length(priv->mc_io, 0, priv->mc_token,
+					(u16)DPAA2_ETH_L2_MAX_FRM(mtu));
+	if (err) {
+		netdev_err(net_dev, "dpni_set_mfl() failed\n");
+		return err;
+	}
+
+	net_dev->mtu = mtu;
+	return 0;
+}
+
+/* Convenience macro to make code littered with error checking more readable */
+#define DPAA2_ETH_WARN_IF_ERR(err, netdevp, format, ...) \
+do { \
+	if (err) \
+		netdev_warn(netdevp, format, ##__VA_ARGS__); \
+} while (0)
+
+/* Copy mac unicast addresses from @net_dev to @priv.
+ * Its sole purpose is to make dpaa2_eth_set_rx_mode() more readable.
+ */
+static void _dpaa2_eth_hw_add_uc_addr(const struct net_device *net_dev,
+				      struct dpaa2_eth_priv *priv)
+{
+	struct netdev_hw_addr *ha;
+	int err;
+
+	netdev_for_each_uc_addr(ha, net_dev) {
+		err = dpni_add_mac_addr(priv->mc_io, 0, priv->mc_token,
+					ha->addr);
+		DPAA2_ETH_WARN_IF_ERR(err, priv->net_dev,
+				      "Could not add ucast MAC %pM to the filtering table (err %d)\n",
+				      ha->addr, err);
+	}
+}
+
+/* Copy mac multicast addresses from @net_dev to @priv
+ * Its sole purpose is to make dpaa2_eth_set_rx_mode() more readable.
+ */
+static void _dpaa2_eth_hw_add_mc_addr(const struct net_device *net_dev,
+				      struct dpaa2_eth_priv *priv)
+{
+	struct netdev_hw_addr *ha;
+	int err;
+
+	netdev_for_each_mc_addr(ha, net_dev) {
+		err = dpni_add_mac_addr(priv->mc_io, 0, priv->mc_token,
+					ha->addr);
+		DPAA2_ETH_WARN_IF_ERR(err, priv->net_dev,
+				      "Could not add mcast MAC %pM to the filtering table (err %d)\n",
+				      ha->addr, err);
+	}
+}
+
+static void dpaa2_eth_set_rx_mode(struct net_device *net_dev)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	int uc_count = netdev_uc_count(net_dev);
+	int mc_count = netdev_mc_count(net_dev);
+	u8 max_uc = priv->dpni_attrs.max_unicast_filters;
+	u8 max_mc = priv->dpni_attrs.max_multicast_filters;
+	u32 options = priv->dpni_attrs.options;
+	u16 mc_token = priv->mc_token;
+	struct fsl_mc_io *mc_io = priv->mc_io;
+	int err;
+
+	/* Basic sanity checks; these probably indicate a misconfiguration */
+	if (!(options & DPNI_OPT_UNICAST_FILTER) && max_uc != 0)
+		netdev_info(net_dev,
+			    "max_unicast_filters=%d, you must have DPNI_OPT_UNICAST_FILTER in the DPL\n",
+			    max_uc);
+	if (!(options & DPNI_OPT_MULTICAST_FILTER) && max_mc != 0)
+		netdev_info(net_dev,
+			    "max_multicast_filters=%d, you must have DPNI_OPT_MULTICAST_FILTER in the DPL\n",
+			    max_mc);
+
+	/* Force promiscuous if the uc or mc counts exceed our capabilities. */
+	if (uc_count > max_uc) {
+		netdev_info(net_dev,
+			    "Unicast addr count reached %d, max allowed is %d; forcing promisc\n",
+			    uc_count, max_uc);
+		goto force_promisc;
+	}
+	if (mc_count > max_mc) {
+		netdev_info(net_dev,
+			    "Multicast addr count reached %d, max allowed is %d; forcing promisc\n",
+			    mc_count, max_mc);
+		goto force_mc_promisc;
+	}
+
+	/* Adjust promisc settings due to flag combinations */
+	if (net_dev->flags & IFF_PROMISC) {
+		goto force_promisc;
+	} else if (net_dev->flags & IFF_ALLMULTI) {
+		/* First, rebuild unicast filtering table. This should be done
+		 * in promisc mode, in order to avoid frame loss while we
+		 * progressively add entries to the table.
+		 * We don't know whether we had been in promisc already, and
+		 * making an MC call to find it is expensive; so set uc promisc
+		 * nonetheless.
+		 */
+		err = dpni_set_unicast_promisc(mc_io, 0, mc_token, 1);
+		DPAA2_ETH_WARN_IF_ERR(err, net_dev, "Can't set uc promisc\n");
+
+		/* Actual uc table reconstruction. */
+		err = dpni_clear_mac_filters(mc_io, 0, mc_token, 1, 0);
+		DPAA2_ETH_WARN_IF_ERR(err, net_dev, "Can't clear uc filters\n");
+		_dpaa2_eth_hw_add_uc_addr(net_dev, priv);
+
+		/* Finally, clear uc promisc and set mc promisc as requested. */
+		err = dpni_set_unicast_promisc(mc_io, 0, mc_token, 0);
+		DPAA2_ETH_WARN_IF_ERR(err, net_dev, "Can't clear uc promisc\n");
+		goto force_mc_promisc;
+	}
+
+	/* Neither unicast, nor multicast promisc will be on... eventually.
+	 * For now, rebuild mac filtering tables while forcing both of them on.
+	 */
+	err = dpni_set_unicast_promisc(mc_io, 0, mc_token, 1);
+	DPAA2_ETH_WARN_IF_ERR(err, net_dev, "Can't set uc promisc (%d)\n", err);
+	err = dpni_set_multicast_promisc(mc_io, 0, mc_token, 1);
+	DPAA2_ETH_WARN_IF_ERR(err, net_dev, "Can't set mc promisc (%d)\n", err);
+
+	/* Actual mac filtering tables reconstruction */
+	err = dpni_clear_mac_filters(mc_io, 0, mc_token, 1, 1);
+	DPAA2_ETH_WARN_IF_ERR(err, net_dev, "Can't clear mac filters\n");
+	_dpaa2_eth_hw_add_mc_addr(net_dev, priv);
+	_dpaa2_eth_hw_add_uc_addr(net_dev, priv);
+
+	/* Now we can clear both ucast and mcast promisc, without risking
+	 * to drop legitimate frames anymore.
+	 */
+	err = dpni_set_unicast_promisc(mc_io, 0, mc_token, 0);
+	DPAA2_ETH_WARN_IF_ERR(err, net_dev, "Can't clear ucast promisc\n");
+	err = dpni_set_multicast_promisc(mc_io, 0, mc_token, 0);
+	DPAA2_ETH_WARN_IF_ERR(err, net_dev, "Can't clear mcast promisc\n");
+
+	return;
+
+force_promisc:
+	err = dpni_set_unicast_promisc(mc_io, 0, mc_token, 1);
+	DPAA2_ETH_WARN_IF_ERR(err, net_dev, "Can't set ucast promisc\n");
+force_mc_promisc:
+	err = dpni_set_multicast_promisc(mc_io, 0, mc_token, 1);
+	DPAA2_ETH_WARN_IF_ERR(err, net_dev, "Can't set mcast promisc\n");
+}
+
+static int dpaa2_eth_set_features(struct net_device *net_dev,
+				  netdev_features_t features)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	netdev_features_t changed = features ^ net_dev->features;
+	int err;
+
+	if (changed & NETIF_F_RXCSUM) {
+		bool enable = !!(features & NETIF_F_RXCSUM);
+
+		err = dpaa2_eth_set_rx_csum(priv, enable);
+		if (err)
+			return err;
+	}
+
+	if (changed & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) {
+		bool enable = !!(features &
+				 (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM));
+		err = dpaa2_eth_set_tx_csum(priv, enable);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int dpaa2_eth_ts_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(dev);
+	struct hwtstamp_config config;
+
+	if (copy_from_user(&config, rq->ifr_data, sizeof(config)))
+		return -EFAULT;
+
+	switch (config.tx_type) {
+	case HWTSTAMP_TX_OFF:
+		priv->ts_tx_en = false;
+		break;
+	case HWTSTAMP_TX_ON:
+		priv->ts_tx_en = true;
+		break;
+	default:
+		return -ERANGE;
+	}
+
+	if (config.rx_filter == HWTSTAMP_FILTER_NONE)
+		priv->ts_rx_en = false;
+	else {
+		priv->ts_rx_en = true;
+		/* TS is set for all frame types, not only those requested */
+		config.rx_filter = HWTSTAMP_FILTER_ALL;
+	}
+
+	return copy_to_user(rq->ifr_data, &config, sizeof(config)) ?
+			-EFAULT : 0;
+}
+
+static int dpaa2_eth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+	if (cmd == SIOCSHWTSTAMP)
+		return dpaa2_eth_ts_ioctl(dev, rq, cmd);
+	else
+		return -EINVAL;
+}
+
+static const struct net_device_ops dpaa2_eth_ops = {
+	.ndo_open = dpaa2_eth_open,
+	.ndo_start_xmit = dpaa2_eth_tx,
+	.ndo_stop = dpaa2_eth_stop,
+	.ndo_init = dpaa2_eth_init,
+	.ndo_set_mac_address = dpaa2_eth_set_addr,
+	.ndo_get_stats64 = dpaa2_eth_get_stats,
+	.ndo_change_mtu = dpaa2_eth_change_mtu,
+	.ndo_set_rx_mode = dpaa2_eth_set_rx_mode,
+	.ndo_set_features = dpaa2_eth_set_features,
+	.ndo_do_ioctl = dpaa2_eth_ioctl,
+};
+
+static void dpaa2_eth_cdan_cb(struct dpaa2_io_notification_ctx *ctx)
+{
+	struct dpaa2_eth_channel *ch;
+
+	ch = container_of(ctx, struct dpaa2_eth_channel, nctx);
+
+	/* Update NAPI statistics */
+	ch->stats.cdan++;
+
+	napi_schedule_irqoff(&ch->napi);
+}
+
+static void dpaa2_eth_setup_fqs(struct dpaa2_eth_priv *priv)
+{
+	int i;
+
+	/* We have one TxConf FQ per Tx flow */
+	for (i = 0; i < priv->dpni_attrs.max_senders; i++) {
+		priv->fq[priv->num_fqs].netdev_priv = priv;
+		priv->fq[priv->num_fqs].type = DPAA2_TX_CONF_FQ;
+		priv->fq[priv->num_fqs].consume = dpaa2_eth_tx_conf;
+		priv->fq[priv->num_fqs++].flowid = DPNI_NEW_FLOW_ID;
+	}
+
+	/* The number of Rx queues (Rx distribution width) may be different from
+	 * the number of cores.
+	 * We only support one traffic class for now.
+	 */
+	for (i = 0; i < dpaa2_queue_count(priv); i++) {
+		priv->fq[priv->num_fqs].netdev_priv = priv;
+		priv->fq[priv->num_fqs].type = DPAA2_RX_FQ;
+		priv->fq[priv->num_fqs].consume = dpaa2_eth_rx;
+		priv->fq[priv->num_fqs++].flowid = (u16)i;
+	}
+
+#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
+	/* We have exactly one Rx error queue per DPNI */
+	priv->fq[priv->num_fqs].netdev_priv = priv;
+	priv->fq[priv->num_fqs].type = DPAA2_RX_ERR_FQ;
+	priv->fq[priv->num_fqs++].consume = dpaa2_eth_rx_err;
+#endif
+}
+
+static int check_obj_version(struct fsl_mc_device *ls_dev, u16 mc_version)
+{
+	char *name = ls_dev->obj_desc.type;
+	struct device *dev = &ls_dev->dev;
+	u16 supported_version, flib_version;
+
+	if (strcmp(name, "dpni") == 0) {
+		flib_version = DPNI_VER_MAJOR;
+		supported_version = DPAA2_SUPPORTED_DPNI_VERSION;
+	} else if (strcmp(name, "dpbp") == 0) {
+		flib_version = DPBP_VER_MAJOR;
+		supported_version = DPAA2_SUPPORTED_DPBP_VERSION;
+	} else if (strcmp(name, "dpcon") == 0) {
+		flib_version = DPCON_VER_MAJOR;
+		supported_version = DPAA2_SUPPORTED_DPCON_VERSION;
+	} else {
+		dev_err(dev, "invalid object type (%s)\n", name);
+		return -EINVAL;
+	}
+
+	/* Check that the FLIB-defined version matches the one reported by MC */
+	if (mc_version != flib_version) {
+		dev_err(dev,
+			"%s FLIB version mismatch: MC reports %d, we have %d\n",
+			name, mc_version, flib_version);
+		return -EINVAL;
+	}
+
+	/* ... and that we actually support it */
+	if (mc_version < supported_version) {
+		dev_err(dev, "Unsupported %s FLIB version (%d)\n",
+			name, mc_version);
+		return -EINVAL;
+	}
+	dev_dbg(dev, "Using %s FLIB version %d\n", name, mc_version);
+
+	return 0;
+}
+
+static struct fsl_mc_device *dpaa2_dpcon_setup(struct dpaa2_eth_priv *priv)
+{
+	struct fsl_mc_device *dpcon;
+	struct device *dev = priv->net_dev->dev.parent;
+	struct dpcon_attr attrs;
+	int err;
+
+	err = fsl_mc_object_allocate(to_fsl_mc_device(dev),
+				     FSL_MC_POOL_DPCON, &dpcon);
+	if (err) {
+		dev_info(dev, "Not enough DPCONs, will go on as-is\n");
+		return NULL;
+	}
+
+	err = dpcon_open(priv->mc_io, 0, dpcon->obj_desc.id, &dpcon->mc_handle);
+	if (err) {
+		dev_err(dev, "dpcon_open() failed\n");
+		goto err_open;
+	}
+
+	err = dpcon_get_attributes(priv->mc_io, 0, dpcon->mc_handle, &attrs);
+	if (err) {
+		dev_err(dev, "dpcon_get_attributes() failed\n");
+		goto err_get_attr;
+	}
+
+	err = check_obj_version(dpcon, attrs.version.major);
+	if (err)
+		goto err_dpcon_ver;
+
+	err = dpcon_enable(priv->mc_io, 0, dpcon->mc_handle);
+	if (err) {
+		dev_err(dev, "dpcon_enable() failed\n");
+		goto err_enable;
+	}
+
+	return dpcon;
+
+err_enable:
+err_dpcon_ver:
+err_get_attr:
+	dpcon_close(priv->mc_io, 0, dpcon->mc_handle);
+err_open:
+	fsl_mc_object_free(dpcon);
+
+	return NULL;
+}
+
+static void dpaa2_dpcon_free(struct dpaa2_eth_priv *priv,
+			     struct fsl_mc_device *dpcon)
+{
+	dpcon_disable(priv->mc_io, 0, dpcon->mc_handle);
+	dpcon_close(priv->mc_io, 0, dpcon->mc_handle);
+	fsl_mc_object_free(dpcon);
+}
+
+static struct dpaa2_eth_channel *
+dpaa2_alloc_channel(struct dpaa2_eth_priv *priv)
+{
+	struct dpaa2_eth_channel *channel;
+	struct dpcon_attr attr;
+	struct device *dev = priv->net_dev->dev.parent;
+	int err;
+
+	channel = kzalloc(sizeof(*channel), GFP_ATOMIC);
+	if (!channel) {
+		dev_err(dev, "Memory allocation failed\n");
+		return NULL;
+	}
+
+	channel->dpcon = dpaa2_dpcon_setup(priv);
+	if (!channel->dpcon)
+		goto err_setup;
+
+	err = dpcon_get_attributes(priv->mc_io, 0, channel->dpcon->mc_handle,
+				   &attr);
+	if (err) {
+		dev_err(dev, "dpcon_get_attributes() failed\n");
+		goto err_get_attr;
+	}
+
+	channel->dpcon_id = attr.id;
+	channel->ch_id = attr.qbman_ch_id;
+	channel->priv = priv;
+
+	return channel;
+
+err_get_attr:
+	dpaa2_dpcon_free(priv, channel->dpcon);
+err_setup:
+	kfree(channel);
+	return NULL;
+}
+
+static void dpaa2_free_channel(struct dpaa2_eth_priv *priv,
+			       struct dpaa2_eth_channel *channel)
+{
+	dpaa2_dpcon_free(priv, channel->dpcon);
+	kfree(channel);
+}
+
+static int dpaa2_dpio_setup(struct dpaa2_eth_priv *priv)
+{
+	struct dpaa2_io_notification_ctx *nctx;
+	struct dpaa2_eth_channel *channel;
+	struct dpcon_notification_cfg dpcon_notif_cfg;
+	struct device *dev = priv->net_dev->dev.parent;
+	int i, err;
+
+	/* Don't allocate more channels than strictly necessary and assign
+	 * them to cores starting from the first one available in
+	 * cpu_online_mask.
+	 * If the number of channels is lower than the number of cores,
+	 * there will be no rx/tx conf processing on the last cores in the mask.
+	 */
+	cpumask_clear(&priv->dpio_cpumask);
+	for_each_online_cpu(i) {
+		/* Try to allocate a channel */
+		channel = dpaa2_alloc_channel(priv);
+		if (!channel)
+			goto err_alloc_ch;
+
+		priv->channel[priv->num_channels] = channel;
+
+		nctx = &channel->nctx;
+		nctx->is_cdan = 1;
+		nctx->cb = dpaa2_eth_cdan_cb;
+		nctx->id = channel->ch_id;
+		nctx->desired_cpu = i;
+
+		/* Register the new context */
+		err = dpaa2_io_service_register(NULL, nctx);
+		if (err) {
+			dev_info(dev, "No affine DPIO for core %d\n", i);
+			/* This core doesn't have an affine DPIO, but there's
+			 * a chance another one does, so keep trying
+			 */
+			dpaa2_free_channel(priv, channel);
+			continue;
+		}
+
+		/* Register DPCON notification with MC */
+		dpcon_notif_cfg.dpio_id = nctx->dpio_id;
+		dpcon_notif_cfg.priority = 0;
+		dpcon_notif_cfg.user_ctx = nctx->qman64;
+		err = dpcon_set_notification(priv->mc_io, 0,
+					     channel->dpcon->mc_handle,
+					     &dpcon_notif_cfg);
+		if (err) {
+			dev_err(dev, "dpcon_set_notification failed()\n");
+			goto err_set_cdan;
+		}
+
+		/* If we managed to allocate a channel and also found an affine
+		 * DPIO for this core, add it to the final mask
+		 */
+		cpumask_set_cpu(i, &priv->dpio_cpumask);
+		priv->num_channels++;
+
+		if (priv->num_channels == dpaa2_max_channels(priv))
+			break;
+	}
+
+	/* Tx confirmation queues can only be serviced by cpus
+	 * with an affine DPIO/channel
+	 */
+	cpumask_copy(&priv->txconf_cpumask, &priv->dpio_cpumask);
+
+	return 0;
+
+err_set_cdan:
+	dpaa2_io_service_deregister(NULL, nctx);
+	dpaa2_free_channel(priv, channel);
+err_alloc_ch:
+	if (cpumask_empty(&priv->dpio_cpumask)) {
+		dev_err(dev, "No cpu with an affine DPIO/DPCON\n");
+		return -ENODEV;
+	}
+	cpumask_copy(&priv->txconf_cpumask, &priv->dpio_cpumask);
+
+	return 0;
+}
+
+static void dpaa2_dpio_free(struct dpaa2_eth_priv *priv)
+{
+	int i;
+	struct dpaa2_eth_channel *ch;
+
+	/* deregister CDAN notifications and free channels */
+	for (i = 0; i < priv->num_channels; i++) {
+		ch = priv->channel[i];
+		dpaa2_io_service_deregister(NULL, &ch->nctx);
+		dpaa2_free_channel(priv, ch);
+	}
+}
+
+static struct dpaa2_eth_channel *
+dpaa2_get_channel_by_cpu(struct dpaa2_eth_priv *priv, int cpu)
+{
+	struct device *dev = priv->net_dev->dev.parent;
+	int i;
+
+	for (i = 0; i < priv->num_channels; i++)
+		if (priv->channel[i]->nctx.desired_cpu == cpu)
+			return priv->channel[i];
+
+	/* We should never get here. Issue a warning and return
+	 * the first channel, because it's still better than nothing
+	 */
+	dev_warn(dev, "No affine channel found for cpu %d\n", cpu);
+
+	return priv->channel[0];
+}
+
+static void dpaa2_set_fq_affinity(struct dpaa2_eth_priv *priv)
+{
+	struct device *dev = priv->net_dev->dev.parent;
+	struct dpaa2_eth_fq *fq;
+	int rx_cpu, txconf_cpu;
+	int i;
+
+	/* For each FQ, pick one channel/CPU to deliver frames to.
+	 * This may well change at runtime, either through irqbalance or
+	 * through direct user intervention.
+	 */
+	rx_cpu = cpumask_first(&priv->dpio_cpumask);
+	txconf_cpu = cpumask_first(&priv->txconf_cpumask);
+
+	for (i = 0; i < priv->num_fqs; i++) {
+		fq = &priv->fq[i];
+		switch (fq->type) {
+		case DPAA2_RX_FQ:
+		case DPAA2_RX_ERR_FQ:
+			fq->target_cpu = rx_cpu;
+			cpumask_rr(rx_cpu, &priv->dpio_cpumask);
+			break;
+		case DPAA2_TX_CONF_FQ:
+			fq->target_cpu = txconf_cpu;
+			cpumask_rr(txconf_cpu, &priv->txconf_cpumask);
+			break;
+		default:
+			dev_err(dev, "Unknown FQ type: %d\n", fq->type);
+		}
+		fq->channel = dpaa2_get_channel_by_cpu(priv, fq->target_cpu);
+	}
+}
+
+static int dpaa2_dpbp_setup(struct dpaa2_eth_priv *priv)
+{
+	int err;
+	struct fsl_mc_device *dpbp_dev;
+	struct device *dev = priv->net_dev->dev.parent;
+
+	err = fsl_mc_object_allocate(to_fsl_mc_device(dev), FSL_MC_POOL_DPBP,
+				     &dpbp_dev);
+	if (err) {
+		dev_err(dev, "DPBP device allocation failed\n");
+		return err;
+	}
+
+	priv->dpbp_dev = dpbp_dev;
+
+	err = dpbp_open(priv->mc_io, 0, priv->dpbp_dev->obj_desc.id,
+			&dpbp_dev->mc_handle);
+	if (err) {
+		dev_err(dev, "dpbp_open() failed\n");
+		goto err_open;
+	}
+
+	err = dpbp_enable(priv->mc_io, 0, dpbp_dev->mc_handle);
+	if (err) {
+		dev_err(dev, "dpbp_enable() failed\n");
+		goto err_enable;
+	}
+
+	err = dpbp_get_attributes(priv->mc_io, 0, dpbp_dev->mc_handle,
+				  &priv->dpbp_attrs);
+	if (err) {
+		dev_err(dev, "dpbp_get_attributes() failed\n");
+		goto err_get_attr;
+	}
+
+	err = check_obj_version(dpbp_dev, priv->dpbp_attrs.version.major);
+	if (err)
+		goto err_dpbp_ver;
+
+	return 0;
+
+err_dpbp_ver:
+err_get_attr:
+	dpbp_disable(priv->mc_io, 0, dpbp_dev->mc_handle);
+err_enable:
+	dpbp_close(priv->mc_io, 0, dpbp_dev->mc_handle);
+err_open:
+	fsl_mc_object_free(dpbp_dev);
+
+	return err;
+}
+
+static void dpaa2_dpbp_free(struct dpaa2_eth_priv *priv)
+{
+	__dpaa2_dpbp_free(priv);
+	dpbp_disable(priv->mc_io, 0, priv->dpbp_dev->mc_handle);
+	dpbp_close(priv->mc_io, 0, priv->dpbp_dev->mc_handle);
+	fsl_mc_object_free(priv->dpbp_dev);
+}
+
+static int dpaa2_dpni_setup(struct fsl_mc_device *ls_dev)
+{
+	struct device *dev = &ls_dev->dev;
+	struct dpaa2_eth_priv *priv;
+	struct net_device *net_dev;
+	void *dma_mem;
+	int err;
+
+	net_dev = dev_get_drvdata(dev);
+	priv = netdev_priv(net_dev);
+
+	priv->dpni_id = ls_dev->obj_desc.id;
+
+	/* and get a handle for the DPNI this interface is associate with */
+	err = dpni_open(priv->mc_io, 0, priv->dpni_id, &priv->mc_token);
+	if (err) {
+		dev_err(dev, "dpni_open() failed\n");
+		goto err_open;
+	}
+
+	ls_dev->mc_io = priv->mc_io;
+	ls_dev->mc_handle = priv->mc_token;
+
+	dma_mem =  kzalloc(DPAA2_EXT_CFG_SIZE, GFP_DMA | GFP_KERNEL);
+	if (!dma_mem)
+		goto err_alloc;
+
+	priv->dpni_attrs.ext_cfg_iova = dma_map_single(dev, dma_mem,
+						       DPAA2_EXT_CFG_SIZE,
+						       DMA_FROM_DEVICE);
+	if (dma_mapping_error(dev, priv->dpni_attrs.ext_cfg_iova)) {
+		dev_err(dev, "dma mapping for dpni_ext_cfg failed\n");
+		goto err_dma_map;
+	}
+
+	err = dpni_get_attributes(priv->mc_io, 0, priv->mc_token,
+				  &priv->dpni_attrs);
+	if (err) {
+		dev_err(dev, "dpni_get_attributes() failed (err=%d)\n", err);
+		dma_unmap_single(dev, priv->dpni_attrs.ext_cfg_iova,
+				 DPAA2_EXT_CFG_SIZE, DMA_FROM_DEVICE);
+		goto err_get_attr;
+	}
+
+	err = check_obj_version(ls_dev, priv->dpni_attrs.version.major);
+	if (err)
+		goto err_dpni_ver;
+
+	dma_unmap_single(dev, priv->dpni_attrs.ext_cfg_iova,
+			 DPAA2_EXT_CFG_SIZE, DMA_FROM_DEVICE);
+
+	memset(&priv->dpni_ext_cfg, 0, sizeof(priv->dpni_ext_cfg));
+	err = dpni_extract_extended_cfg(&priv->dpni_ext_cfg, dma_mem);
+	if (err) {
+		dev_err(dev, "dpni_extract_extended_cfg() failed\n");
+		goto err_extract;
+	}
+
+	/* Configure our buffers' layout */
+	priv->buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
+				   DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
+				   DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
+				   DPNI_BUF_LAYOUT_OPT_DATA_ALIGN;
+	priv->buf_layout.pass_parser_result = true;
+	priv->buf_layout.pass_frame_status = true;
+	priv->buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE;
+	/* HW erratum mandates data alignment in multiples of 256 */
+	priv->buf_layout.data_align = DPAA2_ETH_RX_BUF_ALIGN;
+	/* ...rx, ... */
+	err = dpni_set_rx_buffer_layout(priv->mc_io, 0, priv->mc_token,
+					&priv->buf_layout);
+	if (err) {
+		dev_err(dev, "dpni_set_rx_buffer_layout() failed");
+		goto err_buf_layout;
+	}
+	/* ... tx, ... */
+	/* remove Rx-only options */
+	priv->buf_layout.options &= ~(DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
+				      DPNI_BUF_LAYOUT_OPT_PARSER_RESULT);
+	err = dpni_set_tx_buffer_layout(priv->mc_io, 0, priv->mc_token,
+					&priv->buf_layout);
+	if (err) {
+		dev_err(dev, "dpni_set_tx_buffer_layout() failed");
+		goto err_buf_layout;
+	}
+	/* ... tx-confirm. */
+	priv->buf_layout.options &= ~DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
+	priv->buf_layout.options |= DPNI_BUF_LAYOUT_OPT_TIMESTAMP;
+	priv->buf_layout.pass_timestamp = 1;
+	err = dpni_set_tx_conf_buffer_layout(priv->mc_io, 0, priv->mc_token,
+					     &priv->buf_layout);
+	if (err) {
+		dev_err(dev, "dpni_set_tx_conf_buffer_layout() failed");
+		goto err_buf_layout;
+	}
+	/* Now that we've set our tx buffer layout, retrieve the minimum
+	 * required tx data offset.
+	 */
+	err = dpni_get_tx_data_offset(priv->mc_io, 0, priv->mc_token,
+				      &priv->tx_data_offset);
+	if (err) {
+		dev_err(dev, "dpni_get_tx_data_offset() failed\n");
+		goto err_data_offset;
+	}
+
+	/* Warn in case TX data offset is not multiple of 64 bytes. */
+	WARN_ON(priv->tx_data_offset % 64);
+
+	/* Accommodate SWA space. */
+	priv->tx_data_offset += DPAA2_ETH_SWA_SIZE;
+
+	/* allocate classification rule space */
+	priv->cls_rule = kzalloc(sizeof(*priv->cls_rule) *
+				 DPAA2_CLASSIFIER_ENTRY_COUNT, GFP_KERNEL);
+	if (!priv->cls_rule)
+		goto err_cls_rule;
+
+	kfree(dma_mem);
+
+	return 0;
+
+err_cls_rule:
+err_data_offset:
+err_buf_layout:
+err_extract:
+err_dpni_ver:
+err_get_attr:
+err_dma_map:
+	kfree(dma_mem);
+err_alloc:
+	dpni_close(priv->mc_io, 0, priv->mc_token);
+err_open:
+	return err;
+}
+
+static void dpaa2_dpni_free(struct dpaa2_eth_priv *priv)
+{
+	int err;
+
+	err = dpni_reset(priv->mc_io, 0, priv->mc_token);
+	if (err)
+		netdev_warn(priv->net_dev, "dpni_reset() failed (err %d)\n",
+			    err);
+
+	dpni_close(priv->mc_io, 0, priv->mc_token);
+}
+
+static int dpaa2_rx_flow_setup(struct dpaa2_eth_priv *priv,
+			       struct dpaa2_eth_fq *fq)
+{
+	struct device *dev = priv->net_dev->dev.parent;
+	struct dpni_queue_attr rx_queue_attr;
+	struct dpni_queue_cfg queue_cfg;
+	int err;
+
+	memset(&queue_cfg, 0, sizeof(queue_cfg));
+	queue_cfg.options = DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST |
+			    DPNI_QUEUE_OPT_TAILDROP_THRESHOLD;
+	queue_cfg.dest_cfg.dest_type = DPNI_DEST_DPCON;
+	queue_cfg.dest_cfg.priority = 1;
+	queue_cfg.user_ctx = (u64)fq;
+	queue_cfg.dest_cfg.dest_id = fq->channel->dpcon_id;
+	queue_cfg.tail_drop_threshold = DPAA2_ETH_TAILDROP_THRESH;
+	err = dpni_set_rx_flow(priv->mc_io, 0, priv->mc_token, 0, fq->flowid,
+			       &queue_cfg);
+	if (err) {
+		dev_err(dev, "dpni_set_rx_flow() failed\n");
+		return err;
+	}
+
+	/* Get the actual FQID that was assigned by MC */
+	err = dpni_get_rx_flow(priv->mc_io, 0, priv->mc_token, 0, fq->flowid,
+			       &rx_queue_attr);
+	if (err) {
+		dev_err(dev, "dpni_get_rx_flow() failed\n");
+		return err;
+	}
+	fq->fqid = rx_queue_attr.fqid;
+
+	return 0;
+}
+
+static int dpaa2_tx_flow_setup(struct dpaa2_eth_priv *priv,
+			       struct dpaa2_eth_fq *fq)
+{
+	struct device *dev = priv->net_dev->dev.parent;
+	struct dpni_tx_flow_cfg tx_flow_cfg;
+	struct dpni_tx_conf_cfg tx_conf_cfg;
+	struct dpni_tx_conf_attr tx_conf_attr;
+	int err;
+
+	memset(&tx_flow_cfg, 0, sizeof(tx_flow_cfg));
+	tx_flow_cfg.options = DPNI_TX_FLOW_OPT_TX_CONF_ERROR;
+	tx_flow_cfg.use_common_tx_conf_queue = 0;
+	err = dpni_set_tx_flow(priv->mc_io, 0, priv->mc_token,
+			       &fq->flowid, &tx_flow_cfg);
+	if (err) {
+		dev_err(dev, "dpni_set_tx_flow() failed\n");
+		return err;
+	}
+
+	tx_conf_cfg.errors_only = 0;
+	tx_conf_cfg.queue_cfg.options = DPNI_QUEUE_OPT_USER_CTX |
+					DPNI_QUEUE_OPT_DEST;
+	tx_conf_cfg.queue_cfg.user_ctx = (u64)fq;
+	tx_conf_cfg.queue_cfg.dest_cfg.dest_type = DPNI_DEST_DPCON;
+	tx_conf_cfg.queue_cfg.dest_cfg.dest_id = fq->channel->dpcon_id;
+	tx_conf_cfg.queue_cfg.dest_cfg.priority = 0;
+
+	err = dpni_set_tx_conf(priv->mc_io, 0, priv->mc_token, fq->flowid,
+			       &tx_conf_cfg);
+	if (err) {
+		dev_err(dev, "dpni_set_tx_conf() failed\n");
+		return err;
+	}
+
+	err = dpni_get_tx_conf(priv->mc_io, 0, priv->mc_token, fq->flowid,
+			       &tx_conf_attr);
+	if (err) {
+		dev_err(dev, "dpni_get_tx_conf() failed\n");
+		return err;
+	}
+
+	fq->fqid = tx_conf_attr.queue_attr.fqid;
+
+	return 0;
+}
+
+#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
+static int dpaa2_rx_err_setup(struct dpaa2_eth_priv *priv,
+			      struct dpaa2_eth_fq *fq)
+{
+	struct dpni_queue_attr queue_attr;
+	struct dpni_queue_cfg queue_cfg;
+	int err;
+
+	/* Configure the Rx error queue to generate CDANs,
+	 * just like the Rx queues */
+	queue_cfg.options = DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST;
+	queue_cfg.dest_cfg.dest_type = DPNI_DEST_DPCON;
+	queue_cfg.dest_cfg.priority = 1;
+	queue_cfg.user_ctx = (u64)fq;
+	queue_cfg.dest_cfg.dest_id = fq->channel->dpcon_id;
+	err = dpni_set_rx_err_queue(priv->mc_io, 0, priv->mc_token, &queue_cfg);
+	if (err) {
+		netdev_err(priv->net_dev, "dpni_set_rx_err_queue() failed\n");
+		return err;
+	}
+
+	/* Get the FQID */
+	err = dpni_get_rx_err_queue(priv->mc_io, 0, priv->mc_token, &queue_attr);
+	if (err) {
+		netdev_err(priv->net_dev, "dpni_get_rx_err_queue() failed\n");
+		return err;
+	}
+	fq->fqid = queue_attr.fqid;
+
+	return 0;
+}
+#endif
+
+static int dpaa2_dpni_bind(struct dpaa2_eth_priv *priv)
+{
+	struct net_device *net_dev = priv->net_dev;
+	struct device *dev = net_dev->dev.parent;
+	struct dpni_pools_cfg pools_params;
+	struct dpni_error_cfg err_cfg;
+	int err = 0;
+	int i;
+
+	pools_params.num_dpbp = 1;
+	pools_params.pools[0].dpbp_id = priv->dpbp_dev->obj_desc.id;
+	pools_params.pools[0].backup_pool = 0;
+	pools_params.pools[0].buffer_size = DPAA2_ETH_RX_BUFFER_SIZE;
+	err = dpni_set_pools(priv->mc_io, 0, priv->mc_token, &pools_params);
+	if (err) {
+		dev_err(dev, "dpni_set_pools() failed\n");
+		return err;
+	}
+
+	dpaa2_cls_check(net_dev);
+
+	/* have the interface implicitly distribute traffic based on supported
+	 * header fields
+	 */
+	if (dpaa2_eth_hash_enabled(priv)) {
+		err = dpaa2_set_hash(net_dev, DPAA2_RXH_SUPPORTED);
+		if (err)
+			return err;
+	}
+
+	/* Configure handling of error frames */
+	err_cfg.errors = DPAA2_ETH_RX_ERR_MASK;
+	err_cfg.set_frame_annotation = 1;
+#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
+	err_cfg.error_action = DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE;
+#else
+	err_cfg.error_action = DPNI_ERROR_ACTION_DISCARD;
+#endif
+	err = dpni_set_errors_behavior(priv->mc_io, 0, priv->mc_token,
+				       &err_cfg);
+	if (err) {
+		dev_err(dev, "dpni_set_errors_behavior failed\n");
+		return err;
+	}
+
+	/* Configure Rx and Tx conf queues to generate CDANs */
+	for (i = 0; i < priv->num_fqs; i++) {
+		switch (priv->fq[i].type) {
+		case DPAA2_RX_FQ:
+			err = dpaa2_rx_flow_setup(priv, &priv->fq[i]);
+			break;
+		case DPAA2_TX_CONF_FQ:
+			err = dpaa2_tx_flow_setup(priv, &priv->fq[i]);
+			break;
+#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
+		case DPAA2_RX_ERR_FQ:
+			err = dpaa2_rx_err_setup(priv, &priv->fq[i]);
+			break;
+#endif
+		default:
+			dev_err(dev, "Invalid FQ type %d\n", priv->fq[i].type);
+			return -EINVAL;
+		}
+		if (err)
+			return err;
+	}
+
+	err = dpni_get_qdid(priv->mc_io, 0, priv->mc_token, &priv->tx_qdid);
+	if (err) {
+		dev_err(dev, "dpni_get_qdid() failed\n");
+		return err;
+	}
+
+	return 0;
+}
+
+static int dpaa2_eth_alloc_rings(struct dpaa2_eth_priv *priv)
+{
+	struct net_device *net_dev = priv->net_dev;
+	struct device *dev = net_dev->dev.parent;
+	int i;
+
+	for (i = 0; i < priv->num_channels; i++) {
+		priv->channel[i]->store =
+			dpaa2_io_store_create(DPAA2_ETH_STORE_SIZE, dev);
+		if (!priv->channel[i]->store) {
+			netdev_err(net_dev, "dpaa2_io_store_create() failed\n");
+			goto err_ring;
+		}
+	}
+
+	return 0;
+
+err_ring:
+	for (i = 0; i < priv->num_channels; i++) {
+		if (!priv->channel[i]->store)
+			break;
+		dpaa2_io_store_destroy(priv->channel[i]->store);
+	}
+
+	return -ENOMEM;
+}
+
+static void dpaa2_eth_free_rings(struct dpaa2_eth_priv *priv)
+{
+	int i;
+
+	for (i = 0; i < priv->num_channels; i++)
+		dpaa2_io_store_destroy(priv->channel[i]->store);
+}
+
+static int dpaa2_eth_netdev_init(struct net_device *net_dev)
+{
+	int err;
+	struct device *dev = net_dev->dev.parent;
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	u8 mac_addr[ETH_ALEN];
+	u8 bcast_addr[ETH_ALEN];
+
+	net_dev->netdev_ops = &dpaa2_eth_ops;
+
+	/* If the DPL contains all-0 mac_addr, set a random hardware address */
+	err = dpni_get_primary_mac_addr(priv->mc_io, 0, priv->mc_token,
+					mac_addr);
+	if (err) {
+		dev_err(dev, "dpni_get_primary_mac_addr() failed (%d)", err);
+		return err;
+	}
+	if (is_zero_ether_addr(mac_addr)) {
+		/* Fills in net_dev->dev_addr, as required by
+		 * register_netdevice()
+		 */
+		eth_hw_addr_random(net_dev);
+		/* Make the user aware, without cluttering the boot log */
+		pr_info_once(KBUILD_MODNAME " device(s) have all-zero hwaddr, replaced with random");
+		err = dpni_set_primary_mac_addr(priv->mc_io, 0, priv->mc_token,
+						net_dev->dev_addr);
+		if (err) {
+			dev_err(dev, "dpni_set_primary_mac_addr(): %d\n", err);
+			return err;
+		}
+		/* Override NET_ADDR_RANDOM set by eth_hw_addr_random(); for all
+		 * practical purposes, this will be our "permanent" mac address,
+		 * at least until the next reboot. This move will also permit
+		 * register_netdevice() to properly fill up net_dev->perm_addr.
+		 */
+		net_dev->addr_assign_type = NET_ADDR_PERM;
+	} else {
+		/* NET_ADDR_PERM is default, all we have to do is
+		 * fill in the device addr.
+		 */
+		memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len);
+	}
+
+	/* Explicitly add the broadcast address to the MAC filtering table;
+	 * the MC won't do that for us.
+	 */
+	eth_broadcast_addr(bcast_addr);
+	err = dpni_add_mac_addr(priv->mc_io, 0, priv->mc_token, bcast_addr);
+	if (err) {
+		dev_warn(dev, "dpni_add_mac_addr() failed (%d)\n", err);
+		/* Won't return an error; at least, we'd have egress traffic */
+	}
+
+	/* Reserve enough space to align buffer as per hardware requirement;
+	 * NOTE: priv->tx_data_offset MUST be initialized at this point.
+	 */
+	net_dev->needed_headroom = DPAA2_ETH_NEEDED_HEADROOM(priv);
+
+	/* Our .ndo_init will be called herein */
+	err = register_netdev(net_dev);
+	if (err < 0) {
+		dev_err(dev, "register_netdev() = %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_FSL_DPAA2_ETH_LINK_POLL
+static int dpaa2_poll_link_state(void *arg)
+{
+	struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)arg;
+	int err;
+
+	while (!kthread_should_stop()) {
+		err = dpaa2_link_state_update(priv);
+		if (unlikely(err))
+			return err;
+
+		msleep(DPAA2_ETH_LINK_STATE_REFRESH);
+	}
+
+	return 0;
+}
+#else
+static irqreturn_t dpni_irq0_handler(int irq_num, void *arg)
+{
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t dpni_irq0_handler_thread(int irq_num, void *arg)
+{
+	u8 irq_index = DPNI_IRQ_INDEX;
+	u32 status, clear = 0;
+	struct device *dev = (struct device *)arg;
+	struct fsl_mc_device *dpni_dev = to_fsl_mc_device(dev);
+	struct net_device *net_dev = dev_get_drvdata(dev);
+	int err;
+
+	netdev_dbg(net_dev, "IRQ %d received\n", irq_num);
+	err = dpni_get_irq_status(dpni_dev->mc_io, 0, dpni_dev->mc_handle,
+				  irq_index, &status);
+	if (unlikely(err)) {
+		netdev_err(net_dev, "Can't get irq status (err %d)", err);
+		clear = 0xffffffff;
+		goto out;
+	}
+
+	if (status & DPNI_IRQ_EVENT_LINK_CHANGED) {
+		clear |= DPNI_IRQ_EVENT_LINK_CHANGED;
+		dpaa2_link_state_update(netdev_priv(net_dev));
+	}
+
+out:
+	dpni_clear_irq_status(dpni_dev->mc_io, 0, dpni_dev->mc_handle,
+			      irq_index, clear);
+	return IRQ_HANDLED;
+}
+
+static int dpaa2_eth_setup_irqs(struct fsl_mc_device *ls_dev)
+{
+	int err = 0;
+	struct fsl_mc_device_irq *irq;
+	int irq_count = ls_dev->obj_desc.irq_count;
+	u8 irq_index = DPNI_IRQ_INDEX;
+	u32 mask = DPNI_IRQ_EVENT_LINK_CHANGED;
+
+	/* The only interrupt supported now is the link state notification. */
+	if (WARN_ON(irq_count != 1))
+		return -EINVAL;
+
+	irq = ls_dev->irqs[0];
+	err = devm_request_threaded_irq(&ls_dev->dev, irq->msi_desc->irq,
+					dpni_irq0_handler,
+					dpni_irq0_handler_thread,
+					IRQF_NO_SUSPEND | IRQF_ONESHOT,
+					dev_name(&ls_dev->dev), &ls_dev->dev);
+	if (err < 0) {
+		dev_err(&ls_dev->dev, "devm_request_threaded_irq(): %d", err);
+		return err;
+	}
+
+	err = dpni_set_irq_mask(ls_dev->mc_io, 0, ls_dev->mc_handle,
+				irq_index, mask);
+	if (err < 0) {
+		dev_err(&ls_dev->dev, "dpni_set_irq_mask(): %d", err);
+		return err;
+	}
+
+	err = dpni_set_irq_enable(ls_dev->mc_io, 0, ls_dev->mc_handle,
+				  irq_index, 1);
+	if (err < 0) {
+		dev_err(&ls_dev->dev, "dpni_set_irq_enable(): %d", err);
+		return err;
+	}
+
+	return 0;
+}
+#endif
+
+static void dpaa2_eth_napi_add(struct dpaa2_eth_priv *priv)
+{
+	int i;
+	struct dpaa2_eth_channel *ch;
+
+	for (i = 0; i < priv->num_channels; i++) {
+		ch = priv->channel[i];
+		/* NAPI weight *MUST* be a multiple of DPAA2_ETH_STORE_SIZE */
+		netif_napi_add(priv->net_dev, &ch->napi, dpaa2_eth_poll,
+			       NAPI_POLL_WEIGHT);
+	}
+}
+
+static void dpaa2_eth_napi_del(struct dpaa2_eth_priv *priv)
+{
+	int i;
+	struct dpaa2_eth_channel *ch;
+
+	for (i = 0; i < priv->num_channels; i++) {
+		ch = priv->channel[i];
+		netif_napi_del(&ch->napi);
+	}
+}
+
+/* SysFS support */
+
+static ssize_t dpaa2_eth_show_tx_shaping(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(to_net_dev(dev));
+	/* No MC API for getting the shaping config. We're stateful. */
+	struct dpni_tx_shaping_cfg *scfg = &priv->shaping_cfg;
+
+	return sprintf(buf, "%u %hu\n", scfg->rate_limit, scfg->max_burst_size);
+}
+
+static ssize_t dpaa2_eth_write_tx_shaping(struct device *dev,
+					  struct device_attribute *attr,
+					  const char *buf,
+					  size_t count)
+{
+	int err, items;
+	struct dpaa2_eth_priv *priv = netdev_priv(to_net_dev(dev));
+	struct dpni_tx_shaping_cfg scfg;
+
+	items = sscanf(buf, "%u %hu", &scfg.rate_limit, &scfg.max_burst_size);
+	if (items != 2) {
+		pr_err("Expected format: \"rate_limit(Mbps) max_burst_size(bytes)\"\n");
+		return -EINVAL;
+	}
+	/* Size restriction as per MC API documentation */
+	if (scfg.max_burst_size > 64000) {
+		pr_err("max_burst_size must be <= 64000, thanks.\n");
+		return -EINVAL;
+	}
+
+	err = dpni_set_tx_shaping(priv->mc_io, 0, priv->mc_token, &scfg);
+	if (err) {
+		dev_err(dev, "dpni_set_tx_shaping() failed\n");
+		return -EPERM;
+	}
+	/* If successful, save the current configuration for future inquiries */
+	priv->shaping_cfg = scfg;
+
+	return count;
+}
+
+static ssize_t dpaa2_eth_show_txconf_cpumask(struct device *dev,
+					     struct device_attribute *attr,
+					     char *buf)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(to_net_dev(dev));
+
+	return cpumap_print_to_pagebuf(1, buf, &priv->txconf_cpumask);
+}
+
+static ssize_t dpaa2_eth_write_txconf_cpumask(struct device *dev,
+					      struct device_attribute *attr,
+					      const char *buf,
+					      size_t count)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(to_net_dev(dev));
+	struct dpaa2_eth_fq *fq;
+	bool running = netif_running(priv->net_dev);
+	int i, err;
+
+	err = cpulist_parse(buf, &priv->txconf_cpumask);
+	if (err)
+		return err;
+
+	/* Only accept CPUs that have an affine DPIO */
+	if (!cpumask_subset(&priv->txconf_cpumask, &priv->dpio_cpumask)) {
+		netdev_info(priv->net_dev,
+			    "cpumask must be a subset of 0x%lx\n",
+			    *cpumask_bits(&priv->dpio_cpumask));
+		cpumask_and(&priv->txconf_cpumask, &priv->dpio_cpumask,
+			    &priv->txconf_cpumask);
+	}
+
+	/* Rewiring the TxConf FQs requires interface shutdown.
+	 */
+	if (running) {
+		err = dpaa2_eth_stop(priv->net_dev);
+		if (err)
+			return -ENODEV;
+	}
+
+	/* Set the new TxConf FQ affinities */
+	dpaa2_set_fq_affinity(priv);
+
+#ifdef CONFIG_FSL_DPAA2_ETH_LINK_POLL
+	/* dpaa2_eth_open() below will *stop* the Tx queues until an explicit
+	 * link up notification is received. Give the polling thread enough time
+	 * to detect the link state change, or else we'll end up with the
+	 * transmission side forever shut down.
+	 */
+	msleep(2 * DPAA2_ETH_LINK_STATE_REFRESH);
+#endif
+
+	for (i = 0; i < priv->num_fqs; i++) {
+		fq = &priv->fq[i];
+		if (fq->type != DPAA2_TX_CONF_FQ)
+			continue;
+		dpaa2_tx_flow_setup(priv, fq);
+	}
+
+	if (running) {
+		err = dpaa2_eth_open(priv->net_dev);
+		if (err)
+			return -ENODEV;
+	}
+
+	return count;
+}
+
+static struct device_attribute dpaa2_eth_attrs[] = {
+	__ATTR(txconf_cpumask,
+	       S_IRUSR | S_IWUSR,
+	       dpaa2_eth_show_txconf_cpumask,
+	       dpaa2_eth_write_txconf_cpumask),
+
+	__ATTR(tx_shaping,
+	       S_IRUSR | S_IWUSR,
+	       dpaa2_eth_show_tx_shaping,
+	       dpaa2_eth_write_tx_shaping),
+};
+
+void dpaa2_eth_sysfs_init(struct device *dev)
+{
+	int i, err;
+
+	for (i = 0; i < ARRAY_SIZE(dpaa2_eth_attrs); i++) {
+		err = device_create_file(dev, &dpaa2_eth_attrs[i]);
+		if (err) {
+			dev_err(dev, "ERROR creating sysfs file\n");
+			goto undo;
+		}
+	}
+	return;
+
+undo:
+	while (i > 0)
+		device_remove_file(dev, &dpaa2_eth_attrs[--i]);
+}
+
+void dpaa2_eth_sysfs_remove(struct device *dev)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(dpaa2_eth_attrs); i++)
+		device_remove_file(dev, &dpaa2_eth_attrs[i]);
+}
+
+static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
+{
+	struct device			*dev;
+	struct net_device		*net_dev = NULL;
+	struct dpaa2_eth_priv		*priv = NULL;
+	int				err = 0;
+
+	dev = &dpni_dev->dev;
+
+	/* Net device */
+	net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA2_ETH_MAX_TX_QUEUES);
+	if (!net_dev) {
+		dev_err(dev, "alloc_etherdev_mq() failed\n");
+		return -ENOMEM;
+	}
+
+	SET_NETDEV_DEV(net_dev, dev);
+	dev_set_drvdata(dev, net_dev);
+
+	priv = netdev_priv(net_dev);
+	priv->net_dev = net_dev;
+	priv->msg_enable = netif_msg_init(debug, -1);
+
+	/* Obtain a MC portal */
+	err = fsl_mc_portal_allocate(dpni_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
+				     &priv->mc_io);
+	if (err) {
+		dev_err(dev, "MC portal allocation failed\n");
+		goto err_portal_alloc;
+	}
+
+#ifndef CONFIG_FSL_DPAA2_ETH_LINK_POLL
+	err = fsl_mc_allocate_irqs(dpni_dev);
+	if (err) {
+		dev_err(dev, "MC irqs allocation failed\n");
+		goto err_irqs_alloc;
+	}
+#endif
+
+	/* DPNI initialization */
+	err = dpaa2_dpni_setup(dpni_dev);
+	if (err < 0)
+		goto err_dpni_setup;
+
+	/* DPIO */
+	err = dpaa2_dpio_setup(priv);
+	if (err)
+		goto err_dpio_setup;
+
+	/* FQs */
+	dpaa2_eth_setup_fqs(priv);
+	dpaa2_set_fq_affinity(priv);
+
+	/* DPBP */
+	err = dpaa2_dpbp_setup(priv);
+	if (err)
+		goto err_dpbp_setup;
+
+	/* DPNI binding to DPIO and DPBPs */
+	err = dpaa2_dpni_bind(priv);
+	if (err)
+		goto err_bind;
+
+	dpaa2_eth_napi_add(priv);
+
+	/* Percpu statistics */
+	priv->percpu_stats = alloc_percpu(*priv->percpu_stats);
+	if (!priv->percpu_stats) {
+		dev_err(dev, "alloc_percpu(percpu_stats) failed\n");
+		err = -ENOMEM;
+		goto err_alloc_percpu_stats;
+	}
+	priv->percpu_extras = alloc_percpu(*priv->percpu_extras);
+	if (!priv->percpu_extras) {
+		dev_err(dev, "alloc_percpu(percpu_extras) failed\n");
+		err = -ENOMEM;
+		goto err_alloc_percpu_extras;
+	}
+
+	snprintf(net_dev->name, IFNAMSIZ, "ni%d", dpni_dev->obj_desc.id);
+	if (!dev_valid_name(net_dev->name)) {
+		dev_warn(&net_dev->dev,
+			 "netdevice name \"%s\" cannot be used, reverting to default..\n",
+			 net_dev->name);
+		dev_alloc_name(net_dev, "eth%d");
+		dev_warn(&net_dev->dev, "using name \"%s\"\n", net_dev->name);
+	}
+
+	err = dpaa2_eth_netdev_init(net_dev);
+	if (err)
+		goto err_netdev_init;
+
+	/* Configure checksum offload based on current interface flags */
+	err = dpaa2_eth_set_rx_csum(priv,
+				    !!(net_dev->features & NETIF_F_RXCSUM));
+	if (err)
+		goto err_csum;
+
+	err = dpaa2_eth_set_tx_csum(priv,
+				    !!(net_dev->features &
+				    (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)));
+	if (err)
+		goto err_csum;
+
+	err = dpaa2_eth_alloc_rings(priv);
+	if (err)
+		goto err_alloc_rings;
+
+	net_dev->ethtool_ops = &dpaa2_ethtool_ops;
+
+#ifdef CONFIG_FSL_DPAA2_ETH_LINK_POLL
+	priv->poll_thread = kthread_run(dpaa2_poll_link_state, priv,
+					"%s_poll_link", net_dev->name);
+#else
+	err = dpaa2_eth_setup_irqs(dpni_dev);
+	if (err) {
+		netdev_err(net_dev, "ERROR %d setting up interrupts", err);
+		goto err_setup_irqs;
+	}
+#endif
+
+	dpaa2_eth_sysfs_init(&net_dev->dev);
+	dpaa2_dbg_add(priv);
+
+	dev_info(dev, "Probed interface %s\n", net_dev->name);
+	return 0;
+
+#ifndef CONFIG_FSL_DPAA2_ETH_LINK_POLL
+err_setup_irqs:
+#endif
+	dpaa2_eth_free_rings(priv);
+err_alloc_rings:
+err_csum:
+	unregister_netdev(net_dev);
+err_netdev_init:
+	free_percpu(priv->percpu_extras);
+err_alloc_percpu_extras:
+	free_percpu(priv->percpu_stats);
+err_alloc_percpu_stats:
+	dpaa2_eth_napi_del(priv);
+err_bind:
+	dpaa2_dpbp_free(priv);
+err_dpbp_setup:
+	dpaa2_dpio_free(priv);
+err_dpio_setup:
+	kfree(priv->cls_rule);
+	dpni_close(priv->mc_io, 0, priv->mc_token);
+err_dpni_setup:
+#ifndef CONFIG_FSL_DPAA2_ETH_LINK_POLL
+	fsl_mc_free_irqs(dpni_dev);
+err_irqs_alloc:
+#endif
+	fsl_mc_portal_free(priv->mc_io);
+err_portal_alloc:
+	dev_set_drvdata(dev, NULL);
+	free_netdev(net_dev);
+
+	return err;
+}
+
+static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
+{
+	struct device		*dev;
+	struct net_device	*net_dev;
+	struct dpaa2_eth_priv *priv;
+
+	dev = &ls_dev->dev;
+	net_dev = dev_get_drvdata(dev);
+	priv = netdev_priv(net_dev);
+
+	dpaa2_dbg_remove(priv);
+	dpaa2_eth_sysfs_remove(&net_dev->dev);
+
+	unregister_netdev(net_dev);
+	dev_info(net_dev->dev.parent, "Removed interface %s\n", net_dev->name);
+
+	dpaa2_dpio_free(priv);
+	dpaa2_eth_free_rings(priv);
+	dpaa2_eth_napi_del(priv);
+	dpaa2_dpbp_free(priv);
+	dpaa2_dpni_free(priv);
+
+	fsl_mc_portal_free(priv->mc_io);
+
+	free_percpu(priv->percpu_stats);
+	free_percpu(priv->percpu_extras);
+
+#ifdef CONFIG_FSL_DPAA2_ETH_LINK_POLL
+	kthread_stop(priv->poll_thread);
+#else
+	fsl_mc_free_irqs(ls_dev);
+#endif
+
+	kfree(priv->cls_rule);
+
+	dev_set_drvdata(dev, NULL);
+	free_netdev(net_dev);
+
+	return 0;
+}
+
+static const struct fsl_mc_device_match_id dpaa2_eth_match_id_table[] = {
+	{
+		.vendor = FSL_MC_VENDOR_FREESCALE,
+		.obj_type = "dpni",
+		.ver_major = DPNI_VER_MAJOR,
+		.ver_minor = DPNI_VER_MINOR
+	},
+	{ .vendor = 0x0 }
+};
+
+static struct fsl_mc_driver dpaa2_eth_driver = {
+	.driver = {
+		.name		= KBUILD_MODNAME,
+		.owner		= THIS_MODULE,
+	},
+	.probe		= dpaa2_eth_probe,
+	.remove		= dpaa2_eth_remove,
+	.match_id_table = dpaa2_eth_match_id_table
+};
+
+static int __init dpaa2_eth_driver_init(void)
+{
+	int err;
+
+	dpaa2_eth_dbg_init();
+
+	err = fsl_mc_driver_register(&dpaa2_eth_driver);
+	if (err) {
+		dpaa2_eth_dbg_exit();
+		return err;
+	}
+
+	return 0;
+}
+
+static void __exit dpaa2_eth_driver_exit(void)
+{
+	fsl_mc_driver_unregister(&dpaa2_eth_driver);
+	dpaa2_eth_dbg_exit();
+}
+
+module_init(dpaa2_eth_driver_init);
+module_exit(dpaa2_eth_driver_exit);
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
@@ -0,0 +1,366 @@
+/* Copyright 2014-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __DPAA2_ETH_H
+#define __DPAA2_ETH_H
+
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include "../../fsl-mc/include/fsl_dpaa2_io.h"
+#include "../../fsl-mc/include/fsl_dpaa2_fd.h"
+#include "../../fsl-mc/include/dpbp.h"
+#include "../../fsl-mc/include/dpbp-cmd.h"
+#include "../../fsl-mc/include/dpcon.h"
+#include "../../fsl-mc/include/dpcon-cmd.h"
+#include "../../fsl-mc/include/dpmng.h"
+#include "dpni.h"
+#include "dpni-cmd.h"
+
+#include "dpaa2-eth-trace.h"
+#include "dpaa2-eth-debugfs.h"
+
+#define DPAA2_ETH_STORE_SIZE		16
+
+/* Maximum receive frame size is 64K */
+#define DPAA2_ETH_MAX_SG_ENTRIES	((64 * 1024) / DPAA2_ETH_RX_BUFFER_SIZE)
+
+/* Maximum acceptable MTU value. It is in direct relation with the MC-enforced
+ * Max Frame Length (currently 10k).
+ */
+#define DPAA2_ETH_MFL			(10 * 1024)
+#define DPAA2_ETH_MAX_MTU		(DPAA2_ETH_MFL - VLAN_ETH_HLEN)
+/* Convert L3 MTU to L2 MFL */
+#define DPAA2_ETH_L2_MAX_FRM(mtu)	(mtu + VLAN_ETH_HLEN)
+
+/* Set the taildrop threshold (in bytes) to allow the enqueue of several jumbo
+ * frames in the Rx queues (length of the current frame is not
+ * taken into account when making the taildrop decision)
+ */
+#define DPAA2_ETH_TAILDROP_THRESH	(64 * 1024)
+
+/* Buffer quota per queue. Must be large enough such that for minimum sized
+ * frames taildrop kicks in before the bpool gets depleted, so we compute
+ * how many 64B frames fit inside the taildrop threshold and add a margin
+ * to accommodate the buffer refill delay.
+ */
+#define DPAA2_ETH_MAX_FRAMES_PER_QUEUE	(DPAA2_ETH_TAILDROP_THRESH / 64)
+#define DPAA2_ETH_NUM_BUFS		(DPAA2_ETH_MAX_FRAMES_PER_QUEUE + 256)
+#define DPAA2_ETH_REFILL_THRESH		DPAA2_ETH_MAX_FRAMES_PER_QUEUE
+
+/* Hardware requires alignment for ingress/egress buffer addresses
+ * and ingress buffer lengths.
+ */
+#define DPAA2_ETH_RX_BUFFER_SIZE	2048
+#define DPAA2_ETH_TX_BUF_ALIGN		64
+#define DPAA2_ETH_RX_BUF_ALIGN		256
+#define DPAA2_ETH_NEEDED_HEADROOM(p_priv) \
+	((p_priv)->tx_data_offset + DPAA2_ETH_TX_BUF_ALIGN)
+
+#define DPAA2_ETH_BUF_RAW_SIZE \
+	(DPAA2_ETH_RX_BUFFER_SIZE + \
+	SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + \
+	DPAA2_ETH_RX_BUF_ALIGN)
+
+/* PTP nominal frequency 1MHz */
+#define DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS 1000
+
+/* We are accommodating a skb backpointer and some S/G info
+ * in the frame's software annotation. The hardware
+ * options are either 0 or 64, so we choose the latter.
+ */
+#define DPAA2_ETH_SWA_SIZE		64
+
+/* Must keep this struct smaller than DPAA2_ETH_SWA_SIZE */
+struct dpaa2_eth_swa {
+	struct sk_buff *skb;
+	struct scatterlist *scl;
+	int num_sg;
+	int num_dma_bufs;
+};
+
+/* Annotation valid bits in FD FRC */
+#define DPAA2_FD_FRC_FASV		0x8000
+#define DPAA2_FD_FRC_FAEADV		0x4000
+#define DPAA2_FD_FRC_FAPRV		0x2000
+#define DPAA2_FD_FRC_FAIADV		0x1000
+#define DPAA2_FD_FRC_FASWOV		0x0800
+#define DPAA2_FD_FRC_FAICFDV		0x0400
+
+/* Annotation bits in FD CTRL */
+#define DPAA2_FD_CTRL_ASAL		0x00020000	/* ASAL = 128 */
+#define DPAA2_FD_CTRL_PTA		0x00800000
+#define DPAA2_FD_CTRL_PTV1		0x00400000
+
+/* Frame annotation status */
+struct dpaa2_fas {
+	u8 reserved;
+	u8 ppid;
+	__le16 ifpid;
+	__le32 status;
+} __packed;
+
+/* Debug frame, otherwise supposed to be discarded */
+#define DPAA2_ETH_FAS_DISC		0x80000000
+/* MACSEC frame */
+#define DPAA2_ETH_FAS_MS		0x40000000
+#define DPAA2_ETH_FAS_PTP		0x08000000
+/* Ethernet multicast frame */
+#define DPAA2_ETH_FAS_MC		0x04000000
+/* Ethernet broadcast frame */
+#define DPAA2_ETH_FAS_BC		0x02000000
+#define DPAA2_ETH_FAS_KSE		0x00040000
+#define DPAA2_ETH_FAS_EOFHE		0x00020000
+#define DPAA2_ETH_FAS_MNLE		0x00010000
+#define DPAA2_ETH_FAS_TIDE		0x00008000
+#define DPAA2_ETH_FAS_PIEE		0x00004000
+/* Frame length error */
+#define DPAA2_ETH_FAS_FLE		0x00002000
+/* Frame physical error; our favourite pastime */
+#define DPAA2_ETH_FAS_FPE		0x00001000
+#define DPAA2_ETH_FAS_PTE		0x00000080
+#define DPAA2_ETH_FAS_ISP		0x00000040
+#define DPAA2_ETH_FAS_PHE		0x00000020
+#define DPAA2_ETH_FAS_BLE		0x00000010
+/* L3 csum validation performed */
+#define DPAA2_ETH_FAS_L3CV		0x00000008
+/* L3 csum error */
+#define DPAA2_ETH_FAS_L3CE		0x00000004
+/* L4 csum validation performed */
+#define DPAA2_ETH_FAS_L4CV		0x00000002
+/* L4 csum error */
+#define DPAA2_ETH_FAS_L4CE		0x00000001
+/* These bits always signal errors */
+#define DPAA2_ETH_RX_ERR_MASK		(DPAA2_ETH_FAS_KSE	| \
+					 DPAA2_ETH_FAS_EOFHE	| \
+					 DPAA2_ETH_FAS_MNLE	| \
+					 DPAA2_ETH_FAS_TIDE	| \
+					 DPAA2_ETH_FAS_PIEE	| \
+					 DPAA2_ETH_FAS_FLE	| \
+					 DPAA2_ETH_FAS_FPE	| \
+					 DPAA2_ETH_FAS_PTE	| \
+					 DPAA2_ETH_FAS_ISP	| \
+					 DPAA2_ETH_FAS_PHE	| \
+					 DPAA2_ETH_FAS_BLE	| \
+					 DPAA2_ETH_FAS_L3CE	| \
+					 DPAA2_ETH_FAS_L4CE)
+/* Unsupported features in the ingress */
+#define DPAA2_ETH_RX_UNSUPP_MASK	DPAA2_ETH_FAS_MS
+/* Tx errors */
+#define DPAA2_ETH_TXCONF_ERR_MASK	(DPAA2_ETH_FAS_KSE	| \
+					 DPAA2_ETH_FAS_EOFHE	| \
+					 DPAA2_ETH_FAS_MNLE	| \
+					 DPAA2_ETH_FAS_TIDE)
+
+/* Time in milliseconds between link state updates */
+#define DPAA2_ETH_LINK_STATE_REFRESH	1000
+
+/* Driver statistics, other than those in struct rtnl_link_stats64.
+ * These are usually collected per-CPU and aggregated by ethtool.
+ */
+struct dpaa2_eth_stats {
+	__u64	tx_conf_frames;
+	__u64	tx_conf_bytes;
+	__u64	tx_sg_frames;
+	__u64	tx_sg_bytes;
+	__u64	rx_sg_frames;
+	__u64	rx_sg_bytes;
+	/* Enqueues retried due to portal busy */
+	__u64	tx_portal_busy;
+};
+
+/* Per-FQ statistics */
+struct dpaa2_eth_fq_stats {
+	/* Number of frames received on this queue */
+	__u64 frames;
+};
+
+/* Per-channel statistics */
+struct dpaa2_eth_ch_stats {
+	/* Volatile dequeues retried due to portal busy */
+	__u64 dequeue_portal_busy;
+	/* Number of CDANs; useful to estimate avg NAPI len */
+	__u64 cdan;
+	/* Number of frames received on queues from this channel */
+	__u64 frames;
+};
+
+/* Maximum number of Rx queues associated with a DPNI */
+#define DPAA2_ETH_MAX_RX_QUEUES		16
+#define DPAA2_ETH_MAX_TX_QUEUES		NR_CPUS
+#define DPAA2_ETH_MAX_RX_ERR_QUEUES	1
+#define DPAA2_ETH_MAX_QUEUES	(DPAA2_ETH_MAX_RX_QUEUES + \
+				DPAA2_ETH_MAX_TX_QUEUES + \
+				DPAA2_ETH_MAX_RX_ERR_QUEUES)
+
+#define DPAA2_ETH_MAX_DPCONS		NR_CPUS
+
+enum dpaa2_eth_fq_type {
+	DPAA2_RX_FQ = 0,
+	DPAA2_TX_CONF_FQ,
+	DPAA2_RX_ERR_FQ
+};
+
+struct dpaa2_eth_priv;
+
+struct dpaa2_eth_fq {
+	u32 fqid;
+	u16 flowid;
+	int target_cpu;
+	struct dpaa2_eth_channel *channel;
+	enum dpaa2_eth_fq_type type;
+
+	void (*consume)(struct dpaa2_eth_priv *,
+			struct dpaa2_eth_channel *,
+			const struct dpaa2_fd *,
+			struct napi_struct *);
+	struct dpaa2_eth_priv *netdev_priv;	/* backpointer */
+	struct dpaa2_eth_fq_stats stats;
+};
+
+struct dpaa2_eth_channel {
+	struct dpaa2_io_notification_ctx nctx;
+	struct fsl_mc_device *dpcon;
+	int dpcon_id;
+	int ch_id;
+	int dpio_id;
+	struct napi_struct napi;
+	struct dpaa2_io_store *store;
+	struct dpaa2_eth_priv *priv;
+	int buf_count;
+	struct dpaa2_eth_ch_stats stats;
+};
+
+struct dpaa2_cls_rule {
+	struct ethtool_rx_flow_spec fs;
+	bool in_use;
+};
+
+struct dpaa2_eth_priv {
+	struct net_device *net_dev;
+
+	u8 num_fqs;
+	/* First queue is tx conf, the rest are rx */
+	struct dpaa2_eth_fq fq[DPAA2_ETH_MAX_QUEUES];
+
+	u8 num_channels;
+	struct dpaa2_eth_channel *channel[DPAA2_ETH_MAX_DPCONS];
+
+	int dpni_id;
+	struct dpni_attr dpni_attrs;
+	struct dpni_extended_cfg dpni_ext_cfg;
+	/* Insofar as the MC is concerned, we're using one layout on all 3 types
+	 * of buffers (Rx, Tx, Tx-Conf).
+	 */
+	struct dpni_buffer_layout buf_layout;
+	u16 tx_data_offset;
+
+	struct fsl_mc_device *dpbp_dev;
+	struct dpbp_attr dpbp_attrs;
+
+	u16 tx_qdid;
+	struct fsl_mc_io *mc_io;
+	/* SysFS-controlled affinity mask for TxConf FQs */
+	struct cpumask txconf_cpumask;
+	/* Cores which have an affine DPIO/DPCON.
+	 * This is the cpu set on which Rx frames are processed;
+	 * Tx confirmation frames are processed on a subset of this,
+	 * depending on user settings.
+	 */
+	struct cpumask dpio_cpumask;
+
+	/* Standard statistics */
+	struct rtnl_link_stats64 __percpu *percpu_stats;
+	/* Extra stats, in addition to the ones known by the kernel */
+	struct dpaa2_eth_stats __percpu *percpu_extras;
+	u32 msg_enable;	/* net_device message level */
+
+	u16 mc_token;
+
+	struct dpni_link_state link_state;
+	struct task_struct *poll_thread;
+
+	/* enabled ethtool hashing bits */
+	u64 rx_hash_fields;
+
+#ifdef CONFIG_FSL_DPAA2_ETH_DEBUGFS
+	struct dpaa2_debugfs dbg;
+#endif
+
+	/* array of classification rules */
+	struct dpaa2_cls_rule *cls_rule;
+
+	struct dpni_tx_shaping_cfg shaping_cfg;
+
+	bool ts_tx_en; /* Tx timestamping enabled */
+	bool ts_rx_en; /* Rx timestamping enabled */
+};
+
+/* default Rx hash options, set during probing */
+#define DPAA2_RXH_SUPPORTED	(RXH_L2DA | RXH_VLAN | RXH_L3_PROTO \
+				| RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 \
+				| RXH_L4_B_2_3)
+
+#define dpaa2_eth_hash_enabled(priv)	\
+	((priv)->dpni_attrs.options & DPNI_OPT_DIST_HASH)
+
+#define dpaa2_eth_fs_enabled(priv)	\
+	((priv)->dpni_attrs.options & DPNI_OPT_DIST_FS)
+
+#define DPAA2_CLASSIFIER_ENTRY_COUNT 16
+
+/* Required by struct dpni_attr::ext_cfg_iova */
+#define DPAA2_EXT_CFG_SIZE	256
+
+extern const struct ethtool_ops dpaa2_ethtool_ops;
+
+int dpaa2_set_hash(struct net_device *net_dev, u64 flags);
+
+static int dpaa2_queue_count(struct dpaa2_eth_priv *priv)
+{
+	if (!dpaa2_eth_hash_enabled(priv))
+		return 1;
+
+	return priv->dpni_ext_cfg.tc_cfg[0].max_dist;
+}
+
+static inline int dpaa2_max_channels(struct dpaa2_eth_priv *priv)
+{
+	/* Ideally, we want a number of channels large enough
+	 * to accommodate both the Rx distribution size
+	 * and the max number of Tx confirmation queues
+	 */
+	return max_t(int, dpaa2_queue_count(priv),
+		     priv->dpni_attrs.max_senders);
+}
+
+void dpaa2_cls_check(struct net_device *);
+
+#endif	/* __DPAA2_H */
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
@@ -0,0 +1,882 @@
+/* Copyright 2014-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *	 notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *	 notice, this list of conditions and the following disclaimer in the
+ *	 documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *	 names of its contributors may be used to endorse or promote products
+ *	 derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "dpni.h"	/* DPNI_LINK_OPT_* */
+#include "dpaa2-eth.h"
+
+/* size of DMA memory used to pass configuration to classifier, in bytes */
+#define DPAA2_CLASSIFIER_DMA_SIZE 256
+
+/* To be kept in sync with 'enum dpni_counter' */
+char dpaa2_ethtool_stats[][ETH_GSTRING_LEN] = {
+	"rx frames",
+	"rx bytes",
+	"rx frames dropped",
+	"rx err frames",
+	"rx mcast frames",
+	"rx mcast bytes",
+	"rx bcast frames",
+	"rx bcast bytes",
+	"tx frames",
+	"tx bytes",
+	"tx err frames",
+};
+
+#define DPAA2_ETH_NUM_STATS	ARRAY_SIZE(dpaa2_ethtool_stats)
+
+/* To be kept in sync with 'struct dpaa2_eth_stats' */
+char dpaa2_ethtool_extras[][ETH_GSTRING_LEN] = {
+	/* per-cpu stats */
+
+	"tx conf frames",
+	"tx conf bytes",
+	"tx sg frames",
+	"tx sg bytes",
+	"rx sg frames",
+	"rx sg bytes",
+	/* how many times we had to retry the enqueue command */
+	"tx portal busy",
+
+	/* Channel stats */
+
+	/* How many times we had to retry the volatile dequeue command */
+	"portal busy",
+	/* Number of notifications received */
+	"cdan",
+#ifdef CONFIG_FSL_QBMAN_DEBUG
+	/* FQ stats */
+	"rx pending frames",
+	"rx pending bytes",
+	"tx conf pending frames",
+	"tx conf pending bytes",
+	"buffer count"
+#endif
+};
+
+#define DPAA2_ETH_NUM_EXTRA_STATS	ARRAY_SIZE(dpaa2_ethtool_extras)
+
+static void dpaa2_get_drvinfo(struct net_device *net_dev,
+			      struct ethtool_drvinfo *drvinfo)
+{
+	struct mc_version mc_ver;
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	char fw_version[ETHTOOL_FWVERS_LEN];
+	char version[32];
+	int err;
+
+	err = mc_get_version(priv->mc_io, 0, &mc_ver);
+	if (err) {
+		strlcpy(drvinfo->fw_version, "Error retrieving MC version",
+			sizeof(drvinfo->fw_version));
+	} else {
+		scnprintf(fw_version, sizeof(fw_version), "%d.%d.%d",
+			  mc_ver.major, mc_ver.minor, mc_ver.revision);
+		strlcpy(drvinfo->fw_version, fw_version,
+			sizeof(drvinfo->fw_version));
+	}
+
+	scnprintf(version, sizeof(version), "%d.%d", DPNI_VER_MAJOR,
+		  DPNI_VER_MINOR);
+	strlcpy(drvinfo->version, version, sizeof(drvinfo->version));
+
+	strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
+	strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
+		sizeof(drvinfo->bus_info));
+}
+
+static u32 dpaa2_get_msglevel(struct net_device *net_dev)
+{
+	return ((struct dpaa2_eth_priv *)netdev_priv(net_dev))->msg_enable;
+}
+
+static void dpaa2_set_msglevel(struct net_device *net_dev,
+			       u32 msg_enable)
+{
+	((struct dpaa2_eth_priv *)netdev_priv(net_dev))->msg_enable =
+					msg_enable;
+}
+
+static int dpaa2_get_settings(struct net_device *net_dev,
+			      struct ethtool_cmd *cmd)
+{
+	struct dpni_link_state state = {0};
+	int err = 0;
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+
+	err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
+	if (err) {
+		netdev_err(net_dev, "ERROR %d getting link state", err);
+		goto out;
+	}
+
+	/* At the moment, we have no way of interrogating the DPMAC
+	 * from the DPNI side - and for that matter there may exist
+	 * no DPMAC at all. So for now we just don't report anything
+	 * beyond the DPNI attributes.
+	 */
+	if (state.options & DPNI_LINK_OPT_AUTONEG)
+		cmd->autoneg = AUTONEG_ENABLE;
+	if (!(state.options & DPNI_LINK_OPT_HALF_DUPLEX))
+		cmd->duplex = DUPLEX_FULL;
+	ethtool_cmd_speed_set(cmd, state.rate);
+
+out:
+	return err;
+}
+
+static int dpaa2_set_settings(struct net_device *net_dev,
+			      struct ethtool_cmd *cmd)
+{
+	struct dpni_link_cfg cfg = {0};
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	int err = 0;
+
+	netdev_dbg(net_dev, "Setting link parameters...");
+
+	/* Due to a temporary firmware limitation, the DPNI must be down
+	 * in order to be able to change link settings. Taking steps to let
+	 * the user know that.
+	 */
+	if (netif_running(net_dev)) {
+		netdev_info(net_dev, "Sorry, interface must be brought down first.\n");
+		return -EACCES;
+	}
+
+	cfg.rate = ethtool_cmd_speed(cmd);
+	if (cmd->autoneg == AUTONEG_ENABLE)
+		cfg.options |= DPNI_LINK_OPT_AUTONEG;
+	else
+		cfg.options &= ~DPNI_LINK_OPT_AUTONEG;
+	if (cmd->duplex  == DUPLEX_HALF)
+		cfg.options |= DPNI_LINK_OPT_HALF_DUPLEX;
+	else
+		cfg.options &= ~DPNI_LINK_OPT_HALF_DUPLEX;
+
+	err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg);
+	if (err)
+		/* ethtool will be loud enough if we return an error; no point
+		 * in putting our own error message on the console by default
+		 */
+		netdev_dbg(net_dev, "ERROR %d setting link cfg", err);
+
+	return err;
+}
+
+static void dpaa2_get_strings(struct net_device *netdev, u32 stringset,
+			      u8 *data)
+{
+	u8 *p = data;
+	int i;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < DPAA2_ETH_NUM_STATS; i++) {
+			strlcpy(p, dpaa2_ethtool_stats[i], ETH_GSTRING_LEN);
+			p += ETH_GSTRING_LEN;
+		}
+		for (i = 0; i < DPAA2_ETH_NUM_EXTRA_STATS; i++) {
+			strlcpy(p, dpaa2_ethtool_extras[i], ETH_GSTRING_LEN);
+			p += ETH_GSTRING_LEN;
+		}
+		break;
+	}
+}
+
+static int dpaa2_get_sset_count(struct net_device *net_dev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS: /* ethtool_get_stats(), ethtool_get_drvinfo() */
+		return DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+/** Fill in hardware counters, as returned by the MC firmware.
+ */
+static void dpaa2_get_ethtool_stats(struct net_device *net_dev,
+				    struct ethtool_stats *stats,
+				    u64 *data)
+{
+	int i; /* Current index in the data array */
+	int j, k, err;
+
+#ifdef CONFIG_FSL_QBMAN_DEBUG
+	u32 fcnt, bcnt;
+	u32 fcnt_rx_total = 0, fcnt_tx_total = 0;
+	u32 bcnt_rx_total = 0, bcnt_tx_total = 0;
+	u32 buf_cnt;
+#endif
+	u64 cdan = 0;
+	u64 portal_busy = 0;
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	struct dpaa2_eth_stats *extras;
+	struct dpaa2_eth_ch_stats *ch_stats;
+
+	memset(data, 0,
+	       sizeof(u64) * (DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS));
+
+	/* Print standard counters, from DPNI statistics */
+	for (i = 0; i < DPAA2_ETH_NUM_STATS; i++) {
+		err = dpni_get_counter(priv->mc_io, 0, priv->mc_token, i,
+				       data + i);
+		if (err != 0)
+			netdev_warn(net_dev, "Err %d getting DPNI counter %d",
+				    err, i);
+	}
+
+	/* Print per-cpu extra stats */
+	for_each_online_cpu(k) {
+		extras = per_cpu_ptr(priv->percpu_extras, k);
+		for (j = 0; j < sizeof(*extras) / sizeof(__u64); j++)
+			*((__u64 *)data + i + j) += *((__u64 *)extras + j);
+	}
+	i += j;
+
+	/* We may be using fewer DPIOs than actual CPUs */
+	for_each_cpu(j, &priv->dpio_cpumask) {
+		ch_stats = &priv->channel[j]->stats;
+		cdan += ch_stats->cdan;
+		portal_busy += ch_stats->dequeue_portal_busy;
+	}
+
+	*(data + i++) = portal_busy;
+	*(data + i++) = cdan;
+
+#ifdef CONFIG_FSL_QBMAN_DEBUG
+	for (j = 0; j < priv->num_fqs; j++) {
+		/* Print FQ instantaneous counts */
+		err = dpaa2_io_query_fq_count(NULL, priv->fq[j].fqid,
+					     &fcnt, &bcnt);
+		if (err) {
+			netdev_warn(net_dev, "FQ query error %d", err);
+			return;
+		}
+
+		if (priv->fq[j].type == DPAA2_TX_CONF_FQ) {
+			fcnt_tx_total += fcnt;
+			bcnt_tx_total += bcnt;
+		} else {
+			fcnt_rx_total += fcnt;
+			bcnt_rx_total += bcnt;
+		}
+	}
+	*(data + i++) = fcnt_rx_total;
+	*(data + i++) = bcnt_rx_total;
+	*(data + i++) = fcnt_tx_total;
+	*(data + i++) = bcnt_tx_total;
+
+	err = dpaa2_io_query_bp_count(NULL, priv->dpbp_attrs.bpid, &buf_cnt);
+	if (err) {
+		netdev_warn(net_dev, "Buffer count query error %d\n", err);
+		return;
+	}
+	*(data + i++) = buf_cnt;
+#endif
+}
+
+static const struct dpaa2_hash_fields {
+	u64 rxnfc_field;
+	enum net_prot cls_prot;
+	int cls_field;
+	int size;
+} dpaa2_hash_fields[] = {
+	{
+		/* L2 header */
+		.rxnfc_field = RXH_L2DA,
+		.cls_prot = NET_PROT_ETH,
+		.cls_field = NH_FLD_ETH_DA,
+		.size = 6,
+	}, {
+		/* VLAN header */
+		.rxnfc_field = RXH_VLAN,
+		.cls_prot = NET_PROT_VLAN,
+		.cls_field = NH_FLD_VLAN_TCI,
+		.size = 2,
+	}, {
+		/* IP header */
+		.rxnfc_field = RXH_IP_SRC,
+		.cls_prot = NET_PROT_IP,
+		.cls_field = NH_FLD_IP_SRC,
+		.size = 4,
+	}, {
+		.rxnfc_field = RXH_IP_DST,
+		.cls_prot = NET_PROT_IP,
+		.cls_field = NH_FLD_IP_DST,
+		.size = 4,
+	}, {
+		.rxnfc_field = RXH_L3_PROTO,
+		.cls_prot = NET_PROT_IP,
+		.cls_field = NH_FLD_IP_PROTO,
+		.size = 1,
+	}, {
+		/* Using UDP ports, this is functionally equivalent to raw
+		 * byte pairs from L4 header.
+		 */
+		.rxnfc_field = RXH_L4_B_0_1,
+		.cls_prot = NET_PROT_UDP,
+		.cls_field = NH_FLD_UDP_PORT_SRC,
+		.size = 2,
+	}, {
+		.rxnfc_field = RXH_L4_B_2_3,
+		.cls_prot = NET_PROT_UDP,
+		.cls_field = NH_FLD_UDP_PORT_DST,
+		.size = 2,
+	},
+};
+
+static int dpaa2_cls_is_enabled(struct net_device *net_dev, u64 flag)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+
+	return !!(priv->rx_hash_fields & flag);
+}
+
+static int dpaa2_cls_key_off(struct net_device *net_dev, u64 flag)
+{
+	int i, off = 0;
+
+	for (i = 0; i < ARRAY_SIZE(dpaa2_hash_fields); i++) {
+		if (dpaa2_hash_fields[i].rxnfc_field & flag)
+			return off;
+		if (dpaa2_cls_is_enabled(net_dev,
+					 dpaa2_hash_fields[i].rxnfc_field))
+			off += dpaa2_hash_fields[i].size;
+	}
+
+	return -1;
+}
+
+static u8 dpaa2_cls_key_size(struct net_device *net_dev)
+{
+	u8 i, size = 0;
+
+	for (i = 0; i < ARRAY_SIZE(dpaa2_hash_fields); i++) {
+		if (!dpaa2_cls_is_enabled(net_dev,
+					  dpaa2_hash_fields[i].rxnfc_field))
+			continue;
+		size += dpaa2_hash_fields[i].size;
+	}
+
+	return size;
+}
+
+static u8 dpaa2_cls_max_key_size(struct net_device *net_dev)
+{
+	u8 i, size = 0;
+
+	for (i = 0; i < ARRAY_SIZE(dpaa2_hash_fields); i++)
+		size += dpaa2_hash_fields[i].size;
+
+	return size;
+}
+
+void dpaa2_cls_check(struct net_device *net_dev)
+{
+	u8 key_size = dpaa2_cls_max_key_size(net_dev);
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+
+	if (priv->dpni_attrs.options & DPNI_OPT_DIST_FS &&
+	    priv->dpni_attrs.max_dist_key_size < key_size) {
+		dev_err(&net_dev->dev,
+			"max_dist_key_size = %d, expected %d.  Steering is disabled\n",
+			priv->dpni_attrs.max_dist_key_size,
+			key_size);
+		priv->dpni_attrs.options &= ~DPNI_OPT_DIST_FS;
+	}
+}
+
+/* Set RX hash options
+ * flags is a combination of RXH_ bits
+ */
+int dpaa2_set_hash(struct net_device *net_dev, u64 flags)
+{
+	struct device *dev = net_dev->dev.parent;
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	struct dpkg_profile_cfg cls_cfg;
+	struct dpni_rx_tc_dist_cfg dist_cfg;
+	u8 *dma_mem;
+	u64 enabled_flags = 0;
+	int i;
+	int err = 0;
+
+	if (!dpaa2_eth_hash_enabled(priv)) {
+		dev_err(dev, "Hashing support is not enabled\n");
+		return -EOPNOTSUPP;
+	}
+
+	if (flags & ~DPAA2_RXH_SUPPORTED) {
+		/* RXH_DISCARD is not supported */
+		dev_err(dev, "unsupported option selected, supported options are: mvtsdfn\n");
+		return -EOPNOTSUPP;
+	}
+
+	memset(&cls_cfg, 0, sizeof(cls_cfg));
+
+	for (i = 0; i < ARRAY_SIZE(dpaa2_hash_fields); i++) {
+		struct dpkg_extract *key =
+			&cls_cfg.extracts[cls_cfg.num_extracts];
+
+		if (!(flags & dpaa2_hash_fields[i].rxnfc_field))
+			continue;
+
+		if (cls_cfg.num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) {
+			dev_err(dev, "error adding key extraction rule, too many rules?\n");
+			return -E2BIG;
+		}
+
+		key->type = DPKG_EXTRACT_FROM_HDR;
+		key->extract.from_hdr.prot =
+			dpaa2_hash_fields[i].cls_prot;
+		key->extract.from_hdr.type = DPKG_FULL_FIELD;
+		key->extract.from_hdr.field =
+			dpaa2_hash_fields[i].cls_field;
+		cls_cfg.num_extracts++;
+
+		enabled_flags |= dpaa2_hash_fields[i].rxnfc_field;
+	}
+
+	dma_mem = kzalloc(DPAA2_CLASSIFIER_DMA_SIZE, GFP_DMA | GFP_KERNEL);
+	if (!dma_mem)
+		return -ENOMEM;
+
+	err = dpni_prepare_key_cfg(&cls_cfg, dma_mem);
+	if (err) {
+		dev_err(dev, "dpni_prepare_key_cfg error %d", err);
+		return err;
+	}
+
+	memset(&dist_cfg, 0, sizeof(dist_cfg));
+
+	/* Prepare for setting the rx dist */
+	dist_cfg.key_cfg_iova = dma_map_single(net_dev->dev.parent, dma_mem,
+					       DPAA2_CLASSIFIER_DMA_SIZE,
+					       DMA_TO_DEVICE);
+	if (dma_mapping_error(net_dev->dev.parent, dist_cfg.key_cfg_iova)) {
+		dev_err(dev, "DMA mapping failed\n");
+		kfree(dma_mem);
+		return -ENOMEM;
+	}
+
+	dist_cfg.dist_size = dpaa2_queue_count(priv);
+	if (dpaa2_eth_fs_enabled(priv)) {
+		dist_cfg.dist_mode = DPNI_DIST_MODE_FS;
+		dist_cfg.fs_cfg.miss_action = DPNI_FS_MISS_HASH;
+	} else {
+		dist_cfg.dist_mode = DPNI_DIST_MODE_HASH;
+	}
+
+	err = dpni_set_rx_tc_dist(priv->mc_io, 0, priv->mc_token, 0, &dist_cfg);
+	dma_unmap_single(net_dev->dev.parent, dist_cfg.key_cfg_iova,
+			 DPAA2_CLASSIFIER_DMA_SIZE, DMA_TO_DEVICE);
+	kfree(dma_mem);
+	if (err) {
+		dev_err(dev, "dpni_set_rx_tc_dist() error %d\n", err);
+		return err;
+	}
+
+	priv->rx_hash_fields = enabled_flags;
+
+	return 0;
+}
+
+static int dpaa2_cls_prep_rule(struct net_device *net_dev,
+			       struct ethtool_rx_flow_spec *fs,
+			       void *key)
+{
+	struct ethtool_tcpip4_spec *l4ip4_h, *l4ip4_m;
+	struct ethhdr *eth_h, *eth_m;
+	struct ethtool_flow_ext *ext_h, *ext_m;
+	const u8 key_size = dpaa2_cls_key_size(net_dev);
+	void *msk = key + key_size;
+
+	memset(key, 0, key_size * 2);
+
+	/* This code is a major mess, it has to be cleaned up after the
+	 * classification mask issue is fixed and key format will be made static
+	 */
+
+	switch (fs->flow_type & 0xff) {
+	case TCP_V4_FLOW:
+		l4ip4_h = &fs->h_u.tcp_ip4_spec;
+		l4ip4_m = &fs->m_u.tcp_ip4_spec;
+		/* TODO: ethertype to match IPv4 and protocol to match TCP */
+		goto l4ip4;
+
+	case UDP_V4_FLOW:
+		l4ip4_h = &fs->h_u.udp_ip4_spec;
+		l4ip4_m = &fs->m_u.udp_ip4_spec;
+		goto l4ip4;
+
+	case SCTP_V4_FLOW:
+		l4ip4_h = &fs->h_u.sctp_ip4_spec;
+		l4ip4_m = &fs->m_u.sctp_ip4_spec;
+
+l4ip4:
+		if (l4ip4_m->tos) {
+			netdev_err(net_dev,
+				   "ToS is not supported for IPv4 L4\n");
+			return -EOPNOTSUPP;
+		}
+		if (l4ip4_m->ip4src &&
+		    !dpaa2_cls_is_enabled(net_dev, RXH_IP_SRC)) {
+			netdev_err(net_dev, "IP SRC not supported!\n");
+			return -EOPNOTSUPP;
+		}
+		if (l4ip4_m->ip4dst &&
+		    !dpaa2_cls_is_enabled(net_dev, RXH_IP_DST)) {
+			netdev_err(net_dev, "IP DST not supported!\n");
+			return -EOPNOTSUPP;
+		}
+		if (l4ip4_m->psrc &&
+		    !dpaa2_cls_is_enabled(net_dev, RXH_L4_B_0_1)) {
+			netdev_err(net_dev, "PSRC not supported, ignored\n");
+			return -EOPNOTSUPP;
+		}
+		if (l4ip4_m->pdst &&
+		    !dpaa2_cls_is_enabled(net_dev, RXH_L4_B_2_3)) {
+			netdev_err(net_dev, "PDST not supported, ignored\n");
+			return -EOPNOTSUPP;
+		}
+
+		if (dpaa2_cls_is_enabled(net_dev, RXH_IP_SRC)) {
+			*(u32 *)(key + dpaa2_cls_key_off(net_dev, RXH_IP_SRC))
+				= l4ip4_h->ip4src;
+			*(u32 *)(msk + dpaa2_cls_key_off(net_dev, RXH_IP_SRC))
+				= l4ip4_m->ip4src;
+		}
+		if (dpaa2_cls_is_enabled(net_dev, RXH_IP_DST)) {
+			*(u32 *)(key + dpaa2_cls_key_off(net_dev, RXH_IP_DST))
+				= l4ip4_h->ip4dst;
+			*(u32 *)(msk + dpaa2_cls_key_off(net_dev, RXH_IP_DST))
+				= l4ip4_m->ip4dst;
+		}
+
+		if (dpaa2_cls_is_enabled(net_dev, RXH_L4_B_0_1)) {
+			*(u32 *)(key + dpaa2_cls_key_off(net_dev, RXH_L4_B_0_1))
+				= l4ip4_h->psrc;
+			*(u32 *)(msk + dpaa2_cls_key_off(net_dev, RXH_L4_B_0_1))
+				= l4ip4_m->psrc;
+		}
+
+		if (dpaa2_cls_is_enabled(net_dev, RXH_L4_B_2_3)) {
+			*(u32 *)(key + dpaa2_cls_key_off(net_dev, RXH_L4_B_2_3))
+				= l4ip4_h->pdst;
+			*(u32 *)(msk + dpaa2_cls_key_off(net_dev, RXH_L4_B_2_3))
+				= l4ip4_m->pdst;
+		}
+		break;
+
+	case ETHER_FLOW:
+		eth_h = &fs->h_u.ether_spec;
+		eth_m = &fs->m_u.ether_spec;
+
+		if (eth_m->h_proto) {
+			netdev_err(net_dev, "Ethertype is not supported!\n");
+			return -EOPNOTSUPP;
+		}
+
+		if (!is_zero_ether_addr(eth_m->h_source)) {
+			netdev_err(net_dev, "ETH SRC is not supported!\n");
+			return -EOPNOTSUPP;
+		}
+
+		if (dpaa2_cls_is_enabled(net_dev, RXH_L2DA)) {
+			ether_addr_copy(key
+					+ dpaa2_cls_key_off(net_dev, RXH_L2DA),
+					eth_h->h_dest);
+			ether_addr_copy(msk
+					+ dpaa2_cls_key_off(net_dev, RXH_L2DA),
+					eth_m->h_dest);
+		} else {
+			if (!is_zero_ether_addr(eth_m->h_dest)) {
+				netdev_err(net_dev,
+					   "ETH DST is not supported!\n");
+				return -EOPNOTSUPP;
+			}
+		}
+		break;
+
+	default:
+		/* TODO: IP user flow, AH, ESP */
+		return -EOPNOTSUPP;
+	}
+
+	if (fs->flow_type & FLOW_EXT) {
+		/* TODO: ETH data, VLAN ethertype, VLAN TCI .. */
+		return -EOPNOTSUPP;
+	}
+
+	if (fs->flow_type & FLOW_MAC_EXT) {
+		ext_h = &fs->h_ext;
+		ext_m = &fs->m_ext;
+
+		if (dpaa2_cls_is_enabled(net_dev, RXH_L2DA)) {
+			ether_addr_copy(key
+					+ dpaa2_cls_key_off(net_dev, RXH_L2DA),
+					ext_h->h_dest);
+			ether_addr_copy(msk
+					+ dpaa2_cls_key_off(net_dev, RXH_L2DA),
+					ext_m->h_dest);
+		} else {
+			if (!is_zero_ether_addr(ext_m->h_dest)) {
+				netdev_err(net_dev,
+					   "ETH DST is not supported!\n");
+				return -EOPNOTSUPP;
+			}
+		}
+	}
+	return 0;
+}
+
+static int dpaa2_do_cls(struct net_device *net_dev,
+			struct ethtool_rx_flow_spec *fs,
+			bool add)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	const int rule_cnt = DPAA2_CLASSIFIER_ENTRY_COUNT;
+	struct dpni_rule_cfg rule_cfg;
+	void *dma_mem;
+	int err = 0;
+
+	if (!dpaa2_eth_fs_enabled(priv)) {
+		netdev_err(net_dev, "dev does not support steering!\n");
+		/* dev doesn't support steering */
+		return -EOPNOTSUPP;
+	}
+
+	if ((fs->ring_cookie != RX_CLS_FLOW_DISC &&
+	     fs->ring_cookie >= dpaa2_queue_count(priv)) ||
+	     fs->location >= rule_cnt)
+		return -EINVAL;
+
+	memset(&rule_cfg, 0, sizeof(rule_cfg));
+	rule_cfg.key_size = dpaa2_cls_key_size(net_dev);
+
+	/* allocate twice the key size, for the actual key and for mask */
+	dma_mem =  kzalloc(rule_cfg.key_size * 2, GFP_DMA | GFP_KERNEL);
+	if (!dma_mem)
+		return -ENOMEM;
+
+	err = dpaa2_cls_prep_rule(net_dev, fs, dma_mem);
+	if (err)
+		goto err_free_mem;
+
+	rule_cfg.key_iova = dma_map_single(net_dev->dev.parent, dma_mem,
+					   rule_cfg.key_size * 2,
+					   DMA_TO_DEVICE);
+
+	rule_cfg.mask_iova = rule_cfg.key_iova + rule_cfg.key_size;
+
+	if (!(priv->dpni_attrs.options & DPNI_OPT_FS_MASK_SUPPORT)) {
+		int i;
+		u8 *mask = dma_mem + rule_cfg.key_size;
+
+		/* check that nothing is masked out, otherwise it won't work */
+		for (i = 0; i < rule_cfg.key_size; i++) {
+			if (mask[i] == 0xff)
+				continue;
+			netdev_err(net_dev, "dev does not support masking!\n");
+			err = -EOPNOTSUPP;
+			goto err_free_mem;
+		}
+		rule_cfg.mask_iova = 0;
+	}
+
+	/* No way to control rule order in firmware */
+	if (add)
+		err = dpni_add_fs_entry(priv->mc_io, 0, priv->mc_token, 0,
+					&rule_cfg, (u16)fs->ring_cookie);
+	else
+		err = dpni_remove_fs_entry(priv->mc_io, 0, priv->mc_token, 0,
+					   &rule_cfg);
+
+	dma_unmap_single(net_dev->dev.parent, rule_cfg.key_iova,
+			 rule_cfg.key_size * 2, DMA_TO_DEVICE);
+	if (err) {
+		netdev_err(net_dev, "dpaa2_add_cls() error %d\n", err);
+		goto err_free_mem;
+	}
+
+	priv->cls_rule[fs->location].fs = *fs;
+	priv->cls_rule[fs->location].in_use = true;
+
+err_free_mem:
+	kfree(dma_mem);
+
+	return err;
+}
+
+static int dpaa2_add_cls(struct net_device *net_dev,
+			 struct ethtool_rx_flow_spec *fs)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	int err;
+
+	err = dpaa2_do_cls(net_dev, fs, true);
+	if (err)
+		return err;
+
+	priv->cls_rule[fs->location].in_use = true;
+	priv->cls_rule[fs->location].fs = *fs;
+
+	return 0;
+}
+
+static int dpaa2_del_cls(struct net_device *net_dev, int location)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	int err;
+
+	err = dpaa2_do_cls(net_dev, &priv->cls_rule[location].fs, false);
+	if (err)
+		return err;
+
+	priv->cls_rule[location].in_use = false;
+
+	return 0;
+}
+
+static void dpaa2_clear_cls(struct net_device *net_dev)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	int i, err;
+
+	for (i = 0; i < DPAA2_CLASSIFIER_ENTRY_COUNT; i++) {
+		if (!priv->cls_rule[i].in_use)
+			continue;
+
+		err = dpaa2_del_cls(net_dev, i);
+		if (err)
+			netdev_warn(net_dev,
+				    "err trying to delete classification entry %d\n",
+				    i);
+	}
+}
+
+static int dpaa2_set_rxnfc(struct net_device *net_dev,
+			   struct ethtool_rxnfc *rxnfc)
+{
+	int err = 0;
+
+	switch (rxnfc->cmd) {
+	case ETHTOOL_SRXFH:
+		/* first off clear ALL classification rules, chaging key
+		 * composition will break them anyway
+		 */
+		dpaa2_clear_cls(net_dev);
+		/* we purposely ignore cmd->flow_type for now, because the
+		 * classifier only supports a single set of fields for all
+		 * protocols
+		 */
+		err = dpaa2_set_hash(net_dev, rxnfc->data);
+		break;
+	case ETHTOOL_SRXCLSRLINS:
+		err = dpaa2_add_cls(net_dev, &rxnfc->fs);
+		break;
+
+	case ETHTOOL_SRXCLSRLDEL:
+		err = dpaa2_del_cls(net_dev, rxnfc->fs.location);
+		break;
+
+	default:
+		err = -EOPNOTSUPP;
+	}
+
+	return err;
+}
+
+static int dpaa2_get_rxnfc(struct net_device *net_dev,
+			   struct ethtool_rxnfc *rxnfc, u32 *rule_locs)
+{
+	struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+	const int rule_cnt = DPAA2_CLASSIFIER_ENTRY_COUNT;
+	int i, j;
+
+	switch (rxnfc->cmd) {
+	case ETHTOOL_GRXFH:
+		/* we purposely ignore cmd->flow_type for now, because the
+		 * classifier only supports a single set of fields for all
+		 * protocols
+		 */
+		rxnfc->data = priv->rx_hash_fields;
+		break;
+
+	case ETHTOOL_GRXRINGS:
+		rxnfc->data = dpaa2_queue_count(priv);
+		break;
+
+	case ETHTOOL_GRXCLSRLCNT:
+		for (i = 0, rxnfc->rule_cnt = 0; i < rule_cnt; i++)
+			if (priv->cls_rule[i].in_use)
+				rxnfc->rule_cnt++;
+		rxnfc->data = rule_cnt;
+		break;
+
+	case ETHTOOL_GRXCLSRULE:
+		if (!priv->cls_rule[rxnfc->fs.location].in_use)
+			return -EINVAL;
+
+		rxnfc->fs = priv->cls_rule[rxnfc->fs.location].fs;
+		break;
+
+	case ETHTOOL_GRXCLSRLALL:
+		for (i = 0, j = 0; i < rule_cnt; i++) {
+			if (!priv->cls_rule[i].in_use)
+				continue;
+			if (j == rxnfc->rule_cnt)
+				return -EMSGSIZE;
+			rule_locs[j++] = i;
+		}
+		rxnfc->rule_cnt = j;
+		rxnfc->data = rule_cnt;
+		break;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+const struct ethtool_ops dpaa2_ethtool_ops = {
+	.get_drvinfo = dpaa2_get_drvinfo,
+	.get_msglevel = dpaa2_get_msglevel,
+	.set_msglevel = dpaa2_set_msglevel,
+	.get_link = ethtool_op_get_link,
+	.get_settings = dpaa2_get_settings,
+	.set_settings = dpaa2_set_settings,
+	.get_sset_count = dpaa2_get_sset_count,
+	.get_ethtool_stats = dpaa2_get_ethtool_stats,
+	.get_strings = dpaa2_get_strings,
+	.get_rxnfc = dpaa2_get_rxnfc,
+	.set_rxnfc = dpaa2_set_rxnfc,
+};
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpkg.h
@@ -0,0 +1,175 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __FSL_DPKG_H_
+#define __FSL_DPKG_H_
+
+#include <linux/types.h>
+#include "../../fsl-mc/include/net.h"
+
+/* Data Path Key Generator API
+ * Contains initialization APIs and runtime APIs for the Key Generator
+ */
+
+/** Key Generator properties */
+
+/**
+ * Number of masks per key extraction
+ */
+#define DPKG_NUM_OF_MASKS		4
+/**
+ * Number of extractions per key profile
+ */
+#define DPKG_MAX_NUM_OF_EXTRACTS	10
+
+/**
+ * enum dpkg_extract_from_hdr_type - Selecting extraction by header types
+ * @DPKG_FROM_HDR: Extract selected bytes from header, by offset
+ * @DPKG_FROM_FIELD: Extract selected bytes from header, by offset from field
+ * @DPKG_FULL_FIELD: Extract a full field
+ */
+enum dpkg_extract_from_hdr_type {
+	DPKG_FROM_HDR = 0,
+	DPKG_FROM_FIELD = 1,
+	DPKG_FULL_FIELD = 2
+};
+
+/**
+ * enum dpkg_extract_type - Enumeration for selecting extraction type
+ * @DPKG_EXTRACT_FROM_HDR: Extract from the header
+ * @DPKG_EXTRACT_FROM_DATA: Extract from data not in specific header
+ * @DPKG_EXTRACT_FROM_PARSE: Extract from parser-result;
+ *	e.g. can be used to extract header existence;
+ *	please refer to 'Parse Result definition' section in the parser BG
+ */
+enum dpkg_extract_type {
+	DPKG_EXTRACT_FROM_HDR = 0,
+	DPKG_EXTRACT_FROM_DATA = 1,
+	DPKG_EXTRACT_FROM_PARSE = 3
+};
+
+/**
+ * struct dpkg_mask - A structure for defining a single extraction mask
+ * @mask: Byte mask for the extracted content
+ * @offset: Offset within the extracted content
+ */
+struct dpkg_mask {
+	uint8_t mask;
+	uint8_t offset;
+};
+
+/**
+ * struct dpkg_extract - A structure for defining a single extraction
+ * @type: Determines how the union below is interpreted:
+ *		DPKG_EXTRACT_FROM_HDR: selects 'from_hdr';
+ *		DPKG_EXTRACT_FROM_DATA: selects 'from_data';
+ *		DPKG_EXTRACT_FROM_PARSE: selects 'from_parse'
+ * @extract: Selects extraction method
+ * @num_of_byte_masks: Defines the number of valid entries in the array below;
+ *		This is	also the number of bytes to be used as masks
+ * @masks: Masks parameters
+ */
+struct dpkg_extract {
+	enum dpkg_extract_type type;
+	/**
+	 * union extract - Selects extraction method
+	 * @from_hdr - Used when 'type = DPKG_EXTRACT_FROM_HDR'
+	 * @from_data - Used when 'type = DPKG_EXTRACT_FROM_DATA'
+	 * @from_parse - Used when 'type = DPKG_EXTRACT_FROM_PARSE'
+	 */
+	union {
+		/**
+		 * struct from_hdr - Used when 'type = DPKG_EXTRACT_FROM_HDR'
+		 * @prot: Any of the supported headers
+		 * @type: Defines the type of header extraction:
+		 *	DPKG_FROM_HDR: use size & offset below;
+		 *	DPKG_FROM_FIELD: use field, size and offset below;
+		 *	DPKG_FULL_FIELD: use field below
+		 * @field: One of the supported fields (NH_FLD_)
+		 *
+		 * @size: Size in bytes
+		 * @offset: Byte offset
+		 * @hdr_index: Clear for cases not listed below;
+		 *	Used for protocols that may have more than a single
+		 *	header, 0 indicates an outer header;
+		 *	Supported protocols (possible values):
+		 *	NET_PROT_VLAN (0, HDR_INDEX_LAST);
+		 *	NET_PROT_MPLS (0, 1, HDR_INDEX_LAST);
+		 *	NET_PROT_IP(0, HDR_INDEX_LAST);
+		 *	NET_PROT_IPv4(0, HDR_INDEX_LAST);
+		 *	NET_PROT_IPv6(0, HDR_INDEX_LAST);
+		 */
+
+		struct {
+			enum net_prot			prot;
+			enum dpkg_extract_from_hdr_type type;
+			uint32_t			field;
+			uint8_t			size;
+			uint8_t			offset;
+			uint8_t			hdr_index;
+		} from_hdr;
+		/**
+		 * struct from_data - Used when 'type = DPKG_EXTRACT_FROM_DATA'
+		 * @size: Size in bytes
+		 * @offset: Byte offset
+		 */
+		struct {
+			uint8_t size;
+			uint8_t offset;
+		} from_data;
+
+		/**
+		 * struct from_parse - Used when 'type = DPKG_EXTRACT_FROM_PARSE'
+		 * @size: Size in bytes
+		 * @offset: Byte offset
+		 */
+		struct {
+			uint8_t size;
+			uint8_t offset;
+		} from_parse;
+	} extract;
+
+	uint8_t		num_of_byte_masks;
+	struct dpkg_mask	masks[DPKG_NUM_OF_MASKS];
+};
+
+/**
+ * struct dpkg_profile_cfg - A structure for defining a full Key Generation
+ *				profile (rule)
+ * @num_extracts: Defines the number of valid entries in the array below
+ * @extracts: Array of required extractions
+ */
+struct dpkg_profile_cfg {
+	uint8_t num_extracts;
+	struct dpkg_extract extracts[DPKG_MAX_NUM_OF_EXTRACTS];
+};
+
+#endif /* __FSL_DPKG_H_ */
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h
@@ -0,0 +1,1058 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _FSL_DPNI_CMD_H
+#define _FSL_DPNI_CMD_H
+
+/* DPNI Version */
+#define DPNI_VER_MAJOR				6
+#define DPNI_VER_MINOR				0
+
+/* Command IDs */
+#define DPNI_CMDID_OPEN				0x801
+#define DPNI_CMDID_CLOSE			0x800
+#define DPNI_CMDID_CREATE			0x901
+#define DPNI_CMDID_DESTROY			0x900
+
+#define DPNI_CMDID_ENABLE			0x002
+#define DPNI_CMDID_DISABLE			0x003
+#define DPNI_CMDID_GET_ATTR			0x004
+#define DPNI_CMDID_RESET			0x005
+#define DPNI_CMDID_IS_ENABLED			0x006
+
+#define DPNI_CMDID_SET_IRQ			0x010
+#define DPNI_CMDID_GET_IRQ			0x011
+#define DPNI_CMDID_SET_IRQ_ENABLE		0x012
+#define DPNI_CMDID_GET_IRQ_ENABLE		0x013
+#define DPNI_CMDID_SET_IRQ_MASK			0x014
+#define DPNI_CMDID_GET_IRQ_MASK			0x015
+#define DPNI_CMDID_GET_IRQ_STATUS		0x016
+#define DPNI_CMDID_CLEAR_IRQ_STATUS		0x017
+
+#define DPNI_CMDID_SET_POOLS			0x200
+#define DPNI_CMDID_GET_RX_BUFFER_LAYOUT		0x201
+#define DPNI_CMDID_SET_RX_BUFFER_LAYOUT		0x202
+#define DPNI_CMDID_GET_TX_BUFFER_LAYOUT		0x203
+#define DPNI_CMDID_SET_TX_BUFFER_LAYOUT		0x204
+#define DPNI_CMDID_SET_TX_CONF_BUFFER_LAYOUT	0x205
+#define DPNI_CMDID_GET_TX_CONF_BUFFER_LAYOUT	0x206
+#define DPNI_CMDID_SET_L3_CHKSUM_VALIDATION	0x207
+#define DPNI_CMDID_GET_L3_CHKSUM_VALIDATION	0x208
+#define DPNI_CMDID_SET_L4_CHKSUM_VALIDATION	0x209
+#define DPNI_CMDID_GET_L4_CHKSUM_VALIDATION	0x20A
+#define DPNI_CMDID_SET_ERRORS_BEHAVIOR		0x20B
+#define DPNI_CMDID_SET_TX_CONF_REVOKE		0x20C
+
+#define DPNI_CMDID_GET_QDID			0x210
+#define DPNI_CMDID_GET_SP_INFO			0x211
+#define DPNI_CMDID_GET_TX_DATA_OFFSET		0x212
+#define DPNI_CMDID_GET_COUNTER			0x213
+#define DPNI_CMDID_SET_COUNTER			0x214
+#define DPNI_CMDID_GET_LINK_STATE		0x215
+#define DPNI_CMDID_SET_MAX_FRAME_LENGTH		0x216
+#define DPNI_CMDID_GET_MAX_FRAME_LENGTH		0x217
+#define DPNI_CMDID_SET_MTU			0x218
+#define DPNI_CMDID_GET_MTU			0x219
+#define DPNI_CMDID_SET_LINK_CFG			0x21A
+#define DPNI_CMDID_SET_TX_SHAPING		0x21B
+
+#define DPNI_CMDID_SET_MCAST_PROMISC		0x220
+#define DPNI_CMDID_GET_MCAST_PROMISC		0x221
+#define DPNI_CMDID_SET_UNICAST_PROMISC		0x222
+#define DPNI_CMDID_GET_UNICAST_PROMISC		0x223
+#define DPNI_CMDID_SET_PRIM_MAC			0x224
+#define DPNI_CMDID_GET_PRIM_MAC			0x225
+#define DPNI_CMDID_ADD_MAC_ADDR			0x226
+#define DPNI_CMDID_REMOVE_MAC_ADDR		0x227
+#define DPNI_CMDID_CLR_MAC_FILTERS		0x228
+
+#define DPNI_CMDID_SET_VLAN_FILTERS		0x230
+#define DPNI_CMDID_ADD_VLAN_ID			0x231
+#define DPNI_CMDID_REMOVE_VLAN_ID		0x232
+#define DPNI_CMDID_CLR_VLAN_FILTERS		0x233
+
+#define DPNI_CMDID_SET_RX_TC_DIST		0x235
+#define DPNI_CMDID_SET_TX_FLOW			0x236
+#define DPNI_CMDID_GET_TX_FLOW			0x237
+#define DPNI_CMDID_SET_RX_FLOW			0x238
+#define DPNI_CMDID_GET_RX_FLOW			0x239
+#define DPNI_CMDID_SET_RX_ERR_QUEUE		0x23A
+#define DPNI_CMDID_GET_RX_ERR_QUEUE		0x23B
+
+#define DPNI_CMDID_SET_RX_TC_POLICING		0x23E
+#define DPNI_CMDID_SET_RX_TC_EARLY_DROP		0x23F
+
+#define DPNI_CMDID_SET_QOS_TBL			0x240
+#define DPNI_CMDID_ADD_QOS_ENT			0x241
+#define DPNI_CMDID_REMOVE_QOS_ENT		0x242
+#define DPNI_CMDID_CLR_QOS_TBL			0x243
+#define DPNI_CMDID_ADD_FS_ENT			0x244
+#define DPNI_CMDID_REMOVE_FS_ENT		0x245
+#define DPNI_CMDID_CLR_FS_ENT			0x246
+#define DPNI_CMDID_SET_VLAN_INSERTION		0x247
+#define DPNI_CMDID_SET_VLAN_REMOVAL		0x248
+#define DPNI_CMDID_SET_IPR			0x249
+#define DPNI_CMDID_SET_IPF			0x24A
+
+#define DPNI_CMDID_SET_TX_SELECTION			0x250
+#define DPNI_CMDID_GET_RX_TC_POLICING		0x251
+#define DPNI_CMDID_GET_RX_TC_EARLY_DROP		0x252
+#define DPNI_CMDID_SET_RX_TC_CONGESTION_NOTIFICATION 0x253
+#define DPNI_CMDID_GET_RX_TC_CONGESTION_NOTIFICATION 0x254
+#define DPNI_CMDID_SET_TX_TC_CONGESTION_NOTIFICATION 0x255
+#define DPNI_CMDID_GET_TX_TC_CONGESTION_NOTIFICATION 0x256
+#define DPNI_CMDID_SET_TX_CONF						0x257
+#define DPNI_CMDID_GET_TX_CONF						0x258
+#define DPNI_CMDID_SET_TX_CONF_CONGESTION_NOTIFICATION 0x259
+#define DPNI_CMDID_GET_TX_CONF_CONGESTION_NOTIFICATION 0x25A
+#define DPNI_CMDID_SET_TX_TC_EARLY_DROP				0x25B
+#define DPNI_CMDID_GET_TX_TC_EARLY_DROP				0x25C
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_OPEN(cmd, dpni_id) \
+	MC_CMD_OP(cmd,	 0,	0,	32,	int,	dpni_id)
+
+#define DPNI_PREP_EXTENDED_CFG(ext, cfg) \
+do { \
+	MC_PREP_OP(ext, 0, 0,   16, uint16_t, cfg->tc_cfg[0].max_dist); \
+	MC_PREP_OP(ext, 0, 16,  16, uint16_t, cfg->tc_cfg[0].max_fs_entries); \
+	MC_PREP_OP(ext, 0, 32,  16, uint16_t, cfg->tc_cfg[1].max_dist); \
+	MC_PREP_OP(ext, 0, 48,  16, uint16_t, cfg->tc_cfg[1].max_fs_entries); \
+	MC_PREP_OP(ext, 1, 0,   16, uint16_t, cfg->tc_cfg[2].max_dist); \
+	MC_PREP_OP(ext, 1, 16,  16, uint16_t, cfg->tc_cfg[2].max_fs_entries); \
+	MC_PREP_OP(ext, 1, 32,  16, uint16_t, cfg->tc_cfg[3].max_dist); \
+	MC_PREP_OP(ext, 1, 48,  16, uint16_t, cfg->tc_cfg[3].max_fs_entries); \
+	MC_PREP_OP(ext, 2, 0,   16, uint16_t, cfg->tc_cfg[4].max_dist); \
+	MC_PREP_OP(ext, 2, 16,  16, uint16_t, cfg->tc_cfg[4].max_fs_entries); \
+	MC_PREP_OP(ext, 2, 32,  16, uint16_t, cfg->tc_cfg[5].max_dist); \
+	MC_PREP_OP(ext, 2, 48,  16, uint16_t, cfg->tc_cfg[5].max_fs_entries); \
+	MC_PREP_OP(ext, 3, 0,   16, uint16_t, cfg->tc_cfg[6].max_dist); \
+	MC_PREP_OP(ext, 3, 16,  16, uint16_t, cfg->tc_cfg[6].max_fs_entries); \
+	MC_PREP_OP(ext, 3, 32,  16, uint16_t, cfg->tc_cfg[7].max_dist); \
+	MC_PREP_OP(ext, 3, 48,  16, uint16_t, cfg->tc_cfg[7].max_fs_entries); \
+	MC_PREP_OP(ext, 4, 0,   16, uint16_t, \
+		   cfg->ipr_cfg.max_open_frames_ipv4); \
+	MC_PREP_OP(ext, 4, 16,  16, uint16_t, \
+		   cfg->ipr_cfg.max_open_frames_ipv6); \
+	MC_PREP_OP(ext, 4, 32,  16, uint16_t, \
+		   cfg->ipr_cfg.max_reass_frm_size); \
+	MC_PREP_OP(ext, 5, 0,   16, uint16_t, \
+		   cfg->ipr_cfg.min_frag_size_ipv4); \
+	MC_PREP_OP(ext, 5, 16,  16, uint16_t, \
+		   cfg->ipr_cfg.min_frag_size_ipv6); \
+} while (0)
+
+#define DPNI_EXT_EXTENDED_CFG(ext, cfg) \
+do { \
+	MC_EXT_OP(ext, 0, 0,   16, uint16_t, cfg->tc_cfg[0].max_dist); \
+	MC_EXT_OP(ext, 0, 16,  16, uint16_t, cfg->tc_cfg[0].max_fs_entries); \
+	MC_EXT_OP(ext, 0, 32,  16, uint16_t, cfg->tc_cfg[1].max_dist); \
+	MC_EXT_OP(ext, 0, 48,  16, uint16_t, cfg->tc_cfg[1].max_fs_entries); \
+	MC_EXT_OP(ext, 1, 0,   16, uint16_t, cfg->tc_cfg[2].max_dist); \
+	MC_EXT_OP(ext, 1, 16,  16, uint16_t, cfg->tc_cfg[2].max_fs_entries); \
+	MC_EXT_OP(ext, 1, 32,  16, uint16_t, cfg->tc_cfg[3].max_dist); \
+	MC_EXT_OP(ext, 1, 48,  16, uint16_t, cfg->tc_cfg[3].max_fs_entries); \
+	MC_EXT_OP(ext, 2, 0,   16, uint16_t, cfg->tc_cfg[4].max_dist); \
+	MC_EXT_OP(ext, 2, 16,  16, uint16_t, cfg->tc_cfg[4].max_fs_entries); \
+	MC_EXT_OP(ext, 2, 32,  16, uint16_t, cfg->tc_cfg[5].max_dist); \
+	MC_EXT_OP(ext, 2, 48,  16, uint16_t, cfg->tc_cfg[5].max_fs_entries); \
+	MC_EXT_OP(ext, 3, 0,   16, uint16_t, cfg->tc_cfg[6].max_dist); \
+	MC_EXT_OP(ext, 3, 16,  16, uint16_t, cfg->tc_cfg[6].max_fs_entries); \
+	MC_EXT_OP(ext, 3, 32,  16, uint16_t, cfg->tc_cfg[7].max_dist); \
+	MC_EXT_OP(ext, 3, 48,  16, uint16_t, cfg->tc_cfg[7].max_fs_entries); \
+	MC_EXT_OP(ext, 4, 0,   16, uint16_t, \
+		  cfg->ipr_cfg.max_open_frames_ipv4); \
+	MC_EXT_OP(ext, 4, 16,  16, uint16_t, \
+		  cfg->ipr_cfg.max_open_frames_ipv6); \
+	MC_EXT_OP(ext, 4, 32,  16, uint16_t, \
+		  cfg->ipr_cfg.max_reass_frm_size); \
+	MC_EXT_OP(ext, 5, 0,   16, uint16_t, \
+		  cfg->ipr_cfg.min_frag_size_ipv4); \
+	MC_EXT_OP(ext, 5, 16,  16, uint16_t, \
+		  cfg->ipr_cfg.min_frag_size_ipv6); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_CREATE(cmd, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,	8,  uint8_t,  cfg->adv.max_tcs); \
+	MC_CMD_OP(cmd, 0, 8,	8,  uint8_t,  cfg->adv.max_senders); \
+	MC_CMD_OP(cmd, 0, 16,	8,  uint8_t,  cfg->mac_addr[5]); \
+	MC_CMD_OP(cmd, 0, 24,	8,  uint8_t,  cfg->mac_addr[4]); \
+	MC_CMD_OP(cmd, 0, 32,	8,  uint8_t,  cfg->mac_addr[3]); \
+	MC_CMD_OP(cmd, 0, 40,	8,  uint8_t,  cfg->mac_addr[2]); \
+	MC_CMD_OP(cmd, 0, 48,	8,  uint8_t,  cfg->mac_addr[1]); \
+	MC_CMD_OP(cmd, 0, 56,	8,  uint8_t,  cfg->mac_addr[0]); \
+	MC_CMD_OP(cmd, 1, 0,	32, uint32_t, cfg->adv.options); \
+	MC_CMD_OP(cmd, 2, 0,	8,  uint8_t,  cfg->adv.max_unicast_filters); \
+	MC_CMD_OP(cmd, 2, 8,	8,  uint8_t,  cfg->adv.max_multicast_filters); \
+	MC_CMD_OP(cmd, 2, 16,	8,  uint8_t,  cfg->adv.max_vlan_filters); \
+	MC_CMD_OP(cmd, 2, 24,	8,  uint8_t,  cfg->adv.max_qos_entries); \
+	MC_CMD_OP(cmd, 2, 32,	8,  uint8_t,  cfg->adv.max_qos_key_size); \
+	MC_CMD_OP(cmd, 2, 48,	8,  uint8_t,  cfg->adv.max_dist_key_size); \
+	MC_CMD_OP(cmd, 2, 56,	8,  enum net_prot, cfg->adv.start_hdr); \
+	MC_CMD_OP(cmd, 4, 48,	8,  uint8_t, cfg->adv.max_policers); \
+	MC_CMD_OP(cmd, 4, 56,	8,  uint8_t, cfg->adv.max_congestion_ctrl); \
+	MC_CMD_OP(cmd, 5, 0,	64, uint64_t, cfg->adv.ext_cfg_iova); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_POOLS(cmd, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  cfg->num_dpbp); \
+	MC_CMD_OP(cmd, 0, 8,  1,  int,      cfg->pools[0].backup_pool); \
+	MC_CMD_OP(cmd, 0, 9,  1,  int,      cfg->pools[1].backup_pool); \
+	MC_CMD_OP(cmd, 0, 10, 1,  int,      cfg->pools[2].backup_pool); \
+	MC_CMD_OP(cmd, 0, 11, 1,  int,      cfg->pools[3].backup_pool); \
+	MC_CMD_OP(cmd, 0, 12, 1,  int,      cfg->pools[4].backup_pool); \
+	MC_CMD_OP(cmd, 0, 13, 1,  int,      cfg->pools[5].backup_pool); \
+	MC_CMD_OP(cmd, 0, 14, 1,  int,      cfg->pools[6].backup_pool); \
+	MC_CMD_OP(cmd, 0, 15, 1,  int,      cfg->pools[7].backup_pool); \
+	MC_CMD_OP(cmd, 0, 32, 32, int,      cfg->pools[0].dpbp_id); \
+	MC_CMD_OP(cmd, 4, 32, 16, uint16_t, cfg->pools[0].buffer_size);\
+	MC_CMD_OP(cmd, 1, 0,  32, int,      cfg->pools[1].dpbp_id); \
+	MC_CMD_OP(cmd, 4, 48, 16, uint16_t, cfg->pools[1].buffer_size);\
+	MC_CMD_OP(cmd, 1, 32, 32, int,      cfg->pools[2].dpbp_id); \
+	MC_CMD_OP(cmd, 5, 0,  16, uint16_t, cfg->pools[2].buffer_size);\
+	MC_CMD_OP(cmd, 2, 0,  32, int,      cfg->pools[3].dpbp_id); \
+	MC_CMD_OP(cmd, 5, 16, 16, uint16_t, cfg->pools[3].buffer_size);\
+	MC_CMD_OP(cmd, 2, 32, 32, int,      cfg->pools[4].dpbp_id); \
+	MC_CMD_OP(cmd, 5, 32, 16, uint16_t, cfg->pools[4].buffer_size);\
+	MC_CMD_OP(cmd, 3, 0,  32, int,      cfg->pools[5].dpbp_id); \
+	MC_CMD_OP(cmd, 5, 48, 16, uint16_t, cfg->pools[5].buffer_size);\
+	MC_CMD_OP(cmd, 3, 32, 32, int,      cfg->pools[6].dpbp_id); \
+	MC_CMD_OP(cmd, 6, 0,  16, uint16_t, cfg->pools[6].buffer_size);\
+	MC_CMD_OP(cmd, 4, 0,  32, int,      cfg->pools[7].dpbp_id); \
+	MC_CMD_OP(cmd, 6, 16, 16, uint16_t, cfg->pools[7].buffer_size);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_IS_ENABLED(cmd, en) \
+	MC_RSP_OP(cmd, 0, 0,  1,  int,	    en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_IRQ(cmd, irq_index, irq_cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  32, uint32_t, irq_cfg->val); \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index); \
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, irq_cfg->addr); \
+	MC_CMD_OP(cmd, 2, 0,  32, int,	    irq_cfg->irq_num); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_GET_IRQ(cmd, irq_index) \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_IRQ(cmd, type, irq_cfg) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  32, uint32_t, irq_cfg->val); \
+	MC_RSP_OP(cmd, 1, 0,  64, uint64_t, irq_cfg->addr); \
+	MC_RSP_OP(cmd, 2, 0,  32, int,      irq_cfg->irq_num); \
+	MC_RSP_OP(cmd, 2, 32, 32, int,	    type); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  8,  uint8_t,  en); \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_GET_IRQ_ENABLE(cmd, irq_index) \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_IRQ_ENABLE(cmd, en) \
+	MC_RSP_OP(cmd, 0, 0,  8,  uint8_t,  en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  32, uint32_t, mask); \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_GET_IRQ_MASK(cmd, irq_index) \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_IRQ_MASK(cmd, mask) \
+	MC_RSP_OP(cmd, 0, 0,  32, uint32_t,  mask)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_GET_IRQ_STATUS(cmd, irq_index, status) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  32, uint32_t, status);\
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_IRQ_STATUS(cmd, status) \
+	MC_RSP_OP(cmd, 0, 0,  32, uint32_t,  status)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  32, uint32_t, status); \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  irq_index);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_GET_ATTR(cmd, attr) \
+	MC_CMD_OP(cmd, 6, 0,  64, uint64_t, attr->ext_cfg_iova)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_ATTR(cmd, attr) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  32, int,	    attr->id);\
+	MC_RSP_OP(cmd, 0, 32, 8,  uint8_t,  attr->max_tcs); \
+	MC_RSP_OP(cmd, 0, 40, 8,  uint8_t,  attr->max_senders); \
+	MC_RSP_OP(cmd, 0, 48, 8,  enum net_prot, attr->start_hdr); \
+	MC_RSP_OP(cmd, 1, 0,  32, uint32_t, attr->options); \
+	MC_RSP_OP(cmd, 2, 0,  8,  uint8_t,  attr->max_unicast_filters); \
+	MC_RSP_OP(cmd, 2, 8,  8,  uint8_t,  attr->max_multicast_filters);\
+	MC_RSP_OP(cmd, 2, 16, 8,  uint8_t,  attr->max_vlan_filters); \
+	MC_RSP_OP(cmd, 2, 24, 8,  uint8_t,  attr->max_qos_entries); \
+	MC_RSP_OP(cmd, 2, 32, 8,  uint8_t,  attr->max_qos_key_size); \
+	MC_RSP_OP(cmd, 2, 40, 8,  uint8_t,  attr->max_dist_key_size); \
+	MC_RSP_OP(cmd, 4, 48, 8,  uint8_t, attr->max_policers); \
+	MC_RSP_OP(cmd, 4, 56, 8,  uint8_t, attr->max_congestion_ctrl); \
+	MC_RSP_OP(cmd, 5, 32, 16, uint16_t, attr->version.major);\
+	MC_RSP_OP(cmd, 5, 48, 16, uint16_t, attr->version.minor);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_ERRORS_BEHAVIOR(cmd, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  32, uint32_t, cfg->errors); \
+	MC_CMD_OP(cmd, 0, 32, 4,  enum dpni_error_action, cfg->error_action); \
+	MC_CMD_OP(cmd, 0, 36, 1,  int,      cfg->set_frame_annotation); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_RX_BUFFER_LAYOUT(cmd, layout) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  16, uint16_t, layout->private_data_size); \
+	MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \
+	MC_RSP_OP(cmd, 1, 0,  1,  int,	    layout->pass_timestamp); \
+	MC_RSP_OP(cmd, 1, 1,  1,  int,	    layout->pass_parser_result); \
+	MC_RSP_OP(cmd, 1, 2,  1,  int,	    layout->pass_frame_status); \
+	MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \
+	MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_RX_BUFFER_LAYOUT(cmd, layout) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  16, uint16_t, layout->private_data_size); \
+	MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \
+	MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \
+	MC_CMD_OP(cmd, 1, 0,  1,  int,	    layout->pass_timestamp); \
+	MC_CMD_OP(cmd, 1, 1,  1,  int,	    layout->pass_parser_result); \
+	MC_CMD_OP(cmd, 1, 2,  1,  int,	    layout->pass_frame_status); \
+	MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \
+	MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_TX_BUFFER_LAYOUT(cmd, layout) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  16, uint16_t, layout->private_data_size); \
+	MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \
+	MC_RSP_OP(cmd, 1, 0,  1,  int,      layout->pass_timestamp); \
+	MC_RSP_OP(cmd, 1, 1,  1,  int,	    layout->pass_parser_result); \
+	MC_RSP_OP(cmd, 1, 2,  1,  int,	    layout->pass_frame_status); \
+	MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \
+	MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_TX_BUFFER_LAYOUT(cmd, layout) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  16, uint16_t, layout->private_data_size); \
+	MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \
+	MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \
+	MC_CMD_OP(cmd, 1, 0,  1,  int,	    layout->pass_timestamp); \
+	MC_CMD_OP(cmd, 1, 1,  1,  int,	    layout->pass_parser_result); \
+	MC_CMD_OP(cmd, 1, 2,  1,  int,	    layout->pass_frame_status); \
+	MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \
+	MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_TX_CONF_BUFFER_LAYOUT(cmd, layout) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  16, uint16_t, layout->private_data_size); \
+	MC_RSP_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \
+	MC_RSP_OP(cmd, 1, 0,  1,  int,      layout->pass_timestamp); \
+	MC_RSP_OP(cmd, 1, 1,  1,  int,	    layout->pass_parser_result); \
+	MC_RSP_OP(cmd, 1, 2,  1,  int,	    layout->pass_frame_status); \
+	MC_RSP_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \
+	MC_RSP_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_TX_CONF_BUFFER_LAYOUT(cmd, layout) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  16, uint16_t, layout->private_data_size); \
+	MC_CMD_OP(cmd, 0, 16, 16, uint16_t, layout->data_align); \
+	MC_CMD_OP(cmd, 0, 32, 32, uint32_t, layout->options); \
+	MC_CMD_OP(cmd, 1, 0,  1,  int,	    layout->pass_timestamp); \
+	MC_CMD_OP(cmd, 1, 1,  1,  int,	    layout->pass_parser_result); \
+	MC_CMD_OP(cmd, 1, 2,  1,  int,	    layout->pass_frame_status); \
+	MC_CMD_OP(cmd, 1, 16, 16, uint16_t, layout->data_head_room); \
+	MC_CMD_OP(cmd, 1, 32, 16, uint16_t, layout->data_tail_room); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_L3_CHKSUM_VALIDATION(cmd, en) \
+	MC_CMD_OP(cmd, 0, 0,  1,  int,	    en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_L3_CHKSUM_VALIDATION(cmd, en) \
+	MC_RSP_OP(cmd, 0, 0,  1,  int,	    en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_L4_CHKSUM_VALIDATION(cmd, en) \
+	MC_CMD_OP(cmd, 0, 0,  1,  int,	    en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_L4_CHKSUM_VALIDATION(cmd, en) \
+	MC_RSP_OP(cmd, 0, 0,  1,  int,	    en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_QDID(cmd, qdid) \
+	MC_RSP_OP(cmd, 0, 0,  16, uint16_t, qdid)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_SP_INFO(cmd, sp_info) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  16, uint16_t, sp_info->spids[0]); \
+	MC_RSP_OP(cmd, 0, 16, 16, uint16_t, sp_info->spids[1]); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_TX_DATA_OFFSET(cmd, data_offset) \
+	MC_RSP_OP(cmd, 0, 0,  16, uint16_t, data_offset)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_GET_COUNTER(cmd, counter) \
+	MC_CMD_OP(cmd, 0, 0,  16, enum dpni_counter, counter)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_COUNTER(cmd, value) \
+	MC_RSP_OP(cmd, 1, 0,  64, uint64_t, value)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_COUNTER(cmd, counter, value) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  16, enum dpni_counter, counter); \
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, value); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_LINK_CFG(cmd, cfg) \
+do { \
+	MC_CMD_OP(cmd, 1, 0,  32, uint32_t, cfg->rate);\
+	MC_CMD_OP(cmd, 2, 0,  64, uint64_t, cfg->options);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_LINK_STATE(cmd, state) \
+do { \
+	MC_RSP_OP(cmd, 0, 32,  1, int,      state->up);\
+	MC_RSP_OP(cmd, 1, 0,  32, uint32_t, state->rate);\
+	MC_RSP_OP(cmd, 2, 0,  64, uint64_t, state->options);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_TX_SHAPING(cmd, tx_shaper) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  16, uint16_t, tx_shaper->max_burst_size);\
+	MC_CMD_OP(cmd, 1, 0,  32, uint32_t, tx_shaper->rate_limit);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_MAX_FRAME_LENGTH(cmd, max_frame_length) \
+	MC_CMD_OP(cmd, 0, 0,  16, uint16_t, max_frame_length)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_MAX_FRAME_LENGTH(cmd, max_frame_length) \
+	MC_RSP_OP(cmd, 0, 0,  16, uint16_t, max_frame_length)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_MTU(cmd, mtu) \
+	MC_CMD_OP(cmd, 0, 0,  16, uint16_t, mtu)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_MTU(cmd, mtu) \
+	MC_RSP_OP(cmd, 0, 0,  16, uint16_t, mtu)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_MULTICAST_PROMISC(cmd, en) \
+	MC_CMD_OP(cmd, 0, 0,  1,  int,      en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_MULTICAST_PROMISC(cmd, en) \
+	MC_RSP_OP(cmd, 0, 0,  1,  int,	    en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_UNICAST_PROMISC(cmd, en) \
+	MC_CMD_OP(cmd, 0, 0,  1,  int,      en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_UNICAST_PROMISC(cmd, en) \
+	MC_RSP_OP(cmd, 0, 0,  1,  int,	    en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_PRIMARY_MAC_ADDR(cmd, mac_addr) \
+do { \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  mac_addr[5]); \
+	MC_CMD_OP(cmd, 0, 24, 8,  uint8_t,  mac_addr[4]); \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  mac_addr[3]); \
+	MC_CMD_OP(cmd, 0, 40, 8,  uint8_t,  mac_addr[2]); \
+	MC_CMD_OP(cmd, 0, 48, 8,  uint8_t,  mac_addr[1]); \
+	MC_CMD_OP(cmd, 0, 56, 8,  uint8_t,  mac_addr[0]); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_PRIMARY_MAC_ADDR(cmd, mac_addr) \
+do { \
+	MC_RSP_OP(cmd, 0, 16, 8,  uint8_t,  mac_addr[5]); \
+	MC_RSP_OP(cmd, 0, 24, 8,  uint8_t,  mac_addr[4]); \
+	MC_RSP_OP(cmd, 0, 32, 8,  uint8_t,  mac_addr[3]); \
+	MC_RSP_OP(cmd, 0, 40, 8,  uint8_t,  mac_addr[2]); \
+	MC_RSP_OP(cmd, 0, 48, 8,  uint8_t,  mac_addr[1]); \
+	MC_RSP_OP(cmd, 0, 56, 8,  uint8_t,  mac_addr[0]); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_ADD_MAC_ADDR(cmd, mac_addr) \
+do { \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  mac_addr[5]); \
+	MC_CMD_OP(cmd, 0, 24, 8,  uint8_t,  mac_addr[4]); \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  mac_addr[3]); \
+	MC_CMD_OP(cmd, 0, 40, 8,  uint8_t,  mac_addr[2]); \
+	MC_CMD_OP(cmd, 0, 48, 8,  uint8_t,  mac_addr[1]); \
+	MC_CMD_OP(cmd, 0, 56, 8,  uint8_t,  mac_addr[0]); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_REMOVE_MAC_ADDR(cmd, mac_addr) \
+do { \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  mac_addr[5]); \
+	MC_CMD_OP(cmd, 0, 24, 8,  uint8_t,  mac_addr[4]); \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  mac_addr[3]); \
+	MC_CMD_OP(cmd, 0, 40, 8,  uint8_t,  mac_addr[2]); \
+	MC_CMD_OP(cmd, 0, 48, 8,  uint8_t,  mac_addr[1]); \
+	MC_CMD_OP(cmd, 0, 56, 8,  uint8_t,  mac_addr[0]); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_CLEAR_MAC_FILTERS(cmd, unicast, multicast) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  1,  int,      unicast); \
+	MC_CMD_OP(cmd, 0, 1,  1,  int,      multicast); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_VLAN_FILTERS(cmd, en) \
+	MC_CMD_OP(cmd, 0, 0,  1,  int,	    en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_ADD_VLAN_ID(cmd, vlan_id) \
+	MC_CMD_OP(cmd, 0, 32, 16, uint16_t, vlan_id)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_REMOVE_VLAN_ID(cmd, vlan_id) \
+	MC_CMD_OP(cmd, 0, 32, 16, uint16_t, vlan_id)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_TX_SELECTION(cmd, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  16,  uint16_t, cfg->tc_sched[0].delta_bandwidth);\
+	MC_CMD_OP(cmd, 0, 16,  4,  enum dpni_tx_schedule_mode, \
+				cfg->tc_sched[0].mode); \
+	MC_CMD_OP(cmd, 0, 32, 16,  uint16_t, cfg->tc_sched[1].delta_bandwidth);\
+	MC_CMD_OP(cmd, 0, 48, 4,  enum dpni_tx_schedule_mode, \
+				cfg->tc_sched[1].mode); \
+	MC_CMD_OP(cmd, 1, 0,  16,  uint16_t, cfg->tc_sched[2].delta_bandwidth);\
+	MC_CMD_OP(cmd, 1, 16,  4,  enum dpni_tx_schedule_mode, \
+				cfg->tc_sched[2].mode); \
+	MC_CMD_OP(cmd, 1, 32, 16,  uint16_t, cfg->tc_sched[3].delta_bandwidth);\
+	MC_CMD_OP(cmd, 1, 48, 4,  enum dpni_tx_schedule_mode, \
+				cfg->tc_sched[3].mode); \
+	MC_CMD_OP(cmd, 2, 0,  16,  uint16_t, cfg->tc_sched[4].delta_bandwidth);\
+	MC_CMD_OP(cmd, 2, 16,  4,  enum dpni_tx_schedule_mode, \
+				cfg->tc_sched[4].mode); \
+	MC_CMD_OP(cmd, 2, 32, 16,  uint16_t, cfg->tc_sched[5].delta_bandwidth);\
+	MC_CMD_OP(cmd, 2, 48, 4,  enum dpni_tx_schedule_mode, \
+				cfg->tc_sched[5].mode); \
+	MC_CMD_OP(cmd, 3, 0,  16,  uint16_t, cfg->tc_sched[6].delta_bandwidth);\
+	MC_CMD_OP(cmd, 3, 16,  4,  enum dpni_tx_schedule_mode, \
+				cfg->tc_sched[6].mode); \
+	MC_CMD_OP(cmd, 3, 32, 16,  uint16_t, cfg->tc_sched[7].delta_bandwidth);\
+	MC_CMD_OP(cmd, 3, 48, 4,  enum dpni_tx_schedule_mode, \
+				cfg->tc_sched[7].mode); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_RX_TC_DIST(cmd, tc_id, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  16, uint16_t,  cfg->dist_size); \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  tc_id); \
+	MC_CMD_OP(cmd, 0, 24, 4,  enum dpni_dist_mode, cfg->dist_mode); \
+	MC_CMD_OP(cmd, 0, 28, 4,  enum dpni_fs_miss_action, \
+						  cfg->fs_cfg.miss_action); \
+	MC_CMD_OP(cmd, 0, 48, 16, uint16_t, cfg->fs_cfg.default_flow_id); \
+	MC_CMD_OP(cmd, 6, 0,  64, uint64_t, cfg->key_cfg_iova); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_TX_FLOW(cmd, flow_id, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 43, 1,  int,	    cfg->l3_chksum_gen);\
+	MC_CMD_OP(cmd, 0, 44, 1,  int,	    cfg->l4_chksum_gen);\
+	MC_CMD_OP(cmd, 0, 45, 1,  int,	    cfg->use_common_tx_conf_queue);\
+	MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id);\
+	MC_CMD_OP(cmd, 2, 0,  32, uint32_t, cfg->options);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_SET_TX_FLOW(cmd, flow_id) \
+	MC_RSP_OP(cmd, 0, 48, 16, uint16_t, flow_id)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_GET_TX_FLOW(cmd, flow_id) \
+	MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_TX_FLOW(cmd, attr) \
+do { \
+	MC_RSP_OP(cmd, 0, 43, 1,  int,	    attr->l3_chksum_gen);\
+	MC_RSP_OP(cmd, 0, 44, 1,  int,	    attr->l4_chksum_gen);\
+	MC_RSP_OP(cmd, 0, 45, 1,  int,	    attr->use_common_tx_conf_queue);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_RX_FLOW(cmd, tc_id, flow_id, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  32, int,      cfg->dest_cfg.dest_id); \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  cfg->dest_cfg.priority);\
+	MC_CMD_OP(cmd, 0, 40, 2,  enum dpni_dest, cfg->dest_cfg.dest_type);\
+	MC_CMD_OP(cmd, 0, 42, 1,  int,      cfg->order_preservation_en);\
+	MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, cfg->user_ctx); \
+	MC_CMD_OP(cmd, 2, 16, 8,  uint8_t,  tc_id); \
+	MC_CMD_OP(cmd, 2, 32, 32, uint32_t, cfg->options); \
+	MC_CMD_OP(cmd, 3, 0,  4,  enum dpni_flc_type, cfg->flc_cfg.flc_type); \
+	MC_CMD_OP(cmd, 3, 4,  4,  enum dpni_stash_size, \
+		cfg->flc_cfg.frame_data_size);\
+	MC_CMD_OP(cmd, 3, 8,  4,  enum dpni_stash_size, \
+		cfg->flc_cfg.flow_context_size);\
+	MC_CMD_OP(cmd, 3, 32, 32, uint32_t, cfg->flc_cfg.options);\
+	MC_CMD_OP(cmd, 4, 0,  64, uint64_t, cfg->flc_cfg.flow_context);\
+	MC_CMD_OP(cmd, 5, 0,  32, uint32_t, cfg->tail_drop_threshold); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_GET_RX_FLOW(cmd, tc_id, flow_id) \
+do { \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  tc_id); \
+	MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_RX_FLOW(cmd, attr) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  32, int,      attr->dest_cfg.dest_id); \
+	MC_RSP_OP(cmd, 0, 32, 8,  uint8_t,  attr->dest_cfg.priority);\
+	MC_RSP_OP(cmd, 0, 40, 2,  enum dpni_dest, attr->dest_cfg.dest_type); \
+	MC_RSP_OP(cmd, 0, 42, 1,  int,      attr->order_preservation_en);\
+	MC_RSP_OP(cmd, 1, 0,  64, uint64_t, attr->user_ctx); \
+	MC_RSP_OP(cmd, 2, 0,  32, uint32_t, attr->tail_drop_threshold); \
+	MC_RSP_OP(cmd, 2, 32, 32, uint32_t, attr->fqid); \
+	MC_RSP_OP(cmd, 3, 0,  4,  enum dpni_flc_type, attr->flc_cfg.flc_type); \
+	MC_RSP_OP(cmd, 3, 4,  4,  enum dpni_stash_size, \
+		attr->flc_cfg.frame_data_size);\
+	MC_RSP_OP(cmd, 3, 8,  4,  enum dpni_stash_size, \
+		attr->flc_cfg.flow_context_size);\
+	MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->flc_cfg.options);\
+	MC_RSP_OP(cmd, 4, 0,  64, uint64_t, attr->flc_cfg.flow_context);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_RX_ERR_QUEUE(cmd, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  32, int,      cfg->dest_cfg.dest_id); \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  cfg->dest_cfg.priority);\
+	MC_CMD_OP(cmd, 0, 40, 2,  enum dpni_dest, cfg->dest_cfg.dest_type);\
+	MC_CMD_OP(cmd, 0, 42, 1,  int,      cfg->order_preservation_en);\
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, cfg->user_ctx); \
+	MC_CMD_OP(cmd, 2, 0,  32, uint32_t, cfg->options); \
+	MC_CMD_OP(cmd, 2, 32, 32, uint32_t, cfg->tail_drop_threshold); \
+	MC_CMD_OP(cmd, 3, 0,  4,  enum dpni_flc_type, cfg->flc_cfg.flc_type); \
+	MC_CMD_OP(cmd, 3, 4,  4,  enum dpni_stash_size, \
+		cfg->flc_cfg.frame_data_size);\
+	MC_CMD_OP(cmd, 3, 8,  4,  enum dpni_stash_size, \
+		cfg->flc_cfg.flow_context_size);\
+	MC_CMD_OP(cmd, 3, 32, 32, uint32_t, cfg->flc_cfg.options);\
+	MC_CMD_OP(cmd, 4, 0,  64, uint64_t, cfg->flc_cfg.flow_context);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_RX_ERR_QUEUE(cmd, attr) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  32, int,      attr->dest_cfg.dest_id); \
+	MC_RSP_OP(cmd, 0, 32, 8,  uint8_t,  attr->dest_cfg.priority);\
+	MC_RSP_OP(cmd, 0, 40, 2,  enum dpni_dest, attr->dest_cfg.dest_type);\
+	MC_RSP_OP(cmd, 0, 42, 1,  int,      attr->order_preservation_en);\
+	MC_RSP_OP(cmd, 1, 0,  64, uint64_t, attr->user_ctx); \
+	MC_RSP_OP(cmd, 2, 0,  32, uint32_t, attr->tail_drop_threshold); \
+	MC_RSP_OP(cmd, 2, 32, 32, uint32_t, attr->fqid); \
+	MC_RSP_OP(cmd, 3, 0,  4,  enum dpni_flc_type, attr->flc_cfg.flc_type); \
+	MC_RSP_OP(cmd, 3, 4,  4,  enum dpni_stash_size, \
+		attr->flc_cfg.frame_data_size);\
+	MC_RSP_OP(cmd, 3, 8,  4,  enum dpni_stash_size, \
+		attr->flc_cfg.flow_context_size);\
+	MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->flc_cfg.options);\
+	MC_RSP_OP(cmd, 4, 0,  64, uint64_t, attr->flc_cfg.flow_context);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_TX_CONF_REVOKE(cmd, revoke) \
+	MC_CMD_OP(cmd, 0, 0,  1,  int,      revoke)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_QOS_TABLE(cmd, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t,  cfg->default_tc); \
+	MC_CMD_OP(cmd, 0, 40, 1,  int,	    cfg->discard_on_miss); \
+	MC_CMD_OP(cmd, 6, 0,  64, uint64_t, cfg->key_cfg_iova); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_ADD_QOS_ENTRY(cmd, cfg, tc_id) \
+do { \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  tc_id); \
+	MC_CMD_OP(cmd, 0, 24, 8,  uint8_t,  cfg->key_size); \
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, cfg->key_iova); \
+	MC_CMD_OP(cmd, 2, 0,  64, uint64_t, cfg->mask_iova); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_REMOVE_QOS_ENTRY(cmd, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 24, 8,  uint8_t,  cfg->key_size); \
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, cfg->key_iova); \
+	MC_CMD_OP(cmd, 2, 0,  64, uint64_t, cfg->mask_iova); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_ADD_FS_ENTRY(cmd, tc_id, cfg, flow_id) \
+do { \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  tc_id); \
+	MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \
+	MC_CMD_OP(cmd, 0, 24, 8,  uint8_t,  cfg->key_size); \
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, cfg->key_iova); \
+	MC_CMD_OP(cmd, 2, 0,  64, uint64_t, cfg->mask_iova); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_REMOVE_FS_ENTRY(cmd, tc_id, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  tc_id); \
+	MC_CMD_OP(cmd, 0, 24, 8,  uint8_t,  cfg->key_size); \
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, cfg->key_iova); \
+	MC_CMD_OP(cmd, 2, 0,  64, uint64_t, cfg->mask_iova); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_CLEAR_FS_ENTRIES(cmd, tc_id) \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  tc_id)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_VLAN_INSERTION(cmd, en) \
+	MC_CMD_OP(cmd, 0, 0,  1,  int,	    en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_VLAN_REMOVAL(cmd, en) \
+	MC_CMD_OP(cmd, 0, 0,  1,  int,	    en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_IPR(cmd, en) \
+	MC_CMD_OP(cmd, 0, 0,  1,  int,	    en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_IPF(cmd, en) \
+	MC_CMD_OP(cmd, 0, 0,  1,  int,	    en)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_RX_TC_POLICING(cmd, tc_id, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  4, enum dpni_policer_mode, cfg->mode); \
+	MC_CMD_OP(cmd, 0, 4,  4, enum dpni_policer_color, cfg->default_color); \
+	MC_CMD_OP(cmd, 0, 8,  4, enum dpni_policer_unit, cfg->units); \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  tc_id); \
+	MC_CMD_OP(cmd, 0, 32, 32, uint32_t, cfg->options); \
+	MC_CMD_OP(cmd, 1, 0,  32, uint32_t, cfg->cir); \
+	MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs); \
+	MC_CMD_OP(cmd, 2, 0,  32, uint32_t, cfg->eir); \
+	MC_CMD_OP(cmd, 2, 32, 32, uint32_t, cfg->ebs);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_GET_RX_TC_POLICING(cmd, tc_id) \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  tc_id)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_RSP_GET_RX_TC_POLICING(cmd, cfg) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  4, enum dpni_policer_mode, cfg->mode); \
+	MC_RSP_OP(cmd, 0, 4,  4, enum dpni_policer_color, cfg->default_color); \
+	MC_RSP_OP(cmd, 0, 8,  4, enum dpni_policer_unit, cfg->units); \
+	MC_RSP_OP(cmd, 0, 32, 32, uint32_t, cfg->options); \
+	MC_RSP_OP(cmd, 1, 0,  32, uint32_t, cfg->cir); \
+	MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->cbs); \
+	MC_RSP_OP(cmd, 2, 0,  32, uint32_t, cfg->eir); \
+	MC_RSP_OP(cmd, 2, 32, 32, uint32_t, cfg->ebs);\
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_PREP_EARLY_DROP(ext, cfg) \
+do { \
+	MC_PREP_OP(ext, 0, 0,  2, enum dpni_early_drop_mode, cfg->mode); \
+	MC_PREP_OP(ext, 0, 2,  2, \
+		  enum dpni_congestion_unit, cfg->units); \
+	MC_PREP_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \
+	MC_PREP_OP(ext, 1, 0,  8,  uint8_t,  cfg->green.drop_probability); \
+	MC_PREP_OP(ext, 2, 0,  64, uint64_t, cfg->green.max_threshold); \
+	MC_PREP_OP(ext, 3, 0,  64, uint64_t, cfg->green.min_threshold); \
+	MC_PREP_OP(ext, 5, 0,  8,  uint8_t,  cfg->yellow.drop_probability);\
+	MC_PREP_OP(ext, 6, 0,  64, uint64_t, cfg->yellow.max_threshold); \
+	MC_PREP_OP(ext, 7, 0,  64, uint64_t, cfg->yellow.min_threshold); \
+	MC_PREP_OP(ext, 9, 0,  8,  uint8_t,  cfg->red.drop_probability); \
+	MC_PREP_OP(ext, 10, 0,  64, uint64_t, cfg->red.max_threshold); \
+	MC_PREP_OP(ext, 11, 0,  64, uint64_t, cfg->red.min_threshold); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_EXT_EARLY_DROP(ext, cfg) \
+do { \
+	MC_EXT_OP(ext, 0, 0,  2, enum dpni_early_drop_mode, cfg->mode); \
+	MC_EXT_OP(ext, 0, 2,  2, \
+		  enum dpni_congestion_unit, cfg->units); \
+	MC_EXT_OP(ext, 0, 32, 32, uint32_t, cfg->tail_drop_threshold); \
+	MC_EXT_OP(ext, 1, 0,  8,  uint8_t,  cfg->green.drop_probability); \
+	MC_EXT_OP(ext, 2, 0,  64, uint64_t, cfg->green.max_threshold); \
+	MC_EXT_OP(ext, 3, 0,  64, uint64_t, cfg->green.min_threshold); \
+	MC_EXT_OP(ext, 5, 0,  8,  uint8_t,  cfg->yellow.drop_probability);\
+	MC_EXT_OP(ext, 6, 0,  64, uint64_t, cfg->yellow.max_threshold); \
+	MC_EXT_OP(ext, 7, 0,  64, uint64_t, cfg->yellow.min_threshold); \
+	MC_EXT_OP(ext, 9, 0,  8,  uint8_t,  cfg->red.drop_probability); \
+	MC_EXT_OP(ext, 10, 0,  64, uint64_t, cfg->red.max_threshold); \
+	MC_EXT_OP(ext, 11, 0,  64, uint64_t, cfg->red.min_threshold); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_RX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova) \
+do { \
+	MC_CMD_OP(cmd, 0, 8,  8,  uint8_t,  tc_id); \
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, early_drop_iova); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_GET_RX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova) \
+do { \
+	MC_CMD_OP(cmd, 0, 8,  8,  uint8_t,  tc_id); \
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, early_drop_iova); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_SET_TX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova) \
+do { \
+	MC_CMD_OP(cmd, 0, 8,  8,  uint8_t,  tc_id); \
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, early_drop_iova); \
+} while (0)
+
+/*                cmd, param, offset, width, type, arg_name */
+#define DPNI_CMD_GET_TX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova) \
+do { \
+	MC_CMD_OP(cmd, 0, 8,  8,  uint8_t,  tc_id); \
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, early_drop_iova); \
+} while (0)
+
+#define DPNI_CMD_SET_RX_TC_CONGESTION_NOTIFICATION(cmd, tc_id, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  2,  enum dpni_congestion_unit, cfg->units); \
+	MC_CMD_OP(cmd, 0, 4,  4,  enum dpni_dest, cfg->dest_cfg.dest_type); \
+	MC_CMD_OP(cmd, 0, 8,  8,  uint8_t,  tc_id); \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  cfg->dest_cfg.priority); \
+	MC_CMD_OP(cmd, 1, 0,  32, uint32_t, cfg->threshold_entry); \
+	MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \
+	MC_CMD_OP(cmd, 2, 0,  16, uint16_t, cfg->options); \
+	MC_CMD_OP(cmd, 2, 32, 32, int,	    cfg->dest_cfg.dest_id); \
+	MC_CMD_OP(cmd, 3, 0,  64, uint64_t, cfg->message_ctx); \
+	MC_CMD_OP(cmd, 4, 0,  64, uint64_t, cfg->message_iova); \
+} while (0)
+
+#define DPNI_CMD_GET_RX_TC_CONGESTION_NOTIFICATION(cmd, tc_id) \
+	MC_CMD_OP(cmd, 0, 8,  8,  uint8_t,  tc_id)
+
+#define DPNI_RSP_GET_RX_TC_CONGESTION_NOTIFICATION(cmd, cfg) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  2,  enum dpni_congestion_unit, cfg->units); \
+	MC_RSP_OP(cmd, 0, 4,  4,  enum dpni_dest, cfg->dest_cfg.dest_type); \
+	MC_RSP_OP(cmd, 0, 16, 8,  uint8_t,  cfg->dest_cfg.priority); \
+	MC_RSP_OP(cmd, 1, 0,  32, uint32_t, cfg->threshold_entry); \
+	MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \
+	MC_RSP_OP(cmd, 2, 0,  16, uint16_t, cfg->options); \
+	MC_RSP_OP(cmd, 2, 32, 32, int,	    cfg->dest_cfg.dest_id); \
+	MC_RSP_OP(cmd, 3, 0,  64, uint64_t, cfg->message_ctx); \
+	MC_RSP_OP(cmd, 4, 0,  64, uint64_t, cfg->message_iova); \
+} while (0)
+
+#define DPNI_CMD_SET_TX_TC_CONGESTION_NOTIFICATION(cmd, tc_id, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  2,  enum dpni_congestion_unit, cfg->units); \
+	MC_CMD_OP(cmd, 0, 4,  4,  enum dpni_dest, cfg->dest_cfg.dest_type); \
+	MC_CMD_OP(cmd, 0, 8,  8,  uint8_t,  tc_id); \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  cfg->dest_cfg.priority); \
+	MC_CMD_OP(cmd, 1, 0,  32, uint32_t, cfg->threshold_entry); \
+	MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \
+	MC_CMD_OP(cmd, 2, 0,  16, uint16_t, cfg->options); \
+	MC_CMD_OP(cmd, 2, 32, 32, int,	    cfg->dest_cfg.dest_id); \
+	MC_CMD_OP(cmd, 3, 0,  64, uint64_t, cfg->message_ctx); \
+	MC_CMD_OP(cmd, 4, 0,  64, uint64_t, cfg->message_iova); \
+} while (0)
+
+#define DPNI_CMD_GET_TX_TC_CONGESTION_NOTIFICATION(cmd, tc_id) \
+	MC_CMD_OP(cmd, 0, 8,  8,  uint8_t,  tc_id)
+
+#define DPNI_RSP_GET_TX_TC_CONGESTION_NOTIFICATION(cmd, cfg) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  2,  enum dpni_congestion_unit, cfg->units); \
+	MC_RSP_OP(cmd, 0, 4,  4,  enum dpni_dest, cfg->dest_cfg.dest_type); \
+	MC_RSP_OP(cmd, 0, 16, 8,  uint8_t,  cfg->dest_cfg.priority); \
+	MC_RSP_OP(cmd, 1, 0,  32, uint32_t, cfg->threshold_entry); \
+	MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \
+	MC_RSP_OP(cmd, 2, 0,  16, uint16_t, cfg->options); \
+	MC_RSP_OP(cmd, 2, 32, 32, int,	    cfg->dest_cfg.dest_id); \
+	MC_RSP_OP(cmd, 3, 0,  64, uint64_t, cfg->message_ctx); \
+	MC_RSP_OP(cmd, 4, 0,  64, uint64_t, cfg->message_iova); \
+} while (0)
+
+#define DPNI_CMD_SET_TX_CONF(cmd, flow_id, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 32, 8,  uint8_t, cfg->queue_cfg.dest_cfg.priority); \
+	MC_CMD_OP(cmd, 0, 40, 2,  enum dpni_dest, \
+		cfg->queue_cfg.dest_cfg.dest_type); \
+	MC_CMD_OP(cmd, 0, 42, 1,  int, cfg->errors_only); \
+	MC_CMD_OP(cmd, 0, 46, 1,  int, cfg->queue_cfg.order_preservation_en); \
+	MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \
+	MC_CMD_OP(cmd, 1, 0,  64, uint64_t, cfg->queue_cfg.user_ctx); \
+	MC_CMD_OP(cmd, 2, 0,  32, uint32_t, cfg->queue_cfg.options); \
+	MC_CMD_OP(cmd, 2, 32, 32, int,	    cfg->queue_cfg.dest_cfg.dest_id); \
+	MC_CMD_OP(cmd, 3, 0,  32, uint32_t, \
+		cfg->queue_cfg.tail_drop_threshold); \
+	MC_CMD_OP(cmd, 4, 0,  4,  enum dpni_flc_type, \
+		cfg->queue_cfg.flc_cfg.flc_type); \
+	MC_CMD_OP(cmd, 4, 4,  4,  enum dpni_stash_size, \
+		cfg->queue_cfg.flc_cfg.frame_data_size); \
+	MC_CMD_OP(cmd, 4, 8,  4,  enum dpni_stash_size, \
+		cfg->queue_cfg.flc_cfg.flow_context_size); \
+	MC_CMD_OP(cmd, 4, 32, 32, uint32_t, cfg->queue_cfg.flc_cfg.options); \
+	MC_CMD_OP(cmd, 5, 0,  64, uint64_t, \
+		cfg->queue_cfg.flc_cfg.flow_context); \
+} while (0)
+
+#define DPNI_CMD_GET_TX_CONF(cmd, flow_id) \
+		MC_CMD_OP(cmd, 0, 48, 16, uint16_t,  flow_id)
+
+#define DPNI_RSP_GET_TX_CONF(cmd, attr) \
+do { \
+	MC_RSP_OP(cmd, 0, 32, 8,  uint8_t, \
+		  attr->queue_attr.dest_cfg.priority); \
+	MC_RSP_OP(cmd, 0, 40, 2,  enum dpni_dest, \
+		attr->queue_attr.dest_cfg.dest_type); \
+	MC_RSP_OP(cmd, 0, 42, 1,  int, attr->errors_only); \
+	MC_RSP_OP(cmd, 0, 46, 1,  int, \
+		  attr->queue_attr.order_preservation_en); \
+	MC_RSP_OP(cmd, 1, 0,  64, uint64_t, attr->queue_attr.user_ctx); \
+	MC_RSP_OP(cmd, 2, 32, 32, int,	attr->queue_attr.dest_cfg.dest_id); \
+	MC_RSP_OP(cmd, 3, 0,  32, uint32_t, \
+		attr->queue_attr.tail_drop_threshold); \
+	MC_RSP_OP(cmd, 3, 32, 32, uint32_t, attr->queue_attr.fqid); \
+	MC_RSP_OP(cmd, 4, 0,  4,  enum dpni_flc_type, \
+		attr->queue_attr.flc_cfg.flc_type); \
+	MC_RSP_OP(cmd, 4, 4,  4,  enum dpni_stash_size, \
+		attr->queue_attr.flc_cfg.frame_data_size); \
+	MC_RSP_OP(cmd, 4, 8,  4,  enum dpni_stash_size, \
+		attr->queue_attr.flc_cfg.flow_context_size); \
+	MC_RSP_OP(cmd, 4, 32, 32, uint32_t, attr->queue_attr.flc_cfg.options); \
+	MC_RSP_OP(cmd, 5, 0,  64, uint64_t, \
+		attr->queue_attr.flc_cfg.flow_context); \
+} while (0)
+
+#define DPNI_CMD_SET_TX_CONF_CONGESTION_NOTIFICATION(cmd, flow_id, cfg) \
+do { \
+	MC_CMD_OP(cmd, 0, 0,  2,  enum dpni_congestion_unit, cfg->units); \
+	MC_CMD_OP(cmd, 0, 4,  4,  enum dpni_dest, cfg->dest_cfg.dest_type); \
+	MC_CMD_OP(cmd, 0, 16, 8,  uint8_t,  cfg->dest_cfg.priority); \
+	MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id); \
+	MC_CMD_OP(cmd, 1, 0,  32, uint32_t, cfg->threshold_entry); \
+	MC_CMD_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \
+	MC_CMD_OP(cmd, 2, 0,  16, uint16_t, cfg->options); \
+	MC_CMD_OP(cmd, 2, 32, 32, int,	    cfg->dest_cfg.dest_id); \
+	MC_CMD_OP(cmd, 3, 0,  64, uint64_t, cfg->message_ctx); \
+	MC_CMD_OP(cmd, 4, 0,  64, uint64_t, cfg->message_iova); \
+} while (0)
+
+#define DPNI_CMD_GET_TX_CONF_CONGESTION_NOTIFICATION(cmd, flow_id) \
+	MC_CMD_OP(cmd, 0, 48, 16, uint16_t, flow_id)
+
+#define DPNI_RSP_GET_TX_CONF_CONGESTION_NOTIFICATION(cmd, cfg) \
+do { \
+	MC_RSP_OP(cmd, 0, 0,  2,  enum dpni_congestion_unit, cfg->units); \
+	MC_RSP_OP(cmd, 0, 4,  4,  enum dpni_dest, cfg->dest_cfg.dest_type); \
+	MC_RSP_OP(cmd, 0, 16, 8,  uint8_t,  cfg->dest_cfg.priority); \
+	MC_RSP_OP(cmd, 1, 0,  32, uint32_t, cfg->threshold_entry); \
+	MC_RSP_OP(cmd, 1, 32, 32, uint32_t, cfg->threshold_exit); \
+	MC_RSP_OP(cmd, 2, 0,  16, uint16_t, cfg->options); \
+	MC_RSP_OP(cmd, 2, 32, 32, int,	    cfg->dest_cfg.dest_id); \
+	MC_RSP_OP(cmd, 3, 0,  64, uint64_t, cfg->message_ctx); \
+	MC_RSP_OP(cmd, 4, 0,  64, uint64_t, cfg->message_iova); \
+} while (0)
+
+#endif /* _FSL_DPNI_CMD_H */
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.c
@@ -0,0 +1,1907 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "../../fsl-mc/include/mc-sys.h"
+#include "../../fsl-mc/include/mc-cmd.h"
+#include "dpni.h"
+#include "dpni-cmd.h"
+
+int dpni_prepare_key_cfg(const struct dpkg_profile_cfg *cfg,
+			 uint8_t *key_cfg_buf)
+{
+	int i, j;
+	int offset = 0;
+	int param = 1;
+	uint64_t *params = (uint64_t *)key_cfg_buf;
+
+	if (!key_cfg_buf || !cfg)
+			return -EINVAL;
+
+	params[0] |= mc_enc(0, 8, cfg->num_extracts);
+	params[0] = cpu_to_le64(params[0]);
+
+	if (cfg->num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS)
+		return -EINVAL;
+
+	for (i = 0; i < cfg->num_extracts; i++) {
+		switch (cfg->extracts[i].type) {
+		case DPKG_EXTRACT_FROM_HDR:
+			params[param] |= mc_enc(0, 8,
+					cfg->extracts[i].extract.from_hdr.prot);
+			params[param] |= mc_enc(8, 4,
+					cfg->extracts[i].extract.from_hdr.type);
+			params[param] |= mc_enc(16, 8,
+					cfg->extracts[i].extract.from_hdr.size);
+			params[param] |= mc_enc(24, 8,
+					cfg->extracts[i].extract.
+					from_hdr.offset);
+			params[param] |= mc_enc(32, 32,
+					cfg->extracts[i].extract.
+					from_hdr.field);
+			params[param] = cpu_to_le64(params[param]);
+			param++;
+			params[param] |= mc_enc(0, 8,
+					cfg->extracts[i].extract.
+					from_hdr.hdr_index);
+			break;
+		case DPKG_EXTRACT_FROM_DATA:
+			params[param] |= mc_enc(16, 8,
+					cfg->extracts[i].extract.
+					from_data.size);
+			params[param] |= mc_enc(24, 8,
+					cfg->extracts[i].extract.
+					from_data.offset);
+			params[param] = cpu_to_le64(params[param]);
+			param++;
+			break;
+		case DPKG_EXTRACT_FROM_PARSE:
+			params[param] |= mc_enc(16, 8,
+					cfg->extracts[i].extract.
+					from_parse.size);
+			params[param] |= mc_enc(24, 8,
+					cfg->extracts[i].extract.
+					from_parse.offset);
+			params[param] = cpu_to_le64(params[param]);
+			param++;
+			break;
+		default:
+			return -EINVAL;
+		}
+		params[param] |= mc_enc(
+			24, 8, cfg->extracts[i].num_of_byte_masks);
+		params[param] |= mc_enc(32, 4, cfg->extracts[i].type);
+		params[param] = cpu_to_le64(params[param]);
+		param++;
+		for (offset = 0, j = 0;
+			j < DPKG_NUM_OF_MASKS;
+			offset += 16, j++) {
+			params[param] |= mc_enc(
+				(offset), 8, cfg->extracts[i].masks[j].mask);
+			params[param] |= mc_enc(
+				(offset + 8), 8,
+				cfg->extracts[i].masks[j].offset);
+		}
+		params[param] = cpu_to_le64(params[param]);
+		param++;
+	}
+	return 0;
+}
+
+int dpni_prepare_extended_cfg(const struct dpni_extended_cfg	*cfg,
+			      uint8_t			*ext_cfg_buf)
+{
+	uint64_t *ext_params = (uint64_t *)ext_cfg_buf;
+
+	DPNI_PREP_EXTENDED_CFG(ext_params, cfg);
+
+	return 0;
+}
+
+int dpni_extract_extended_cfg(struct dpni_extended_cfg	*cfg,
+			      const uint8_t		*ext_cfg_buf)
+{
+	uint64_t *ext_params = (uint64_t *)ext_cfg_buf;
+
+	DPNI_EXT_EXTENDED_CFG(ext_params, cfg);
+
+	return 0;
+}
+
+int dpni_open(struct fsl_mc_io *mc_io,
+	      uint32_t cmd_flags,
+	      int dpni_id,
+	      uint16_t *token)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_OPEN,
+					  cmd_flags,
+					  0);
+	DPNI_CMD_OPEN(cmd, dpni_id);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	*token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+
+	return 0;
+}
+
+int dpni_close(struct fsl_mc_io *mc_io,
+	       uint32_t cmd_flags,
+	       uint16_t token)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLOSE,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_create(struct fsl_mc_io *mc_io,
+		uint32_t cmd_flags,
+		const struct dpni_cfg *cfg,
+		uint16_t *token)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_CREATE,
+					  cmd_flags,
+					  0);
+	DPNI_CMD_CREATE(cmd, cfg);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	*token = MC_CMD_HDR_READ_TOKEN(cmd.header);
+
+	return 0;
+}
+
+int dpni_destroy(struct fsl_mc_io *mc_io,
+		 uint32_t cmd_flags,
+		 uint16_t token)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_DESTROY,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_pools(struct fsl_mc_io *mc_io,
+		   uint32_t cmd_flags,
+		   uint16_t token,
+		   const struct dpni_pools_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_POOLS,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_POOLS(cmd, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_enable(struct fsl_mc_io *mc_io,
+		uint32_t cmd_flags,
+		uint16_t token)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_ENABLE,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_disable(struct fsl_mc_io *mc_io,
+		 uint32_t cmd_flags,
+		 uint16_t token)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_DISABLE,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_is_enabled(struct fsl_mc_io *mc_io,
+		    uint32_t cmd_flags,
+		    uint16_t token,
+		    int *en)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_IS_ENABLED, cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_IS_ENABLED(cmd, *en);
+
+	return 0;
+}
+
+int dpni_reset(struct fsl_mc_io *mc_io,
+	       uint32_t cmd_flags,
+	       uint16_t token)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_irq(struct fsl_mc_io	*mc_io,
+		 uint32_t		cmd_flags,
+		 uint16_t		token,
+		 uint8_t		irq_index,
+		 struct dpni_irq_cfg	*irq_cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IRQ,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_IRQ(cmd, irq_index, irq_cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_irq(struct fsl_mc_io	*mc_io,
+		 uint32_t		cmd_flags,
+		 uint16_t		token,
+		 uint8_t		irq_index,
+		 int			*type,
+		 struct dpni_irq_cfg	*irq_cfg)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_GET_IRQ(cmd, irq_index);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_IRQ(cmd, *type, irq_cfg);
+
+	return 0;
+}
+
+int dpni_set_irq_enable(struct fsl_mc_io *mc_io,
+			uint32_t cmd_flags,
+			uint16_t token,
+			uint8_t irq_index,
+			uint8_t en)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IRQ_ENABLE,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_IRQ_ENABLE(cmd, irq_index, en);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_irq_enable(struct fsl_mc_io *mc_io,
+			uint32_t cmd_flags,
+			uint16_t token,
+			uint8_t irq_index,
+			uint8_t *en)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_ENABLE,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_GET_IRQ_ENABLE(cmd, irq_index);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_IRQ_ENABLE(cmd, *en);
+
+	return 0;
+}
+
+int dpni_set_irq_mask(struct fsl_mc_io *mc_io,
+		      uint32_t cmd_flags,
+		      uint16_t token,
+		      uint8_t irq_index,
+		      uint32_t mask)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IRQ_MASK,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_IRQ_MASK(cmd, irq_index, mask);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_irq_mask(struct fsl_mc_io *mc_io,
+		      uint32_t cmd_flags,
+		      uint16_t token,
+		      uint8_t irq_index,
+		      uint32_t *mask)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_MASK,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_GET_IRQ_MASK(cmd, irq_index);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_IRQ_MASK(cmd, *mask);
+
+	return 0;
+}
+
+int dpni_get_irq_status(struct fsl_mc_io *mc_io,
+			uint32_t cmd_flags,
+			uint16_t token,
+			uint8_t irq_index,
+			uint32_t *status)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_STATUS,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_GET_IRQ_STATUS(cmd, irq_index, *status);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_IRQ_STATUS(cmd, *status);
+
+	return 0;
+}
+
+int dpni_clear_irq_status(struct fsl_mc_io *mc_io,
+			  uint32_t cmd_flags,
+			  uint16_t token,
+			  uint8_t irq_index,
+			  uint32_t status)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLEAR_IRQ_STATUS,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_attributes(struct fsl_mc_io *mc_io,
+			uint32_t cmd_flags,
+			uint16_t token,
+			struct dpni_attr *attr)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_ATTR,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_GET_ATTR(cmd, attr);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_ATTR(cmd, attr);
+
+	return 0;
+}
+
+int dpni_set_errors_behavior(struct fsl_mc_io *mc_io,
+			     uint32_t cmd_flags,
+			     uint16_t token,
+			      struct dpni_error_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_ERRORS_BEHAVIOR,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_ERRORS_BEHAVIOR(cmd, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_rx_buffer_layout(struct fsl_mc_io *mc_io,
+			      uint32_t cmd_flags,
+			      uint16_t token,
+			      struct dpni_buffer_layout *layout)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_BUFFER_LAYOUT,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_RX_BUFFER_LAYOUT(cmd, layout);
+
+	return 0;
+}
+
+int dpni_set_rx_buffer_layout(struct fsl_mc_io *mc_io,
+			      uint32_t cmd_flags,
+			      uint16_t token,
+			      const struct dpni_buffer_layout *layout)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_BUFFER_LAYOUT,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_RX_BUFFER_LAYOUT(cmd, layout);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_tx_buffer_layout(struct fsl_mc_io *mc_io,
+			      uint32_t cmd_flags,
+			      uint16_t token,
+			      struct dpni_buffer_layout *layout)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_BUFFER_LAYOUT,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_TX_BUFFER_LAYOUT(cmd, layout);
+
+	return 0;
+}
+
+int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io,
+			      uint32_t cmd_flags,
+			      uint16_t token,
+			      const struct dpni_buffer_layout *layout)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_BUFFER_LAYOUT,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_TX_BUFFER_LAYOUT(cmd, layout);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io,
+				   uint32_t cmd_flags,
+				   uint16_t token,
+				   struct dpni_buffer_layout *layout)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_CONF_BUFFER_LAYOUT,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_TX_CONF_BUFFER_LAYOUT(cmd, layout);
+
+	return 0;
+}
+
+int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io *mc_io,
+				   uint32_t cmd_flags,
+				   uint16_t token,
+				   const struct dpni_buffer_layout *layout)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF_BUFFER_LAYOUT,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_TX_CONF_BUFFER_LAYOUT(cmd, layout);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_l3_chksum_validation(struct fsl_mc_io *mc_io,
+				  uint32_t cmd_flags,
+				  uint16_t token,
+				  int *en)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_L3_CHKSUM_VALIDATION,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_L3_CHKSUM_VALIDATION(cmd, *en);
+
+	return 0;
+}
+
+int dpni_set_l3_chksum_validation(struct fsl_mc_io *mc_io,
+				  uint32_t cmd_flags,
+				  uint16_t token,
+				  int en)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_L3_CHKSUM_VALIDATION,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_L3_CHKSUM_VALIDATION(cmd, en);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_l4_chksum_validation(struct fsl_mc_io *mc_io,
+				  uint32_t cmd_flags,
+				  uint16_t token,
+				  int *en)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_L4_CHKSUM_VALIDATION,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_L4_CHKSUM_VALIDATION(cmd, *en);
+
+	return 0;
+}
+
+int dpni_set_l4_chksum_validation(struct fsl_mc_io *mc_io,
+				  uint32_t cmd_flags,
+				  uint16_t token,
+				  int en)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_L4_CHKSUM_VALIDATION,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_L4_CHKSUM_VALIDATION(cmd, en);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_qdid(struct fsl_mc_io *mc_io,
+		  uint32_t cmd_flags,
+		  uint16_t token,
+		  uint16_t *qdid)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_QDID,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_QDID(cmd, *qdid);
+
+	return 0;
+}
+
+int dpni_get_sp_info(struct fsl_mc_io *mc_io,
+		     uint32_t cmd_flags,
+		     uint16_t token,
+		     struct dpni_sp_info *sp_info)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_SP_INFO,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_SP_INFO(cmd, sp_info);
+
+	return 0;
+}
+
+int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io,
+			    uint32_t cmd_flags,
+			    uint16_t token,
+			    uint16_t *data_offset)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_DATA_OFFSET,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_TX_DATA_OFFSET(cmd, *data_offset);
+
+	return 0;
+}
+
+int dpni_get_counter(struct fsl_mc_io *mc_io,
+		     uint32_t cmd_flags,
+		     uint16_t token,
+		     enum dpni_counter counter,
+		     uint64_t *value)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_COUNTER,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_GET_COUNTER(cmd, counter);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_COUNTER(cmd, *value);
+
+	return 0;
+}
+
+int dpni_set_counter(struct fsl_mc_io *mc_io,
+		     uint32_t cmd_flags,
+		     uint16_t token,
+		     enum dpni_counter counter,
+		     uint64_t value)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_COUNTER,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_COUNTER(cmd, counter, value);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_link_cfg(struct fsl_mc_io *mc_io,
+		      uint32_t cmd_flags,
+		      uint16_t token,
+		      const struct dpni_link_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_LINK_CFG,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_LINK_CFG(cmd, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_link_state(struct fsl_mc_io *mc_io,
+			uint32_t cmd_flags,
+			uint16_t token,
+			struct dpni_link_state *state)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_LINK_STATE,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_LINK_STATE(cmd, state);
+
+	return 0;
+}
+
+int dpni_set_tx_shaping(struct fsl_mc_io *mc_io,
+			uint32_t cmd_flags,
+			uint16_t token,
+			const struct dpni_tx_shaping_cfg *tx_shaper)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_SHAPING,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_TX_SHAPING(cmd, tx_shaper);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_max_frame_length(struct fsl_mc_io *mc_io,
+			      uint32_t cmd_flags,
+			      uint16_t token,
+			      uint16_t max_frame_length)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_MAX_FRAME_LENGTH,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_MAX_FRAME_LENGTH(cmd, max_frame_length);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_max_frame_length(struct fsl_mc_io *mc_io,
+			      uint32_t cmd_flags,
+			      uint16_t token,
+			      uint16_t *max_frame_length)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_MAX_FRAME_LENGTH,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_MAX_FRAME_LENGTH(cmd, *max_frame_length);
+
+	return 0;
+}
+
+int dpni_set_mtu(struct fsl_mc_io *mc_io,
+		 uint32_t cmd_flags,
+		 uint16_t token,
+		 uint16_t mtu)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_MTU,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_MTU(cmd, mtu);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_mtu(struct fsl_mc_io *mc_io,
+		 uint32_t cmd_flags,
+		 uint16_t token,
+		 uint16_t *mtu)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_MTU,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_MTU(cmd, *mtu);
+
+	return 0;
+}
+
+int dpni_set_multicast_promisc(struct fsl_mc_io *mc_io,
+			       uint32_t cmd_flags,
+			       uint16_t token,
+			       int en)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_MCAST_PROMISC,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_MULTICAST_PROMISC(cmd, en);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_multicast_promisc(struct fsl_mc_io *mc_io,
+			       uint32_t cmd_flags,
+			       uint16_t token,
+			       int *en)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_MCAST_PROMISC,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_MULTICAST_PROMISC(cmd, *en);
+
+	return 0;
+}
+
+int dpni_set_unicast_promisc(struct fsl_mc_io *mc_io,
+			     uint32_t cmd_flags,
+			     uint16_t token,
+			     int en)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_UNICAST_PROMISC,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_UNICAST_PROMISC(cmd, en);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_unicast_promisc(struct fsl_mc_io *mc_io,
+			     uint32_t cmd_flags,
+			     uint16_t token,
+			     int *en)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_UNICAST_PROMISC,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_UNICAST_PROMISC(cmd, *en);
+
+	return 0;
+}
+
+int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io,
+			      uint32_t cmd_flags,
+			      uint16_t token,
+			      const uint8_t mac_addr[6])
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_PRIM_MAC,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_PRIMARY_MAC_ADDR(cmd, mac_addr);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io,
+			      uint32_t cmd_flags,
+			      uint16_t token,
+			      uint8_t mac_addr[6])
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_PRIM_MAC,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_PRIMARY_MAC_ADDR(cmd, mac_addr);
+
+	return 0;
+}
+
+int dpni_add_mac_addr(struct fsl_mc_io *mc_io,
+		      uint32_t cmd_flags,
+		      uint16_t token,
+		      const uint8_t mac_addr[6])
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_MAC_ADDR,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_ADD_MAC_ADDR(cmd, mac_addr);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_remove_mac_addr(struct fsl_mc_io *mc_io,
+			 uint32_t cmd_flags,
+			 uint16_t token,
+			 const uint8_t mac_addr[6])
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_MAC_ADDR,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_REMOVE_MAC_ADDR(cmd, mac_addr);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_clear_mac_filters(struct fsl_mc_io *mc_io,
+			   uint32_t cmd_flags,
+			   uint16_t token,
+			   int unicast,
+			   int multicast)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_MAC_FILTERS,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_CLEAR_MAC_FILTERS(cmd, unicast, multicast);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_vlan_filters(struct fsl_mc_io *mc_io,
+			  uint32_t cmd_flags,
+			  uint16_t token,
+			  int en)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_VLAN_FILTERS,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_VLAN_FILTERS(cmd, en);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_add_vlan_id(struct fsl_mc_io *mc_io,
+		     uint32_t cmd_flags,
+		     uint16_t token,
+		     uint16_t vlan_id)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_VLAN_ID,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_ADD_VLAN_ID(cmd, vlan_id);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_remove_vlan_id(struct fsl_mc_io *mc_io,
+			uint32_t cmd_flags,
+			uint16_t token,
+			uint16_t vlan_id)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_VLAN_ID,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_REMOVE_VLAN_ID(cmd, vlan_id);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_clear_vlan_filters(struct fsl_mc_io *mc_io,
+			    uint32_t cmd_flags,
+			    uint16_t token)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_VLAN_FILTERS,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_tx_selection(struct fsl_mc_io			*mc_io,
+			  uint32_t				cmd_flags,
+			  uint16_t				token,
+			  const struct dpni_tx_selection_cfg	*cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_SELECTION,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_TX_SELECTION(cmd, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io,
+			uint32_t cmd_flags,
+			uint16_t token,
+			uint8_t tc_id,
+			const struct dpni_rx_tc_dist_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_TC_DIST,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_RX_TC_DIST(cmd, tc_id, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_tx_flow(struct fsl_mc_io *mc_io,
+		     uint32_t cmd_flags,
+		     uint16_t token,
+		     uint16_t *flow_id,
+		     const struct dpni_tx_flow_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_FLOW,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_TX_FLOW(cmd, *flow_id, cfg);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_SET_TX_FLOW(cmd, *flow_id);
+
+	return 0;
+}
+
+int dpni_get_tx_flow(struct fsl_mc_io *mc_io,
+		     uint32_t cmd_flags,
+		     uint16_t token,
+		     uint16_t flow_id,
+		     struct dpni_tx_flow_attr *attr)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_FLOW,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_GET_TX_FLOW(cmd, flow_id);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_TX_FLOW(cmd, attr);
+
+	return 0;
+}
+
+int dpni_set_rx_flow(struct fsl_mc_io *mc_io,
+		     uint32_t cmd_flags,
+		     uint16_t token,
+		     uint8_t tc_id,
+		     uint16_t flow_id,
+		     const struct dpni_queue_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_FLOW,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_RX_FLOW(cmd, tc_id, flow_id, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_rx_flow(struct fsl_mc_io *mc_io,
+		     uint32_t cmd_flags,
+		     uint16_t token,
+		     uint8_t tc_id,
+		     uint16_t flow_id,
+		     struct dpni_queue_attr *attr)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_FLOW,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_GET_RX_FLOW(cmd, tc_id, flow_id);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_RX_FLOW(cmd, attr);
+
+	return 0;
+}
+
+int dpni_set_rx_err_queue(struct fsl_mc_io *mc_io,
+			  uint32_t cmd_flags,
+			  uint16_t token,
+			  const struct dpni_queue_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_ERR_QUEUE,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_RX_ERR_QUEUE(cmd, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_rx_err_queue(struct fsl_mc_io *mc_io,
+			  uint32_t cmd_flags,
+			  uint16_t token,
+			  struct dpni_queue_attr *attr)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_ERR_QUEUE,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	/* retrieve response parameters */
+	DPNI_RSP_GET_RX_ERR_QUEUE(cmd, attr);
+
+	return 0;
+}
+
+int dpni_set_tx_conf_revoke(struct fsl_mc_io	*mc_io,
+			    uint32_t		cmd_flags,
+			    uint16_t		token,
+			    int		revoke)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF_REVOKE,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_TX_CONF_REVOKE(cmd, revoke);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_qos_table(struct fsl_mc_io *mc_io,
+		       uint32_t cmd_flags,
+		       uint16_t token,
+		       const struct dpni_qos_tbl_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_QOS_TBL,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_QOS_TABLE(cmd, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_add_qos_entry(struct fsl_mc_io *mc_io,
+		       uint32_t cmd_flags,
+		       uint16_t token,
+		       const struct dpni_rule_cfg *cfg,
+		       uint8_t tc_id)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_QOS_ENT,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_ADD_QOS_ENTRY(cmd, cfg, tc_id);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_remove_qos_entry(struct fsl_mc_io *mc_io,
+			  uint32_t cmd_flags,
+			  uint16_t token,
+			  const struct dpni_rule_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_QOS_ENT,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_REMOVE_QOS_ENTRY(cmd, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_clear_qos_table(struct fsl_mc_io *mc_io,
+			 uint32_t cmd_flags,
+			 uint16_t token)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_QOS_TBL,
+					  cmd_flags,
+					  token);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_add_fs_entry(struct fsl_mc_io *mc_io,
+		      uint32_t cmd_flags,
+		      uint16_t token,
+		      uint8_t tc_id,
+		      const struct dpni_rule_cfg *cfg,
+		      uint16_t flow_id)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_ADD_FS_ENTRY(cmd, tc_id, cfg, flow_id);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_remove_fs_entry(struct fsl_mc_io *mc_io,
+			 uint32_t cmd_flags,
+			 uint16_t token,
+			 uint8_t tc_id,
+			 const struct dpni_rule_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_FS_ENT,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_REMOVE_FS_ENTRY(cmd, tc_id, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_clear_fs_entries(struct fsl_mc_io *mc_io,
+			  uint32_t cmd_flags,
+			  uint16_t token,
+			  uint8_t tc_id)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_FS_ENT,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_CLEAR_FS_ENTRIES(cmd, tc_id);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_vlan_insertion(struct fsl_mc_io *mc_io,
+			    uint32_t cmd_flags,
+			    uint16_t token,
+			    int en)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_VLAN_INSERTION,
+					  cmd_flags, token);
+	DPNI_CMD_SET_VLAN_INSERTION(cmd, en);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_vlan_removal(struct fsl_mc_io *mc_io,
+			  uint32_t cmd_flags,
+			  uint16_t token,
+			  int en)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_VLAN_REMOVAL,
+					  cmd_flags, token);
+	DPNI_CMD_SET_VLAN_REMOVAL(cmd, en);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_ipr(struct fsl_mc_io *mc_io,
+		 uint32_t cmd_flags,
+		 uint16_t token,
+		 int en)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IPR,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_IPR(cmd, en);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_ipf(struct fsl_mc_io *mc_io,
+		 uint32_t cmd_flags,
+		 uint16_t token,
+		 int en)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IPF,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_IPF(cmd, en);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_rx_tc_policing(struct fsl_mc_io	*mc_io,
+			    uint32_t		cmd_flags,
+			    uint16_t		token,
+			    uint8_t		tc_id,
+			    const struct dpni_rx_tc_policing_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_TC_POLICING,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_RX_TC_POLICING(cmd, tc_id, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_rx_tc_policing(struct fsl_mc_io			*mc_io,
+			    uint32_t				cmd_flags,
+			    uint16_t				token,
+			    uint8_t				tc_id,
+			    struct dpni_rx_tc_policing_cfg	*cfg)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_TC_POLICING,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_GET_RX_TC_POLICING(cmd, tc_id);
+
+	/* send command to mc*/
+	err =  mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	DPNI_RSP_GET_RX_TC_POLICING(cmd, cfg);
+
+	return 0;
+}
+
+void dpni_prepare_early_drop(const struct dpni_early_drop_cfg *cfg,
+			     uint8_t *early_drop_buf)
+{
+	uint64_t *ext_params = (uint64_t *)early_drop_buf;
+
+	DPNI_PREP_EARLY_DROP(ext_params, cfg);
+}
+
+void dpni_extract_early_drop(struct dpni_early_drop_cfg *cfg,
+			     const uint8_t *early_drop_buf)
+{
+	uint64_t *ext_params = (uint64_t *)early_drop_buf;
+
+	DPNI_EXT_EARLY_DROP(ext_params, cfg);
+}
+
+int dpni_set_rx_tc_early_drop(struct fsl_mc_io	*mc_io,
+			      uint32_t		cmd_flags,
+			      uint16_t		token,
+			      uint8_t		tc_id,
+			      uint64_t		early_drop_iova)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_TC_EARLY_DROP,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_RX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_rx_tc_early_drop(struct fsl_mc_io	*mc_io,
+			      uint32_t		cmd_flags,
+			      uint16_t		token,
+			      uint8_t		tc_id,
+			      uint64_t		early_drop_iova)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_TC_EARLY_DROP,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_GET_RX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_tx_tc_early_drop(struct fsl_mc_io	*mc_io,
+			      uint32_t		cmd_flags,
+			      uint16_t		token,
+			      uint8_t		tc_id,
+			      uint64_t		early_drop_iova)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_TC_EARLY_DROP,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_TX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_tx_tc_early_drop(struct fsl_mc_io	*mc_io,
+			      uint32_t		cmd_flags,
+			      uint16_t		token,
+			      uint8_t		tc_id,
+			      uint64_t		early_drop_iova)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_TC_EARLY_DROP,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_GET_TX_TC_EARLY_DROP(cmd, tc_id, early_drop_iova);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_set_rx_tc_congestion_notification(struct fsl_mc_io	*mc_io,
+					   uint32_t		cmd_flags,
+					   uint16_t		token,
+					   uint8_t		tc_id,
+			const struct dpni_congestion_notification_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(
+			DPNI_CMDID_SET_RX_TC_CONGESTION_NOTIFICATION,
+			cmd_flags,
+			token);
+	DPNI_CMD_SET_RX_TC_CONGESTION_NOTIFICATION(cmd, tc_id, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_rx_tc_congestion_notification(struct fsl_mc_io	*mc_io,
+					   uint32_t		cmd_flags,
+					   uint16_t		token,
+					   uint8_t		tc_id,
+				struct dpni_congestion_notification_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(
+			DPNI_CMDID_GET_RX_TC_CONGESTION_NOTIFICATION,
+			cmd_flags,
+			token);
+	DPNI_CMD_GET_RX_TC_CONGESTION_NOTIFICATION(cmd, tc_id);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	DPNI_RSP_GET_RX_TC_CONGESTION_NOTIFICATION(cmd, cfg);
+
+	return 0;
+}
+
+int dpni_set_tx_tc_congestion_notification(struct fsl_mc_io	*mc_io,
+					   uint32_t		cmd_flags,
+					   uint16_t		token,
+					   uint8_t		tc_id,
+			const struct dpni_congestion_notification_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(
+			DPNI_CMDID_SET_TX_TC_CONGESTION_NOTIFICATION,
+			cmd_flags,
+			token);
+	DPNI_CMD_SET_TX_TC_CONGESTION_NOTIFICATION(cmd, tc_id, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_tx_tc_congestion_notification(struct fsl_mc_io	*mc_io,
+					   uint32_t		cmd_flags,
+					   uint16_t		token,
+					   uint8_t		tc_id,
+				struct dpni_congestion_notification_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(
+			DPNI_CMDID_GET_TX_TC_CONGESTION_NOTIFICATION,
+			cmd_flags,
+			token);
+	DPNI_CMD_GET_TX_TC_CONGESTION_NOTIFICATION(cmd, tc_id);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	DPNI_RSP_GET_TX_TC_CONGESTION_NOTIFICATION(cmd, cfg);
+
+	return 0;
+}
+
+int dpni_set_tx_conf(struct fsl_mc_io	*mc_io,
+		     uint32_t		cmd_flags,
+		     uint16_t		token,
+		     uint16_t		flow_id,
+		     const struct dpni_tx_conf_cfg	*cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_SET_TX_CONF(cmd, flow_id, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_tx_conf(struct fsl_mc_io		*mc_io,
+		     uint32_t			cmd_flags,
+		     uint16_t			token,
+		     uint16_t			flow_id,
+		     struct dpni_tx_conf_attr	*attr)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_CONF,
+					  cmd_flags,
+					  token);
+	DPNI_CMD_GET_TX_CONF(cmd, flow_id);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	DPNI_RSP_GET_TX_CONF(cmd, attr);
+
+	return 0;
+}
+
+int dpni_set_tx_conf_congestion_notification(struct fsl_mc_io	*mc_io,
+					     uint32_t		cmd_flags,
+					     uint16_t		token,
+					     uint16_t		flow_id,
+			 const struct dpni_congestion_notification_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(
+			DPNI_CMDID_SET_TX_CONF_CONGESTION_NOTIFICATION,
+			cmd_flags,
+			token);
+	DPNI_CMD_SET_TX_CONF_CONGESTION_NOTIFICATION(cmd, flow_id, cfg);
+
+	/* send command to mc*/
+	return mc_send_command(mc_io, &cmd);
+}
+
+int dpni_get_tx_conf_congestion_notification(struct fsl_mc_io	*mc_io,
+					     uint32_t		cmd_flags,
+					     uint16_t		token,
+					     uint16_t		flow_id,
+				 struct dpni_congestion_notification_cfg *cfg)
+{
+	struct mc_command cmd = { 0 };
+	int err;
+
+	/* prepare command */
+	cmd.header = mc_encode_cmd_header(
+				DPNI_CMDID_GET_TX_CONF_CONGESTION_NOTIFICATION,
+				cmd_flags,
+				token);
+	DPNI_CMD_GET_TX_CONF_CONGESTION_NOTIFICATION(cmd, flow_id);
+
+	/* send command to mc*/
+	err = mc_send_command(mc_io, &cmd);
+	if (err)
+		return err;
+
+	DPNI_RSP_GET_TX_CONF_CONGESTION_NOTIFICATION(cmd, cfg);
+
+	return 0;
+}
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.h
@@ -0,0 +1,2581 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __FSL_DPNI_H
+#define __FSL_DPNI_H
+
+#include "dpkg.h"
+
+struct fsl_mc_io;
+
+/**
+ * Data Path Network Interface API
+ * Contains initialization APIs and runtime control APIs for DPNI
+ */
+
+/** General DPNI macros */
+
+/**
+ * Maximum number of traffic classes
+ */
+#define DPNI_MAX_TC				8
+/**
+ * Maximum number of buffer pools per DPNI
+ */
+#define DPNI_MAX_DPBP				8
+/**
+ * Maximum number of storage-profiles per DPNI
+ */
+#define DPNI_MAX_SP				2
+
+/**
+ * All traffic classes considered; see dpni_set_rx_flow()
+ */
+#define DPNI_ALL_TCS				(uint8_t)(-1)
+/**
+ * All flows within traffic class considered; see dpni_set_rx_flow()
+ */
+#define DPNI_ALL_TC_FLOWS			(uint16_t)(-1)
+/**
+ * Generate new flow ID; see dpni_set_tx_flow()
+ */
+#define DPNI_NEW_FLOW_ID			(uint16_t)(-1)
+/* use for common tx-conf queue; see dpni_set_tx_conf_<x>() */
+#define DPNI_COMMON_TX_CONF			(uint16_t)(-1)
+
+/**
+ * dpni_open() - Open a control session for the specified object
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @dpni_id:	DPNI unique ID
+ * @token:	Returned token; use in subsequent API calls
+ *
+ * This function can be used to open a control session for an
+ * already created object; an object may have been declared in
+ * the DPL or by calling the dpni_create() function.
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent commands for
+ * this specific object.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_open(struct fsl_mc_io	*mc_io,
+	      uint32_t		cmd_flags,
+	      int		dpni_id,
+	      uint16_t		*token);
+
+/**
+ * dpni_close() - Close the control session of the object
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ *
+ * After this function is called, no further operations are
+ * allowed on the object without opening a new control session.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_close(struct fsl_mc_io	*mc_io,
+	       uint32_t		cmd_flags,
+	       uint16_t		token);
+
+/* DPNI configuration options */
+
+/**
+ * Allow different distribution key profiles for different traffic classes;
+ * if not set, a single key profile is assumed
+ */
+#define DPNI_OPT_ALLOW_DIST_KEY_PER_TC		0x00000001
+
+/**
+ * Disable all non-error transmit confirmation; error frames are reported
+ * back to a common Tx error queue
+ */
+#define DPNI_OPT_TX_CONF_DISABLED		0x00000002
+
+/**
+ * Disable per-sender private Tx confirmation/error queue
+ */
+#define DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED	0x00000004
+
+/**
+ * Support distribution based on hashed key;
+ * allows statistical distribution over receive queues in a traffic class
+ */
+#define DPNI_OPT_DIST_HASH			0x00000010
+
+/**
+ * DEPRECATED - if this flag is selected and and all new 'max_fs_entries' are
+ * '0' then backward compatibility is preserved;
+ * Support distribution based on flow steering;
+ * allows explicit control of distribution over receive queues in a traffic
+ * class
+ */
+#define DPNI_OPT_DIST_FS			0x00000020
+
+/**
+ * Unicast filtering support
+ */
+#define DPNI_OPT_UNICAST_FILTER			0x00000080
+/**
+ * Multicast filtering support
+ */
+#define DPNI_OPT_MULTICAST_FILTER		0x00000100
+/**
+ * VLAN filtering support
+ */
+#define DPNI_OPT_VLAN_FILTER			0x00000200
+/**
+ * Support IP reassembly on received packets
+ */
+#define DPNI_OPT_IPR				0x00000800
+/**
+ * Support IP fragmentation on transmitted packets
+ */
+#define DPNI_OPT_IPF				0x00001000
+/**
+ * VLAN manipulation support
+ */
+#define DPNI_OPT_VLAN_MANIPULATION		0x00010000
+/**
+ * Support masking of QoS lookup keys
+ */
+#define DPNI_OPT_QOS_MASK_SUPPORT		0x00020000
+/**
+ * Support masking of Flow Steering lookup keys
+ */
+#define DPNI_OPT_FS_MASK_SUPPORT		0x00040000
+
+/**
+ * struct dpni_extended_cfg - Structure representing extended DPNI configuration
+ * @tc_cfg: TCs configuration
+ * @ipr_cfg: IP reassembly configuration
+ */
+struct dpni_extended_cfg {
+	/**
+	 * struct tc_cfg - TC configuration
+	 * @max_dist: Maximum distribution size for Rx traffic class;
+	 *	supported values: 1,2,3,4,6,7,8,12,14,16,24,28,32,48,56,64,96,
+	 *	112,128,192,224,256,384,448,512,768,896,1024;
+	 *	value '0' will be treated as '1'.
+	 *	other unsupported values will be round down to the nearest
+	 *	supported value.
+	 * @max_fs_entries: Maximum FS entries for Rx traffic class;
+	 *	'0' means no support for this TC;
+	 */
+	struct {
+		uint16_t	max_dist;
+		uint16_t	max_fs_entries;
+	} tc_cfg[DPNI_MAX_TC];
+	/**
+	 * struct ipr_cfg - Structure representing IP reassembly configuration
+	 * @max_reass_frm_size: Maximum size of the reassembled frame
+	 * @min_frag_size_ipv4: Minimum fragment size of IPv4 fragments
+	 * @min_frag_size_ipv6: Minimum fragment size of IPv6 fragments
+	 * @max_open_frames_ipv4: Maximum concurrent IPv4 packets in reassembly
+	 *		process
+	 * @max_open_frames_ipv6: Maximum concurrent IPv6 packets in reassembly
+	 *		process
+	 */
+	struct {
+		uint16_t max_reass_frm_size;
+		uint16_t min_frag_size_ipv4;
+		uint16_t min_frag_size_ipv6;
+		uint16_t max_open_frames_ipv4;
+		uint16_t max_open_frames_ipv6;
+	} ipr_cfg;
+};
+
+/**
+ * dpni_prepare_extended_cfg() - function prepare extended parameters
+ * @cfg: extended structure
+ * @ext_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA
+ *
+ * This function has to be called before dpni_create()
+ */
+int dpni_prepare_extended_cfg(const struct dpni_extended_cfg	*cfg,
+			      uint8_t			*ext_cfg_buf);
+
+/**
+ * struct dpni_cfg - Structure representing DPNI configuration
+ * @mac_addr: Primary MAC address
+ * @adv: Advanced parameters; default is all zeros;
+ *		use this structure to change default settings
+ */
+struct dpni_cfg {
+	uint8_t mac_addr[6];
+	/**
+	 * struct adv - Advanced parameters
+	 * @options: Mask of available options; use 'DPNI_OPT_<X>' values
+	 * @start_hdr: Selects the packet starting header for parsing;
+	 *		'NET_PROT_NONE' is treated as default: 'NET_PROT_ETH'
+	 * @max_senders: Maximum number of different senders; used as the number
+	 *		of dedicated Tx flows; Non-power-of-2 values are rounded
+	 *		up to the next power-of-2 value as hardware demands it;
+	 *		'0' will be treated as '1'
+	 * @max_tcs: Maximum number of traffic classes (for both Tx and Rx);
+	 *		'0' will e treated as '1'
+	 * @max_unicast_filters: Maximum number of unicast filters;
+	 *			'0' is treated	as '16'
+	 * @max_multicast_filters: Maximum number of multicast filters;
+	 *			'0' is treated as '64'
+	 * @max_qos_entries: if 'max_tcs > 1', declares the maximum entries in
+	 *			the QoS	table; '0' is treated as '64'
+	 * @max_qos_key_size: Maximum key size for the QoS look-up;
+	 *			'0' is treated as '24' which is enough for IPv4
+	 *			5-tuple
+	 * @max_dist_key_size: Maximum key size for the distribution;
+	 *		'0' is treated as '24' which is enough for IPv4 5-tuple
+	 * @max_policers: Maximum number of policers;
+	 *		should be between '0' and max_tcs
+	 * @max_congestion_ctrl: Maximum number of congestion control groups
+	 *		(CGs); covers early drop and congestion notification
+	 *		requirements;
+	 *		should be between '0' and ('max_tcs' + 'max_senders')
+	 * @ext_cfg_iova: I/O virtual address of 256 bytes DMA-able memory
+	 *		filled with the extended configuration by calling
+	 *		dpni_prepare_extended_cfg()
+	 */
+	struct {
+		uint32_t	options;
+		enum net_prot	start_hdr;
+		uint8_t		max_senders;
+		uint8_t		max_tcs;
+		uint8_t		max_unicast_filters;
+		uint8_t		max_multicast_filters;
+		uint8_t		max_vlan_filters;
+		uint8_t		max_qos_entries;
+		uint8_t		max_qos_key_size;
+		uint8_t		max_dist_key_size;
+		uint8_t		max_policers;
+		uint8_t		max_congestion_ctrl;
+		uint64_t	ext_cfg_iova;
+	} adv;
+};
+
+/**
+ * dpni_create() - Create the DPNI object
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @cfg:	Configuration structure
+ * @token:	Returned token; use in subsequent API calls
+ *
+ * Create the DPNI object, allocate required resources and
+ * perform required initialization.
+ *
+ * The object can be created either by declaring it in the
+ * DPL file, or by calling this function.
+ *
+ * This function returns a unique authentication token,
+ * associated with the specific object ID and the specific MC
+ * portal; this token must be used in all subsequent calls to
+ * this specific object. For objects that are created using the
+ * DPL file, call dpni_open() function to get an authentication
+ * token first.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_create(struct fsl_mc_io	*mc_io,
+		uint32_t		cmd_flags,
+		const struct dpni_cfg	*cfg,
+		uint16_t		*token);
+
+/**
+ * dpni_destroy() - Destroy the DPNI object and release all its resources.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_destroy(struct fsl_mc_io	*mc_io,
+		 uint32_t		cmd_flags,
+		 uint16_t		token);
+
+/**
+ * struct dpni_pools_cfg - Structure representing buffer pools configuration
+ * @num_dpbp: Number of DPBPs
+ * @pools: Array of buffer pools parameters; The number of valid entries
+ *	must match 'num_dpbp' value
+ */
+struct dpni_pools_cfg {
+	uint8_t		num_dpbp;
+	/**
+	 * struct pools - Buffer pools parameters
+	 * @dpbp_id: DPBP object ID
+	 * @buffer_size: Buffer size
+	 * @backup_pool: Backup pool
+	 */
+	struct {
+		int		dpbp_id;
+		uint16_t	buffer_size;
+		int		backup_pool;
+	} pools[DPNI_MAX_DPBP];
+};
+
+/**
+ * dpni_set_pools() - Set buffer pools configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @cfg:	Buffer pools configuration
+ *
+ * mandatory for DPNI operation
+ * warning:Allowed only when DPNI is disabled
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_pools(struct fsl_mc_io		*mc_io,
+		   uint32_t			cmd_flags,
+		   uint16_t			token,
+		   const struct dpni_pools_cfg	*cfg);
+
+/**
+ * dpni_enable() - Enable the DPNI, allow sending and receiving frames.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:		Token of DPNI object
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_enable(struct fsl_mc_io	*mc_io,
+		uint32_t		cmd_flags,
+		uint16_t		token);
+
+/**
+ * dpni_disable() - Disable the DPNI, stop sending and receiving frames.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_disable(struct fsl_mc_io	*mc_io,
+		 uint32_t		cmd_flags,
+		 uint16_t		token);
+
+/**
+ * dpni_is_enabled() - Check if the DPNI is enabled.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Returns '1' if object is enabled; '0' otherwise
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_is_enabled(struct fsl_mc_io	*mc_io,
+		    uint32_t		cmd_flags,
+		    uint16_t		token,
+		    int		*en);
+
+/**
+ * dpni_reset() - Reset the DPNI, returns the object to initial state.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_reset(struct fsl_mc_io	*mc_io,
+	       uint32_t		cmd_flags,
+	       uint16_t		token);
+
+/**
+ * DPNI IRQ Index and Events
+ */
+
+/**
+ * IRQ index
+ */
+#define DPNI_IRQ_INDEX				0
+/**
+ * IRQ event - indicates a change in link state
+ */
+#define DPNI_IRQ_EVENT_LINK_CHANGED		0x00000001
+
+/**
+ * struct dpni_irq_cfg - IRQ configuration
+ * @addr:	Address that must be written to signal a message-based interrupt
+ * @val:	Value to write into irq_addr address
+ * @irq_num: A user defined number associated with this IRQ
+ */
+struct dpni_irq_cfg {
+	     uint64_t		addr;
+	     uint32_t		val;
+	     int		irq_num;
+};
+
+/**
+ * dpni_set_irq() - Set IRQ information for the DPNI to trigger an interrupt.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @irq_index:	Identifies the interrupt index to configure
+ * @irq_cfg:	IRQ configuration
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_irq(struct fsl_mc_io	*mc_io,
+		 uint32_t		cmd_flags,
+		 uint16_t		token,
+		 uint8_t		irq_index,
+		 struct dpni_irq_cfg	*irq_cfg);
+
+/**
+ * dpni_get_irq() - Get IRQ information from the DPNI.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @irq_index:	The interrupt index to configure
+ * @type:	Interrupt type: 0 represents message interrupt
+ *		type (both irq_addr and irq_val are valid)
+ * @irq_cfg:	IRQ attributes
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_irq(struct fsl_mc_io	*mc_io,
+		 uint32_t		cmd_flags,
+		 uint16_t		token,
+		 uint8_t		irq_index,
+		 int			*type,
+		 struct dpni_irq_cfg	*irq_cfg);
+
+/**
+ * dpni_set_irq_enable() - Set overall interrupt state.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @irq_index:	The interrupt index to configure
+ * @en:		Interrupt state: - enable = 1, disable = 0
+ *
+ * Allows GPP software to control when interrupts are generated.
+ * Each interrupt can have up to 32 causes.  The enable/disable control's the
+ * overall interrupt state. if the interrupt is disabled no causes will cause
+ * an interrupt.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_irq_enable(struct fsl_mc_io	*mc_io,
+			uint32_t		cmd_flags,
+			uint16_t		token,
+			uint8_t			irq_index,
+			uint8_t			en);
+
+/**
+ * dpni_get_irq_enable() - Get overall interrupt state
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @irq_index:	The interrupt index to configure
+ * @en:		Returned interrupt state - enable = 1, disable = 0
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_irq_enable(struct fsl_mc_io	*mc_io,
+			uint32_t		cmd_flags,
+			uint16_t		token,
+			uint8_t			irq_index,
+			uint8_t			*en);
+
+/**
+ * dpni_set_irq_mask() - Set interrupt mask.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @irq_index:	The interrupt index to configure
+ * @mask:	event mask to trigger interrupt;
+ *			each bit:
+ *				0 = ignore event
+ *				1 = consider event for asserting IRQ
+ *
+ * Every interrupt can have up to 32 causes and the interrupt model supports
+ * masking/unmasking each cause independently
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_irq_mask(struct fsl_mc_io	*mc_io,
+		      uint32_t		cmd_flags,
+		      uint16_t		token,
+		      uint8_t		irq_index,
+		      uint32_t		mask);
+
+/**
+ * dpni_get_irq_mask() - Get interrupt mask.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @irq_index:	The interrupt index to configure
+ * @mask:	Returned event mask to trigger interrupt
+ *
+ * Every interrupt can have up to 32 causes and the interrupt model supports
+ * masking/unmasking each cause independently
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_irq_mask(struct fsl_mc_io	*mc_io,
+		      uint32_t		cmd_flags,
+		      uint16_t		token,
+		      uint8_t		irq_index,
+		      uint32_t		*mask);
+
+/**
+ * dpni_get_irq_status() - Get the current status of any pending interrupts.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @irq_index:	The interrupt index to configure
+ * @status:	Returned interrupts status - one bit per cause:
+ *			0 = no interrupt pending
+ *			1 = interrupt pending
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_irq_status(struct fsl_mc_io	*mc_io,
+			uint32_t		cmd_flags,
+			uint16_t		token,
+			uint8_t			irq_index,
+			uint32_t		*status);
+
+/**
+ * dpni_clear_irq_status() - Clear a pending interrupt's status
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @irq_index:	The interrupt index to configure
+ * @status:	bits to clear (W1C) - one bit per cause:
+ *			0 = don't change
+ *			1 = clear status bit
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_clear_irq_status(struct fsl_mc_io	*mc_io,
+			  uint32_t		cmd_flags,
+			  uint16_t		token,
+			  uint8_t		irq_index,
+			  uint32_t		status);
+
+/**
+ * struct dpni_attr - Structure representing DPNI attributes
+ * @id: DPNI object ID
+ * @version: DPNI version
+ * @start_hdr: Indicates the packet starting header for parsing
+ * @options: Mask of available options; reflects the value as was given in
+ *		object's creation
+ * @max_senders: Maximum number of different senders; used as the number
+ *		of dedicated Tx flows;
+ * @max_tcs: Maximum number of traffic classes (for both Tx and Rx)
+ * @max_unicast_filters: Maximum number of unicast filters
+ * @max_multicast_filters: Maximum number of multicast filters
+ * @max_vlan_filters: Maximum number of VLAN filters
+ * @max_qos_entries: if 'max_tcs > 1', declares the maximum entries in QoS table
+ * @max_qos_key_size: Maximum key size for the QoS look-up
+ * @max_dist_key_size: Maximum key size for the distribution look-up
+ * @max_policers: Maximum number of policers;
+ * @max_congestion_ctrl: Maximum number of congestion control groups (CGs);
+ * @ext_cfg_iova: I/O virtual address of 256 bytes DMA-able memory;
+ *	call dpni_extract_extended_cfg() to extract the extended configuration
+ */
+struct dpni_attr {
+	int		id;
+	/**
+	 * struct version - DPNI version
+	 * @major: DPNI major version
+	 * @minor: DPNI minor version
+	 */
+	struct {
+		uint16_t major;
+		uint16_t minor;
+	} version;
+	enum net_prot	start_hdr;
+	uint32_t	options;
+	uint8_t		max_senders;
+	uint8_t		max_tcs;
+	uint8_t		max_unicast_filters;
+	uint8_t		max_multicast_filters;
+	uint8_t		max_vlan_filters;
+	uint8_t		max_qos_entries;
+	uint8_t		max_qos_key_size;
+	uint8_t		max_dist_key_size;
+	uint8_t		max_policers;
+	uint8_t		max_congestion_ctrl;
+	uint64_t	ext_cfg_iova;
+};
+
+/**
+ * dpni_get_attributes() - Retrieve DPNI attributes.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @attr:	Object's attributes
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_attributes(struct fsl_mc_io	*mc_io,
+			uint32_t		cmd_flags,
+			uint16_t		token,
+			struct dpni_attr	*attr);
+
+/**
+ * dpni_extract_extended_cfg() - extract the extended parameters
+ * @cfg: extended structure
+ * @ext_cfg_buf: 256 bytes of DMA-able memory
+ *
+ * This function has to be called after dpni_get_attributes()
+ */
+int dpni_extract_extended_cfg(struct dpni_extended_cfg	*cfg,
+			      const uint8_t		*ext_cfg_buf);
+
+/**
+ * DPNI errors
+ */
+
+/**
+ * Extract out of frame header error
+ */
+#define DPNI_ERROR_EOFHE	0x00020000
+/**
+ * Frame length error
+ */
+#define DPNI_ERROR_FLE		0x00002000
+/**
+ * Frame physical error
+ */
+#define DPNI_ERROR_FPE		0x00001000
+/**
+ * Parsing header error
+ */
+#define DPNI_ERROR_PHE		0x00000020
+/**
+ * Parser L3 checksum error
+ */
+#define DPNI_ERROR_L3CE		0x00000004
+/**
+ * Parser L3 checksum error
+ */
+#define DPNI_ERROR_L4CE		0x00000001
+
+/**
+ * enum dpni_error_action - Defines DPNI behavior for errors
+ * @DPNI_ERROR_ACTION_DISCARD: Discard the frame
+ * @DPNI_ERROR_ACTION_CONTINUE: Continue with the normal flow
+ * @DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE: Send the frame to the error queue
+ */
+enum dpni_error_action {
+	DPNI_ERROR_ACTION_DISCARD = 0,
+	DPNI_ERROR_ACTION_CONTINUE = 1,
+	DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE = 2
+};
+
+/**
+ * struct dpni_error_cfg - Structure representing DPNI errors treatment
+ * @errors: Errors mask; use 'DPNI_ERROR__<X>
+ * @error_action: The desired action for the errors mask
+ * @set_frame_annotation: Set to '1' to mark the errors in frame annotation
+ *		status (FAS); relevant only for the non-discard action
+ */
+struct dpni_error_cfg {
+	uint32_t		errors;
+	enum dpni_error_action	error_action;
+	int			set_frame_annotation;
+};
+
+/**
+ * dpni_set_errors_behavior() - Set errors behavior
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @cfg:	Errors configuration
+ *
+ * this function may be called numerous times with different
+ * error masks
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_errors_behavior(struct fsl_mc_io		*mc_io,
+			     uint32_t			cmd_flags,
+			     uint16_t			token,
+			     struct dpni_error_cfg	*cfg);
+
+/**
+ * DPNI buffer layout modification options
+ */
+
+/**
+ * Select to modify the time-stamp setting
+ */
+#define DPNI_BUF_LAYOUT_OPT_TIMESTAMP		0x00000001
+/**
+ * Select to modify the parser-result setting; not applicable for Tx
+ */
+#define DPNI_BUF_LAYOUT_OPT_PARSER_RESULT	0x00000002
+/**
+ * Select to modify the frame-status setting
+ */
+#define DPNI_BUF_LAYOUT_OPT_FRAME_STATUS	0x00000004
+/**
+ * Select to modify the private-data-size setting
+ */
+#define DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE	0x00000008
+/**
+ * Select to modify the data-alignment setting
+ */
+#define DPNI_BUF_LAYOUT_OPT_DATA_ALIGN		0x00000010
+/**
+ * Select to modify the data-head-room setting
+ */
+#define DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM	0x00000020
+/**
+ * Select to modify the data-tail-room setting
+ */
+#define DPNI_BUF_LAYOUT_OPT_DATA_TAIL_ROOM	0x00000040
+
+/**
+ * struct dpni_buffer_layout - Structure representing DPNI buffer layout
+ * @options: Flags representing the suggested modifications to the buffer
+ *		layout; Use any combination of 'DPNI_BUF_LAYOUT_OPT_<X>' flags
+ * @pass_timestamp: Pass timestamp value
+ * @pass_parser_result: Pass parser results
+ * @pass_frame_status: Pass frame status
+ * @private_data_size: Size kept for private data (in bytes)
+ * @data_align: Data alignment
+ * @data_head_room: Data head room
+ * @data_tail_room: Data tail room
+ */
+struct dpni_buffer_layout {
+	uint32_t	options;
+	int		pass_timestamp;
+	int		pass_parser_result;
+	int		pass_frame_status;
+	uint16_t	private_data_size;
+	uint16_t	data_align;
+	uint16_t	data_head_room;
+	uint16_t	data_tail_room;
+};
+
+/**
+ * dpni_get_rx_buffer_layout() - Retrieve Rx buffer layout attributes.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @layout:	Returns buffer layout attributes
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_rx_buffer_layout(struct fsl_mc_io		*mc_io,
+			      uint32_t			cmd_flags,
+			      uint16_t			token,
+			      struct dpni_buffer_layout	*layout);
+
+/**
+ * dpni_set_rx_buffer_layout() - Set Rx buffer layout configuration.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @layout:	Buffer layout configuration
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ *
+ * @warning	Allowed only when DPNI is disabled
+ */
+int dpni_set_rx_buffer_layout(struct fsl_mc_io			*mc_io,
+			      uint32_t				cmd_flags,
+			      uint16_t				token,
+			      const struct dpni_buffer_layout	*layout);
+
+/**
+ * dpni_get_tx_buffer_layout() - Retrieve Tx buffer layout attributes.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @layout:	Returns buffer layout attributes
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_tx_buffer_layout(struct fsl_mc_io		*mc_io,
+			      uint32_t			cmd_flags,
+			      uint16_t			token,
+			      struct dpni_buffer_layout	*layout);
+
+/**
+ * dpni_set_tx_buffer_layout() - Set Tx buffer layout configuration.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @layout:	Buffer layout configuration
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ *
+ * @warning	Allowed only when DPNI is disabled
+ */
+int dpni_set_tx_buffer_layout(struct fsl_mc_io			*mc_io,
+			      uint32_t				cmd_flags,
+			      uint16_t				token,
+			      const struct dpni_buffer_layout	*layout);
+
+/**
+ * dpni_get_tx_conf_buffer_layout() - Retrieve Tx confirmation buffer layout
+ *				attributes.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @layout:	Returns buffer layout attributes
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io		*mc_io,
+				   uint32_t			cmd_flags,
+				   uint16_t			token,
+				   struct dpni_buffer_layout	*layout);
+
+/**
+ * dpni_set_tx_conf_buffer_layout() - Set Tx confirmation buffer layout
+ *					configuration.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @layout:	Buffer layout configuration
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ *
+ * @warning	Allowed only when DPNI is disabled
+ */
+int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io		   *mc_io,
+				   uint32_t			   cmd_flags,
+				   uint16_t			   token,
+				   const struct dpni_buffer_layout *layout);
+
+/**
+ * dpni_set_l3_chksum_validation() - Enable/disable L3 checksum validation
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Set to '1' to enable; '0' to disable
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_l3_chksum_validation(struct fsl_mc_io	*mc_io,
+				  uint32_t		cmd_flags,
+				  uint16_t		token,
+				  int			en);
+
+/**
+ * dpni_get_l3_chksum_validation() - Get L3 checksum validation mode
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Returns '1' if enabled; '0' otherwise
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_l3_chksum_validation(struct fsl_mc_io	*mc_io,
+				  uint32_t		cmd_flags,
+				  uint16_t		token,
+				  int			*en);
+
+/**
+ * dpni_set_l4_chksum_validation() - Enable/disable L4 checksum validation
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Set to '1' to enable; '0' to disable
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_l4_chksum_validation(struct fsl_mc_io	*mc_io,
+				  uint32_t		cmd_flags,
+				  uint16_t		token,
+				  int			en);
+
+/**
+ * dpni_get_l4_chksum_validation() - Get L4 checksum validation mode
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Returns '1' if enabled; '0' otherwise
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_l4_chksum_validation(struct fsl_mc_io	*mc_io,
+				  uint32_t		cmd_flags,
+				  uint16_t		token,
+				  int			*en);
+
+/**
+ * dpni_get_qdid() - Get the Queuing Destination ID (QDID) that should be used
+ *			for enqueue operations
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @qdid:	Returned virtual QDID value that should be used as an argument
+ *			in all enqueue operations
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_qdid(struct fsl_mc_io	*mc_io,
+		  uint32_t		cmd_flags,
+		  uint16_t		token,
+		  uint16_t		*qdid);
+
+/**
+ * struct dpni_sp_info - Structure representing DPNI storage-profile information
+ * (relevant only for DPNI owned by AIOP)
+ * @spids: array of storage-profiles
+ */
+struct dpni_sp_info {
+	uint16_t spids[DPNI_MAX_SP];
+};
+
+/**
+ * dpni_get_spids() - Get the AIOP storage profile IDs associated with the DPNI
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @sp_info:	Returned AIOP storage-profile information
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ *
+ * @warning	Only relevant for DPNI that belongs to AIOP container.
+ */
+int dpni_get_sp_info(struct fsl_mc_io		*mc_io,
+		     uint32_t			cmd_flags,
+		     uint16_t			token,
+		     struct dpni_sp_info	*sp_info);
+
+/**
+ * dpni_get_tx_data_offset() - Get the Tx data offset (from start of buffer)
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @data_offset: Tx data offset (from start of buffer)
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_tx_data_offset(struct fsl_mc_io	*mc_io,
+			    uint32_t		cmd_flags,
+			    uint16_t		token,
+			    uint16_t		*data_offset);
+
+/**
+ * enum dpni_counter - DPNI counter types
+ * @DPNI_CNT_ING_FRAME: Counts ingress frames
+ * @DPNI_CNT_ING_BYTE: Counts ingress bytes
+ * @DPNI_CNT_ING_FRAME_DROP: Counts ingress frames dropped due to explicit
+ *		'drop' setting
+ * @DPNI_CNT_ING_FRAME_DISCARD: Counts ingress frames discarded due to errors
+ * @DPNI_CNT_ING_MCAST_FRAME: Counts ingress multicast frames
+ * @DPNI_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes
+ * @DPNI_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames
+ * @DPNI_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes
+ * @DPNI_CNT_EGR_FRAME: Counts egress frames
+ * @DPNI_CNT_EGR_BYTE: Counts egress bytes
+ * @DPNI_CNT_EGR_FRAME_DISCARD: Counts egress frames discarded due to errors
+ */
+enum dpni_counter {
+	DPNI_CNT_ING_FRAME = 0x0,
+	DPNI_CNT_ING_BYTE = 0x1,
+	DPNI_CNT_ING_FRAME_DROP = 0x2,
+	DPNI_CNT_ING_FRAME_DISCARD = 0x3,
+	DPNI_CNT_ING_MCAST_FRAME = 0x4,
+	DPNI_CNT_ING_MCAST_BYTE = 0x5,
+	DPNI_CNT_ING_BCAST_FRAME = 0x6,
+	DPNI_CNT_ING_BCAST_BYTES = 0x7,
+	DPNI_CNT_EGR_FRAME = 0x8,
+	DPNI_CNT_EGR_BYTE = 0x9,
+	DPNI_CNT_EGR_FRAME_DISCARD = 0xa
+};
+
+/**
+ * dpni_get_counter() - Read a specific DPNI counter
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @counter:	The requested counter
+ * @value:	Returned counter's current value
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_counter(struct fsl_mc_io	*mc_io,
+		     uint32_t		cmd_flags,
+		     uint16_t		token,
+		     enum dpni_counter	counter,
+		     uint64_t		*value);
+
+/**
+ * dpni_set_counter() - Set (or clear) a specific DPNI counter
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @counter:	The requested counter
+ * @value:	New counter value; typically pass '0' for resetting
+ *			the counter.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_counter(struct fsl_mc_io	*mc_io,
+		     uint32_t		cmd_flags,
+		     uint16_t		token,
+		     enum dpni_counter	counter,
+		     uint64_t		value);
+
+/**
+ * Enable auto-negotiation
+ */
+#define DPNI_LINK_OPT_AUTONEG		0x0000000000000001ULL
+/**
+ * Enable half-duplex mode
+ */
+#define DPNI_LINK_OPT_HALF_DUPLEX	0x0000000000000002ULL
+/**
+ * Enable pause frames
+ */
+#define DPNI_LINK_OPT_PAUSE		0x0000000000000004ULL
+/**
+ * Enable a-symmetric pause frames
+ */
+#define DPNI_LINK_OPT_ASYM_PAUSE	0x0000000000000008ULL
+
+/**
+ * struct - Structure representing DPNI link configuration
+ * @rate: Rate
+ * @options: Mask of available options; use 'DPNI_LINK_OPT_<X>' values
+ */
+struct dpni_link_cfg {
+	uint32_t rate;
+	uint64_t options;
+};
+
+/**
+ * dpni_set_link_cfg() - set the link configuration.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @cfg:	Link configuration
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_link_cfg(struct fsl_mc_io			*mc_io,
+		      uint32_t				cmd_flags,
+		      uint16_t				token,
+		      const struct dpni_link_cfg	*cfg);
+
+/**
+ * struct dpni_link_state - Structure representing DPNI link state
+ * @rate: Rate
+ * @options: Mask of available options; use 'DPNI_LINK_OPT_<X>' values
+ * @up: Link state; '0' for down, '1' for up
+ */
+struct dpni_link_state {
+	uint32_t	rate;
+	uint64_t	options;
+	int		up;
+};
+
+/**
+ * dpni_get_link_state() - Return the link state (either up or down)
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @state:	Returned link state;
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_link_state(struct fsl_mc_io	*mc_io,
+			uint32_t		cmd_flags,
+			uint16_t		token,
+			struct dpni_link_state	*state);
+
+/**
+ * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration
+ * @rate_limit: rate in Mbps
+ * @max_burst_size: burst size in bytes (up to 64KB)
+ */
+struct dpni_tx_shaping_cfg {
+	uint32_t rate_limit;
+	uint16_t max_burst_size;
+};
+
+/**
+ * dpni_set_tx_shaping() - Set the transmit shaping
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tx_shaper:  tx shaping configuration
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_tx_shaping(struct fsl_mc_io			*mc_io,
+			uint32_t				cmd_flags,
+			uint16_t				token,
+			const struct dpni_tx_shaping_cfg	*tx_shaper);
+
+/**
+ * dpni_set_max_frame_length() - Set the maximum received frame length.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @max_frame_length:	Maximum received frame length (in
+ *				bytes); frame is discarded if its
+ *				length exceeds this value
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_max_frame_length(struct fsl_mc_io	*mc_io,
+			      uint32_t		cmd_flags,
+			      uint16_t		token,
+			      uint16_t		max_frame_length);
+
+/**
+ * dpni_get_max_frame_length() - Get the maximum received frame length.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @max_frame_length:	Maximum received frame length (in
+ *				bytes); frame is discarded if its
+ *				length exceeds this value
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_max_frame_length(struct fsl_mc_io	*mc_io,
+			      uint32_t		cmd_flags,
+			      uint16_t		token,
+			      uint16_t		*max_frame_length);
+
+/**
+ * dpni_set_mtu() - Set the MTU for the interface.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @mtu:	MTU length (in bytes)
+ *
+ * MTU determines the maximum fragment size for performing IP
+ * fragmentation on egress packets.
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_mtu(struct fsl_mc_io	*mc_io,
+		 uint32_t		cmd_flags,
+		 uint16_t		token,
+		 uint16_t		mtu);
+
+/**
+ * dpni_get_mtu() - Get the MTU.
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @mtu:	Returned MTU length (in bytes)
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_mtu(struct fsl_mc_io	*mc_io,
+		 uint32_t		cmd_flags,
+		 uint16_t		token,
+		 uint16_t		*mtu);
+
+/**
+ * dpni_set_multicast_promisc() - Enable/disable multicast promiscuous mode
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Set to '1' to enable; '0' to disable
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_multicast_promisc(struct fsl_mc_io *mc_io,
+			       uint32_t	cmd_flags,
+			       uint16_t		token,
+			       int		en);
+
+/**
+ * dpni_get_multicast_promisc() - Get multicast promiscuous mode
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Returns '1' if enabled; '0' otherwise
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_multicast_promisc(struct fsl_mc_io *mc_io,
+			       uint32_t	cmd_flags,
+			       uint16_t		token,
+			       int		*en);
+
+/**
+ * dpni_set_unicast_promisc() - Enable/disable unicast promiscuous mode
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Set to '1' to enable; '0' to disable
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_unicast_promisc(struct fsl_mc_io	*mc_io,
+			     uint32_t		cmd_flags,
+			     uint16_t		token,
+			     int		en);
+
+/**
+ * dpni_get_unicast_promisc() - Get unicast promiscuous mode
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Returns '1' if enabled; '0' otherwise
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_unicast_promisc(struct fsl_mc_io	*mc_io,
+			     uint32_t		cmd_flags,
+			     uint16_t		token,
+			     int		*en);
+
+/**
+ * dpni_set_primary_mac_addr() - Set the primary MAC address
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @mac_addr:	MAC address to set as primary address
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io,
+			      uint32_t		cmd_flags,
+			      uint16_t		token,
+			      const uint8_t	mac_addr[6]);
+
+/**
+ * dpni_get_primary_mac_addr() - Get the primary MAC address
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @mac_addr:	Returned MAC address
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_primary_mac_addr(struct fsl_mc_io	*mc_io,
+			      uint32_t		cmd_flags,
+			      uint16_t		token,
+			      uint8_t		mac_addr[6]);
+
+/**
+ * dpni_add_mac_addr() - Add MAC address filter
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @mac_addr:	MAC address to add
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_add_mac_addr(struct fsl_mc_io	*mc_io,
+		      uint32_t		cmd_flags,
+		      uint16_t		token,
+		      const uint8_t	mac_addr[6]);
+
+/**
+ * dpni_remove_mac_addr() - Remove MAC address filter
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @mac_addr:	MAC address to remove
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_remove_mac_addr(struct fsl_mc_io	*mc_io,
+			 uint32_t		cmd_flags,
+			 uint16_t		token,
+			 const uint8_t		mac_addr[6]);
+
+/**
+ * dpni_clear_mac_filters() - Clear all unicast and/or multicast MAC filters
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @unicast:	Set to '1' to clear unicast addresses
+ * @multicast:	Set to '1' to clear multicast addresses
+ *
+ * The primary MAC address is not cleared by this operation.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_clear_mac_filters(struct fsl_mc_io	*mc_io,
+			   uint32_t		cmd_flags,
+			   uint16_t		token,
+			   int			unicast,
+			   int			multicast);
+
+/**
+ * dpni_set_vlan_filters() - Enable/disable VLAN filtering mode
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Set to '1' to enable; '0' to disable
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_vlan_filters(struct fsl_mc_io	*mc_io,
+			  uint32_t		cmd_flags,
+			  uint16_t		token,
+			  int			en);
+
+/**
+ * dpni_add_vlan_id() - Add VLAN ID filter
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @vlan_id:	VLAN ID to add
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_add_vlan_id(struct fsl_mc_io	*mc_io,
+		     uint32_t		cmd_flags,
+		     uint16_t		token,
+		     uint16_t		vlan_id);
+
+/**
+ * dpni_remove_vlan_id() - Remove VLAN ID filter
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @vlan_id:	VLAN ID to remove
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_remove_vlan_id(struct fsl_mc_io	*mc_io,
+			uint32_t		cmd_flags,
+			uint16_t		token,
+			uint16_t		vlan_id);
+
+/**
+ * dpni_clear_vlan_filters() - Clear all VLAN filters
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_clear_vlan_filters(struct fsl_mc_io	*mc_io,
+			    uint32_t		cmd_flags,
+			    uint16_t		token);
+
+/**
+ * enum dpni_tx_schedule_mode - DPNI Tx scheduling mode
+ * @DPNI_TX_SCHED_STRICT_PRIORITY: strict priority
+ * @DPNI_TX_SCHED_WEIGHTED: weighted based scheduling
+ */
+enum dpni_tx_schedule_mode {
+	DPNI_TX_SCHED_STRICT_PRIORITY,
+	DPNI_TX_SCHED_WEIGHTED,
+};
+
+/**
+ * struct dpni_tx_schedule_cfg - Structure representing Tx
+ *	scheduling configuration
+ * @mode: scheduling mode
+ * @delta_bandwidth: Bandwidth represented in weights from 100 to 10000;
+ *	not applicable for 'strict-priority' mode;
+ */
+struct dpni_tx_schedule_cfg {
+	enum dpni_tx_schedule_mode	mode;
+	uint16_t		delta_bandwidth;
+};
+
+/**
+ * struct dpni_tx_selection_cfg - Structure representing transmission
+ *	selection configuration
+ * @tc_sched: an array of traffic-classes
+ */
+struct dpni_tx_selection_cfg {
+	struct dpni_tx_schedule_cfg tc_sched[DPNI_MAX_TC];
+};
+
+/**
+ * dpni_set_tx_selection() - Set transmission selection configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @cfg:	transmission selection configuration
+ *
+ * warning:	Allowed only when DPNI is disabled
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_tx_selection(struct fsl_mc_io			*mc_io,
+			  uint32_t				cmd_flags,
+			  uint16_t				token,
+			  const struct dpni_tx_selection_cfg	*cfg);
+
+/**
+ * enum dpni_dist_mode - DPNI distribution mode
+ * @DPNI_DIST_MODE_NONE: No distribution
+ * @DPNI_DIST_MODE_HASH: Use hash distribution; only relevant if
+ *		the 'DPNI_OPT_DIST_HASH' option was set at DPNI creation
+ * @DPNI_DIST_MODE_FS:  Use explicit flow steering; only relevant if
+ *	 the 'DPNI_OPT_DIST_FS' option was set at DPNI creation
+ */
+enum dpni_dist_mode {
+	DPNI_DIST_MODE_NONE = 0,
+	DPNI_DIST_MODE_HASH = 1,
+	DPNI_DIST_MODE_FS = 2
+};
+
+/**
+ * enum dpni_fs_miss_action -   DPNI Flow Steering miss action
+ * @DPNI_FS_MISS_DROP: In case of no-match, drop the frame
+ * @DPNI_FS_MISS_EXPLICIT_FLOWID: In case of no-match, use explicit flow-id
+ * @DPNI_FS_MISS_HASH: In case of no-match, distribute using hash
+ */
+enum dpni_fs_miss_action {
+	DPNI_FS_MISS_DROP = 0,
+	DPNI_FS_MISS_EXPLICIT_FLOWID = 1,
+	DPNI_FS_MISS_HASH = 2
+};
+
+/**
+ * struct dpni_fs_tbl_cfg - Flow Steering table configuration
+ * @miss_action: Miss action selection
+ * @default_flow_id: Used when 'miss_action = DPNI_FS_MISS_EXPLICIT_FLOWID'
+ */
+struct dpni_fs_tbl_cfg {
+	enum dpni_fs_miss_action	miss_action;
+	uint16_t			default_flow_id;
+};
+
+/**
+ * dpni_prepare_key_cfg() - function prepare extract parameters
+ * @cfg: defining a full Key Generation profile (rule)
+ * @key_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA
+ *
+ * This function has to be called before the following functions:
+ *	- dpni_set_rx_tc_dist()
+ *		- dpni_set_qos_table()
+ */
+int dpni_prepare_key_cfg(const struct dpkg_profile_cfg	*cfg,
+			 uint8_t			*key_cfg_buf);
+
+/**
+ * struct dpni_rx_tc_dist_cfg - Rx traffic class distribution configuration
+ * @dist_size: Set the distribution size;
+ *	supported values: 1,2,3,4,6,7,8,12,14,16,24,28,32,48,56,64,96,
+ *	112,128,192,224,256,384,448,512,768,896,1024
+ * @dist_mode: Distribution mode
+ * @key_cfg_iova: I/O virtual address of 256 bytes DMA-able memory filled with
+ *		the extractions to be used for the distribution key by calling
+ *		dpni_prepare_key_cfg() relevant only when
+ *		'dist_mode != DPNI_DIST_MODE_NONE', otherwise it can be '0'
+ * @fs_cfg: Flow Steering table configuration; only relevant if
+ *		'dist_mode = DPNI_DIST_MODE_FS'
+ */
+struct dpni_rx_tc_dist_cfg {
+	uint16_t		dist_size;
+	enum dpni_dist_mode	dist_mode;
+	uint64_t		key_cfg_iova;
+	struct dpni_fs_tbl_cfg	fs_cfg;
+};
+
+/**
+ * dpni_set_rx_tc_dist() - Set Rx traffic class distribution configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @cfg:	Traffic class distribution configuration
+ *
+ * warning: if 'dist_mode != DPNI_DIST_MODE_NONE', call dpni_prepare_key_cfg()
+ *			first to prepare the key_cfg_iova parameter
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_set_rx_tc_dist(struct fsl_mc_io			*mc_io,
+			uint32_t				cmd_flags,
+			uint16_t				token,
+			uint8_t					tc_id,
+			const struct dpni_rx_tc_dist_cfg	*cfg);
+
+/**
+ * Set to select color aware mode (otherwise - color blind)
+ */
+#define DPNI_POLICER_OPT_COLOR_AWARE	0x00000001
+/**
+ * Set to discard frame with RED color
+ */
+#define DPNI_POLICER_OPT_DISCARD_RED	0x00000002
+
+/**
+ * enum dpni_policer_mode - selecting the policer mode
+ * @DPNI_POLICER_MODE_NONE: Policer is disabled
+ * @DPNI_POLICER_MODE_PASS_THROUGH: Policer pass through
+ * @DPNI_POLICER_MODE_RFC_2698: Policer algorithm RFC 2698
+ * @DPNI_POLICER_MODE_RFC_4115: Policer algorithm RFC 4115
+ */
+enum dpni_policer_mode {
+	DPNI_POLICER_MODE_NONE = 0,
+	DPNI_POLICER_MODE_PASS_THROUGH,
+	DPNI_POLICER_MODE_RFC_2698,
+	DPNI_POLICER_MODE_RFC_4115
+};
+
+/**
+ * enum dpni_policer_unit - DPNI policer units
+ * @DPNI_POLICER_UNIT_BYTES: bytes units
+ * @DPNI_POLICER_UNIT_FRAMES: frames units
+ */
+enum dpni_policer_unit {
+	DPNI_POLICER_UNIT_BYTES = 0,
+	DPNI_POLICER_UNIT_FRAMES
+};
+
+/**
+ * enum dpni_policer_color - selecting the policer color
+ * @DPNI_POLICER_COLOR_GREEN: Green color
+ * @DPNI_POLICER_COLOR_YELLOW: Yellow color
+ * @DPNI_POLICER_COLOR_RED: Red color
+ */
+enum dpni_policer_color {
+	DPNI_POLICER_COLOR_GREEN = 0,
+	DPNI_POLICER_COLOR_YELLOW,
+	DPNI_POLICER_COLOR_RED
+};
+
+/**
+ * struct dpni_rx_tc_policing_cfg - Policer configuration
+ * @options: Mask of available options; use 'DPNI_POLICER_OPT_<X>' values
+ * @mode: policer mode
+ * @default_color: For pass-through mode the policer re-colors with this
+ *	color any incoming packets. For Color aware non-pass-through mode:
+ *	policer re-colors with this color all packets with FD[DROPP]>2.
+ * @units: Bytes or Packets
+ * @cir: Committed information rate (CIR) in Kbps or packets/second
+ * @cbs: Committed burst size (CBS) in bytes or packets
+ * @eir: Peak information rate (PIR, rfc2698) in Kbps or packets/second
+ *	 Excess information rate (EIR, rfc4115) in Kbps or packets/second
+ * @ebs: Peak burst size (PBS, rfc2698) in bytes or packets
+ *       Excess burst size (EBS, rfc4115) in bytes or packets
+ */
+struct dpni_rx_tc_policing_cfg {
+	uint32_t		options;
+	enum dpni_policer_mode	mode;
+	enum dpni_policer_unit	units;
+	enum dpni_policer_color default_color;
+	uint32_t		cir;
+	uint32_t		cbs;
+	uint32_t		eir;
+	uint32_t		ebs;
+};
+
+/**
+ * dpni_set_rx_tc_policing() - Set Rx traffic class policing configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @cfg:	Traffic class policing configuration
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_set_rx_tc_policing(struct fsl_mc_io			*mc_io,
+			    uint32_t				cmd_flags,
+			    uint16_t				token,
+			    uint8_t				tc_id,
+			    const struct dpni_rx_tc_policing_cfg *cfg);
+
+/**
+ * dpni_get_rx_tc_policing() - Get Rx traffic class policing configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @cfg:	Traffic class policing configuration
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_get_rx_tc_policing(struct fsl_mc_io			*mc_io,
+			    uint32_t				cmd_flags,
+			    uint16_t				token,
+			    uint8_t				tc_id,
+			    struct dpni_rx_tc_policing_cfg	*cfg);
+
+/**
+ * enum dpni_congestion_unit - DPNI congestion units
+ * @DPNI_CONGESTION_UNIT_BYTES: bytes units
+ * @DPNI_CONGESTION_UNIT_FRAMES: frames units
+ */
+enum dpni_congestion_unit {
+	DPNI_CONGESTION_UNIT_BYTES = 0,
+	DPNI_CONGESTION_UNIT_FRAMES
+};
+
+/**
+ * enum dpni_early_drop_mode - DPNI early drop mode
+ * @DPNI_EARLY_DROP_MODE_NONE: early drop is disabled
+ * @DPNI_EARLY_DROP_MODE_TAIL: early drop in taildrop mode
+ * @DPNI_EARLY_DROP_MODE_WRED: early drop in WRED mode
+ */
+enum dpni_early_drop_mode {
+	DPNI_EARLY_DROP_MODE_NONE = 0,
+	DPNI_EARLY_DROP_MODE_TAIL,
+	DPNI_EARLY_DROP_MODE_WRED
+};
+
+/**
+ * struct dpni_wred_cfg - WRED configuration
+ * @max_threshold: maximum threshold that packets may be discarded. Above this
+ *	  threshold all packets are discarded; must be less than 2^39;
+ *	  approximated to be expressed as (x+256)*2^(y-1) due to HW
+ *	  implementation.
+ * @min_threshold: minimum threshold that packets may be discarded at
+ * @drop_probability: probability that a packet will be discarded (1-100,
+ *			associated with the max_threshold).
+ */
+struct dpni_wred_cfg {
+	uint64_t	max_threshold;
+	uint64_t	min_threshold;
+	uint8_t	drop_probability;
+};
+
+/**
+ * struct dpni_early_drop_cfg - early-drop configuration
+ * @mode: drop mode
+ * @units: units type
+ * @green: WRED - 'green' configuration
+ * @yellow: WRED - 'yellow' configuration
+ * @red: WRED - 'red' configuration
+ * @tail_drop_threshold: tail drop threshold
+ */
+struct dpni_early_drop_cfg {
+	enum dpni_early_drop_mode	mode;
+	enum dpni_congestion_unit	units;
+
+	struct dpni_wred_cfg		green;
+	struct dpni_wred_cfg		yellow;
+	struct dpni_wred_cfg		red;
+
+	uint32_t			tail_drop_threshold;
+};
+
+/**
+ * dpni_prepare_early_drop() - prepare an early drop.
+ * @cfg: Early-drop configuration
+ * @early_drop_buf: Zeroed 256 bytes of memory before mapping it to DMA
+ *
+ * This function has to be called before dpni_set_rx_tc_early_drop or
+ * dpni_set_tx_tc_early_drop
+ *
+ */
+void dpni_prepare_early_drop(const struct dpni_early_drop_cfg *cfg,
+			     uint8_t	*early_drop_buf);
+
+/**
+ * dpni_extract_early_drop() - extract the early drop configuration.
+ * @cfg: Early-drop configuration
+ * @early_drop_buf: Zeroed 256 bytes of memory before mapping it to DMA
+ *
+ * This function has to be called after dpni_get_rx_tc_early_drop or
+ * dpni_get_tx_tc_early_drop
+ *
+ */
+void dpni_extract_early_drop(struct dpni_early_drop_cfg *cfg,
+			     const uint8_t *early_drop_buf);
+
+/**
+ * dpni_set_rx_tc_early_drop() - Set Rx traffic class early-drop configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @early_drop_iova:  I/O virtual address of 256 bytes DMA-able memory filled
+ *	with the early-drop configuration by calling dpni_prepare_early_drop()
+ *
+ * warning: Before calling this function, call dpni_prepare_early_drop() to
+ *			prepare the early_drop_iova parameter
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_set_rx_tc_early_drop(struct fsl_mc_io	*mc_io,
+			      uint32_t		cmd_flags,
+			      uint16_t		token,
+			      uint8_t		tc_id,
+			      uint64_t		early_drop_iova);
+
+/**
+ * dpni_get_rx_tc_early_drop() - Get Rx traffic class early-drop configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @early_drop_iova:  I/O virtual address of 256 bytes DMA-able memory
+ *
+ * warning: After calling this function, call dpni_extract_early_drop() to
+ *	get the early drop configuration
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_get_rx_tc_early_drop(struct fsl_mc_io	*mc_io,
+			      uint32_t		cmd_flags,
+			      uint16_t		token,
+			      uint8_t		tc_id,
+			      uint64_t		early_drop_iova);
+
+/**
+ * dpni_set_tx_tc_early_drop() - Set Tx traffic class early-drop configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @early_drop_iova:  I/O virtual address of 256 bytes DMA-able memory filled
+ *	with the early-drop configuration by calling dpni_prepare_early_drop()
+ *
+ * warning: Before calling this function, call dpni_prepare_early_drop() to
+ *			prepare the early_drop_iova parameter
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_set_tx_tc_early_drop(struct fsl_mc_io	*mc_io,
+			      uint32_t		cmd_flags,
+			      uint16_t		token,
+			      uint8_t		tc_id,
+			      uint64_t		early_drop_iova);
+
+/**
+ * dpni_get_tx_tc_early_drop() - Get Tx traffic class early-drop configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @early_drop_iova:  I/O virtual address of 256 bytes DMA-able memory
+ *
+ * warning: After calling this function, call dpni_extract_early_drop() to
+ *	get the early drop configuration
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_get_tx_tc_early_drop(struct fsl_mc_io	*mc_io,
+			      uint32_t		cmd_flags,
+			      uint16_t		token,
+			      uint8_t		tc_id,
+			      uint64_t		early_drop_iova);
+
+/**
+ * enum dpni_dest - DPNI destination types
+ * @DPNI_DEST_NONE: Unassigned destination; The queue is set in parked mode and
+ *		does not generate FQDAN notifications; user is expected to
+ *		dequeue from the queue based on polling or other user-defined
+ *		method
+ * @DPNI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN
+ *		notifications to the specified DPIO; user is expected to dequeue
+ *		from the queue only after notification is received
+ * @DPNI_DEST_DPCON: The queue is set in schedule mode and does not generate
+ *		FQDAN notifications, but is connected to the specified DPCON
+ *		object; user is expected to dequeue from the DPCON channel
+ */
+enum dpni_dest {
+	DPNI_DEST_NONE = 0,
+	DPNI_DEST_DPIO = 1,
+	DPNI_DEST_DPCON = 2
+};
+
+/**
+ * struct dpni_dest_cfg - Structure representing DPNI destination parameters
+ * @dest_type: Destination type
+ * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type
+ * @priority: Priority selection within the DPIO or DPCON channel; valid values
+ *		are 0-1 or 0-7, depending on the number of priorities in that
+ *		channel; not relevant for 'DPNI_DEST_NONE' option
+ */
+struct dpni_dest_cfg {
+	enum dpni_dest	dest_type;
+	int		dest_id;
+	uint8_t	priority;
+};
+
+/* DPNI congestion options */
+
+/**
+ * CSCN message is written to message_iova once entering a
+ * congestion state (see 'threshold_entry')
+ */
+#define DPNI_CONG_OPT_WRITE_MEM_ON_ENTER	0x00000001
+/**
+ * CSCN message is written to message_iova once exiting a
+ * congestion state (see 'threshold_exit')
+ */
+#define DPNI_CONG_OPT_WRITE_MEM_ON_EXIT		0x00000002
+/**
+ * CSCN write will attempt to allocate into a cache (coherent write);
+ * valid only if 'DPNI_CONG_OPT_WRITE_MEM_<X>' is selected
+ */
+#define DPNI_CONG_OPT_COHERENT_WRITE		0x00000004
+/**
+ * if 'dest_cfg.dest_type != DPNI_DEST_NONE' CSCN message is sent to
+ * DPIO/DPCON's WQ channel once entering a congestion state
+ * (see 'threshold_entry')
+ */
+#define DPNI_CONG_OPT_NOTIFY_DEST_ON_ENTER	0x00000008
+/**
+ * if 'dest_cfg.dest_type != DPNI_DEST_NONE' CSCN message is sent to
+ * DPIO/DPCON's WQ channel once exiting a congestion state
+ * (see 'threshold_exit')
+ */
+#define DPNI_CONG_OPT_NOTIFY_DEST_ON_EXIT	0x00000010
+/**
+ * if 'dest_cfg.dest_type != DPNI_DEST_NONE' when the CSCN is written to the
+ * sw-portal's DQRR, the DQRI interrupt is asserted immediately (if enabled)
+ */
+#define DPNI_CONG_OPT_INTR_COALESCING_DISABLED	0x00000020
+
+/**
+ * struct dpni_congestion_notification_cfg - congestion notification
+ *		configuration
+ * @units: units type
+ * @threshold_entry: above this threshold we enter a congestion state.
+ *	set it to '0' to disable it
+ * @threshold_exit: below this threshold we exit the congestion state.
+ * @message_ctx: The context that will be part of the CSCN message
+ * @message_iova: I/O virtual address (must be in DMA-able memory),
+ *	must be 16B aligned; valid only if 'DPNI_CONG_OPT_WRITE_MEM_<X>' is
+ *	contained in 'options'
+ * @dest_cfg: CSCN can be send to either DPIO or DPCON WQ channel
+ * @options: Mask of available options; use 'DPNI_CONG_OPT_<X>' values
+ */
+
+struct dpni_congestion_notification_cfg {
+	enum dpni_congestion_unit	units;
+	uint32_t	threshold_entry;
+	uint32_t	threshold_exit;
+	uint64_t	message_ctx;
+	uint64_t	message_iova;
+	struct dpni_dest_cfg dest_cfg;
+	uint16_t	options;
+};
+
+/**
+ * dpni_set_rx_tc_congestion_notification() - Set Rx traffic class congestion
+ *	notification configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @cfg:	congestion notification configuration
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_set_rx_tc_congestion_notification(struct fsl_mc_io	*mc_io,
+					   uint32_t		cmd_flags,
+					   uint16_t		token,
+					   uint8_t		tc_id,
+			const struct dpni_congestion_notification_cfg *cfg);
+
+/**
+ * dpni_get_rx_tc_congestion_notification() - Get Rx traffic class congestion
+ *	notification configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @cfg:	congestion notification configuration
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_get_rx_tc_congestion_notification(struct fsl_mc_io	*mc_io,
+					   uint32_t		cmd_flags,
+					   uint16_t		token,
+					   uint8_t		tc_id,
+				struct dpni_congestion_notification_cfg *cfg);
+
+/**
+ * dpni_set_tx_tc_congestion_notification() - Set Tx traffic class congestion
+ *	notification configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @cfg:	congestion notification configuration
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_set_tx_tc_congestion_notification(struct fsl_mc_io	*mc_io,
+					   uint32_t		cmd_flags,
+					   uint16_t		token,
+					   uint8_t		tc_id,
+			const struct dpni_congestion_notification_cfg *cfg);
+
+/**
+ * dpni_get_tx_tc_congestion_notification() - Get Tx traffic class congestion
+ *	notification configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @cfg:	congestion notification configuration
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_get_tx_tc_congestion_notification(struct fsl_mc_io	*mc_io,
+					   uint32_t		cmd_flags,
+					   uint16_t		token,
+					   uint8_t		tc_id,
+				struct dpni_congestion_notification_cfg *cfg);
+
+/**
+ * enum dpni_flc_type - DPNI FLC types
+ * @DPNI_FLC_USER_DEFINED: select the FLC to be used for user defined value
+ * @DPNI_FLC_STASH: select the FLC to be used for stash control
+ */
+enum dpni_flc_type {
+	DPNI_FLC_USER_DEFINED = 0,
+	DPNI_FLC_STASH = 1,
+};
+
+/**
+ * enum dpni_stash_size - DPNI FLC stashing size
+ * @DPNI_STASH_SIZE_0B: no stash
+ * @DPNI_STASH_SIZE_64B: stashes 64 bytes
+ * @DPNI_STASH_SIZE_128B: stashes 128 bytes
+ * @DPNI_STASH_SIZE_192B: stashes 192 bytes
+ */
+enum dpni_stash_size {
+	DPNI_STASH_SIZE_0B = 0,
+	DPNI_STASH_SIZE_64B = 1,
+	DPNI_STASH_SIZE_128B = 2,
+	DPNI_STASH_SIZE_192B = 3,
+};
+
+/* DPNI FLC stash options */
+
+/**
+ * stashes the whole annotation area (up to 192 bytes)
+ */
+#define DPNI_FLC_STASH_FRAME_ANNOTATION	0x00000001
+
+/**
+ * struct dpni_flc_cfg - Structure representing DPNI FLC configuration
+ * @flc_type: FLC type
+ * @options: Mask of available options;
+ *	use 'DPNI_FLC_STASH_<X>' values
+ * @frame_data_size: Size of frame data to be stashed
+ * @flow_context_size: Size of flow context to be stashed
+ * @flow_context: 1. In case flc_type is 'DPNI_FLC_USER_DEFINED':
+ *			this value will be provided in the frame descriptor
+ *			(FD[FLC])
+ *		  2. In case flc_type is 'DPNI_FLC_STASH':
+ *			this value will be I/O virtual address of the
+ *			flow-context;
+ *			Must be cacheline-aligned and DMA-able memory
+ */
+struct dpni_flc_cfg {
+	enum dpni_flc_type	flc_type;
+	uint32_t		options;
+	enum dpni_stash_size	frame_data_size;
+	enum dpni_stash_size	flow_context_size;
+	uint64_t		flow_context;
+};
+
+/**
+ * DPNI queue modification options
+ */
+
+/**
+ * Select to modify the user's context associated with the queue
+ */
+#define DPNI_QUEUE_OPT_USER_CTX		0x00000001
+/**
+ * Select to modify the queue's destination
+ */
+#define DPNI_QUEUE_OPT_DEST		0x00000002
+/** Select to modify the flow-context parameters;
+ * not applicable for Tx-conf/Err queues as the FD comes from the user
+ */
+#define DPNI_QUEUE_OPT_FLC		0x00000004
+/**
+ * Select to modify the queue's order preservation
+ */
+#define DPNI_QUEUE_OPT_ORDER_PRESERVATION 0x00000008
+/* Select to modify the queue's tail-drop threshold */
+#define DPNI_QUEUE_OPT_TAILDROP_THRESHOLD 0x00000010
+
+/**
+ * struct dpni_queue_cfg - Structure representing queue configuration
+ * @options: Flags representing the suggested modifications to the queue;
+ *		Use any combination of 'DPNI_QUEUE_OPT_<X>' flags
+ * @user_ctx: User context value provided in the frame descriptor of each
+ *		dequeued frame; valid only if 'DPNI_QUEUE_OPT_USER_CTX'
+ *		is contained in 'options'
+ * @dest_cfg: Queue destination parameters;
+ *		valid only if 'DPNI_QUEUE_OPT_DEST' is contained in 'options'
+ * @flc_cfg: Flow context configuration; in case the TC's distribution
+ *		is either NONE or HASH the FLC's settings of flow#0 are used.
+ *		in the case of FS (flow-steering) the flow's FLC settings
+ *		are used.
+ *		valid only if 'DPNI_QUEUE_OPT_FLC' is contained in 'options'
+ * @order_preservation_en: enable/disable order preservation;
+ *		valid only if 'DPNI_QUEUE_OPT_ORDER_PRESERVATION' is contained
+ *		in 'options'
+ * @tail_drop_threshold: set the queue's tail drop threshold in bytes;
+ *		'0' value disable the threshold; maximum value is 0xE000000;
+ *		valid only if 'DPNI_QUEUE_OPT_TAILDROP_THRESHOLD' is contained
+ *		in 'options'
+ */
+struct dpni_queue_cfg {
+	uint32_t		options;
+	uint64_t		user_ctx;
+	struct dpni_dest_cfg	dest_cfg;
+	struct dpni_flc_cfg	flc_cfg;
+	int			order_preservation_en;
+	uint32_t		tail_drop_threshold;
+};
+
+/**
+ * struct dpni_queue_attr - Structure representing queue attributes
+ * @user_ctx: User context value provided in the frame descriptor of each
+ *	dequeued frame
+ * @dest_cfg: Queue destination configuration
+ * @flc_cfg: Flow context configuration
+ * @order_preservation_en: enable/disable order preservation
+ * @tail_drop_threshold: queue's tail drop threshold in bytes;
+ * @fqid: Virtual fqid value to be used for dequeue operations
+ */
+struct dpni_queue_attr {
+	uint64_t		user_ctx;
+	struct dpni_dest_cfg	dest_cfg;
+	struct dpni_flc_cfg	flc_cfg;
+	int			order_preservation_en;
+	uint32_t		tail_drop_threshold;
+
+	uint32_t		fqid;
+};
+
+/**
+ * DPNI Tx flow modification options
+ */
+
+/**
+ * Select to modify the settings for dedicate Tx confirmation/error
+ */
+#define DPNI_TX_FLOW_OPT_TX_CONF_ERROR	0x00000001
+/**
+ * Select to modify the L3 checksum generation setting
+ */
+#define DPNI_TX_FLOW_OPT_L3_CHKSUM_GEN	0x00000010
+/**
+ * Select to modify the L4 checksum generation setting
+ */
+#define DPNI_TX_FLOW_OPT_L4_CHKSUM_GEN	0x00000020
+
+/**
+ * struct dpni_tx_flow_cfg - Structure representing Tx flow configuration
+ * @options: Flags representing the suggested modifications to the Tx flow;
+ *	Use any combination 'DPNI_TX_FLOW_OPT_<X>' flags
+ * @use_common_tx_conf_queue: Set to '1' to use the common (default) Tx
+ *	confirmation and error queue; Set to '0' to use the private
+ *	Tx confirmation and error queue; valid only if
+ *	'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' wasn't set at DPNI creation
+ *	and 'DPNI_TX_FLOW_OPT_TX_CONF_ERROR' is contained in 'options'
+ * @l3_chksum_gen: Set to '1' to enable L3 checksum generation; '0' to disable;
+ *	valid only if 'DPNI_TX_FLOW_OPT_L3_CHKSUM_GEN' is contained in 'options'
+ * @l4_chksum_gen: Set to '1' to enable L4 checksum generation; '0' to disable;
+ *	valid only if 'DPNI_TX_FLOW_OPT_L4_CHKSUM_GEN' is contained in 'options'
+ */
+struct dpni_tx_flow_cfg {
+	uint32_t	options;
+	int		use_common_tx_conf_queue;
+	int		l3_chksum_gen;
+	int		l4_chksum_gen;
+};
+
+/**
+ * dpni_set_tx_flow() - Set Tx flow configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @flow_id:	Provides (or returns) the sender's flow ID;
+ *	for each new sender set (*flow_id) to 'DPNI_NEW_FLOW_ID' to generate
+ *	a new flow_id;	this ID should be used as the QDBIN argument
+ *	in enqueue operations
+ * @cfg:	Tx flow configuration
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_tx_flow(struct fsl_mc_io			*mc_io,
+		     uint32_t				cmd_flags,
+		     uint16_t				token,
+		     uint16_t				*flow_id,
+		     const struct dpni_tx_flow_cfg	*cfg);
+
+/**
+ * struct dpni_tx_flow_attr - Structure representing Tx flow attributes
+ * @use_common_tx_conf_queue: '1' if using common (default) Tx confirmation and
+ *	error queue; '0' if using private Tx confirmation and error queue
+ * @l3_chksum_gen: '1' if L3 checksum generation is enabled; '0' if disabled
+ * @l4_chksum_gen: '1' if L4 checksum generation is enabled; '0' if disabled
+ */
+struct dpni_tx_flow_attr {
+	int	use_common_tx_conf_queue;
+	int	l3_chksum_gen;
+	int	l4_chksum_gen;
+};
+
+/**
+ * dpni_get_tx_flow() - Get Tx flow attributes
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @flow_id:	The sender's flow ID, as returned by the
+ *	dpni_set_tx_flow() function
+ * @attr:	Returned Tx flow attributes
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_tx_flow(struct fsl_mc_io		*mc_io,
+		     uint32_t			cmd_flags,
+		     uint16_t			token,
+		     uint16_t			flow_id,
+		     struct dpni_tx_flow_attr	*attr);
+
+/**
+ * struct dpni_tx_conf_cfg - Structure representing Tx conf configuration
+ * @errors_only: Set to '1' to report back only error frames;
+ *	Set to '0' to confirm transmission/error for all transmitted frames;
+ * @queue_cfg: Queue configuration
+ */
+struct dpni_tx_conf_cfg {
+	int			errors_only;
+	struct dpni_queue_cfg	queue_cfg;
+};
+
+/**
+ * dpni_set_tx_conf() - Set Tx confirmation and error queue configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @flow_id:	The sender's flow ID, as returned by the
+ *	dpni_set_tx_flow() function;
+ *	use 'DPNI_COMMON_TX_CONF' for common tx-conf
+ * @cfg:	Queue configuration
+ *
+ * If either 'DPNI_OPT_TX_CONF_DISABLED' or
+ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation,
+ * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF';
+ * i.e. only serve the common tx-conf-err queue;
+ * if 'DPNI_OPT_TX_CONF_DISABLED' was selected, only error frames are reported
+ * back - successfully transmitted frames are not confirmed. Otherwise, all
+ * transmitted frames are sent for confirmation.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_tx_conf(struct fsl_mc_io	*mc_io,
+		     uint32_t		cmd_flags,
+		     uint16_t		token,
+		     uint16_t		flow_id,
+		     const struct dpni_tx_conf_cfg	*cfg);
+
+/**
+ * struct dpni_tx_conf_attr - Structure representing Tx conf attributes
+ * @errors_only: '1' if only error frames are reported back; '0' if all
+ *		transmitted frames are confirmed
+ * @queue_attr: Queue attributes
+ */
+struct dpni_tx_conf_attr {
+	int			errors_only;
+	struct dpni_queue_attr	queue_attr;
+};
+
+/**
+ * dpni_get_tx_conf() - Get Tx confirmation and error queue attributes
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @flow_id:	The sender's flow ID, as returned by the
+ *	dpni_set_tx_flow() function;
+ *	use 'DPNI_COMMON_TX_CONF' for common tx-conf
+ * @attr:	Returned tx-conf attributes
+ *
+ * If either 'DPNI_OPT_TX_CONF_DISABLED' or
+ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation,
+ * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF';
+ * i.e. only serve the common tx-conf-err queue;
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_tx_conf(struct fsl_mc_io	*mc_io,
+		     uint32_t		cmd_flags,
+		     uint16_t		token,
+		     uint16_t		flow_id,
+		     struct dpni_tx_conf_attr	*attr);
+
+/**
+ * dpni_set_tx_conf_congestion_notification() - Set Tx conf congestion
+ *	notification configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @flow_id:	The sender's flow ID, as returned by the
+ *	dpni_set_tx_flow() function;
+ *	use 'DPNI_COMMON_TX_CONF' for common tx-conf
+ * @cfg:	congestion notification configuration
+ *
+ * If either 'DPNI_OPT_TX_CONF_DISABLED' or
+ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation,
+ * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF';
+ * i.e. only serve the common tx-conf-err queue;
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_set_tx_conf_congestion_notification(struct fsl_mc_io	*mc_io,
+					     uint32_t		cmd_flags,
+					     uint16_t		token,
+					     uint16_t		flow_id,
+			const struct dpni_congestion_notification_cfg *cfg);
+
+/**
+ * dpni_get_tx_conf_congestion_notification() - Get Tx conf congestion
+ *	notification configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @flow_id:	The sender's flow ID, as returned by the
+ *	dpni_set_tx_flow() function;
+ *	use 'DPNI_COMMON_TX_CONF' for common tx-conf
+ * @cfg:	congestion notification
+ *
+ * If either 'DPNI_OPT_TX_CONF_DISABLED' or
+ * 'DPNI_OPT_PRIVATE_TX_CONF_ERROR_DISABLED' were selected at DPNI creation,
+ * this function can ONLY be used with 'flow_id == DPNI_COMMON_TX_CONF';
+ * i.e. only serve the common tx-conf-err queue;
+ *
+ * Return:	'0' on Success; error code otherwise.
+ */
+int dpni_get_tx_conf_congestion_notification(struct fsl_mc_io	*mc_io,
+					     uint32_t		cmd_flags,
+					     uint16_t		token,
+					     uint16_t		flow_id,
+				struct dpni_congestion_notification_cfg *cfg);
+
+/**
+ * dpni_set_tx_conf_revoke() - Tx confirmation revocation
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @revoke:	revoke or not
+ *
+ * This function is useful only when 'DPNI_OPT_TX_CONF_DISABLED' is not
+ * selected at DPNI creation.
+ * Calling this function with 'revoke' set to '1' disables all transmit
+ * confirmation (including the private confirmation queues), regardless of
+ * previous settings; Note that in this case, Tx error frames are still
+ * enqueued to the general transmit errors queue.
+ * Calling this function with 'revoke' set to '0' restores the previous
+ * settings for both general and private transmit confirmation.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_tx_conf_revoke(struct fsl_mc_io		*mc_io,
+			    uint32_t			cmd_flags,
+			    uint16_t			token,
+			    int			revoke);
+
+/**
+ * dpni_set_rx_flow() - Set Rx flow configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7);
+ *			use 'DPNI_ALL_TCS' to set all TCs and all flows
+ * @flow_id:	Rx flow id within the traffic class; use
+ *			'DPNI_ALL_TC_FLOWS' to set all flows within
+ *			this tc_id; ignored if tc_id is set to
+ *			'DPNI_ALL_TCS';
+ * @cfg:	Rx flow configuration
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_rx_flow(struct fsl_mc_io			*mc_io,
+		     uint32_t				cmd_flags,
+		     uint16_t				token,
+		     uint8_t				tc_id,
+		     uint16_t				flow_id,
+		     const struct dpni_queue_cfg	*cfg);
+
+/**
+ * dpni_get_rx_flow() -	Get Rx flow attributes
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @flow_id:	Rx flow id within the traffic class
+ * @attr:	Returned Rx flow attributes
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_rx_flow(struct fsl_mc_io		*mc_io,
+		     uint32_t			cmd_flags,
+		     uint16_t			token,
+		     uint8_t			tc_id,
+		     uint16_t			flow_id,
+		     struct dpni_queue_attr	*attr);
+
+/**
+ * dpni_set_rx_err_queue() - Set Rx error queue configuration
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @cfg:	Queue configuration
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_rx_err_queue(struct fsl_mc_io		*mc_io,
+			  uint32_t			cmd_flags,
+			  uint16_t			token,
+			  const struct dpni_queue_cfg	*cfg);
+
+/**
+ * dpni_get_rx_err_queue() - Get Rx error queue attributes
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @attr:	Returned Queue attributes
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_get_rx_err_queue(struct fsl_mc_io		*mc_io,
+			  uint32_t			cmd_flags,
+			  uint16_t			token,
+			  struct dpni_queue_attr	*attr);
+
+/**
+ * struct dpni_qos_tbl_cfg - Structure representing QOS table configuration
+ * @key_cfg_iova: I/O virtual address of 256 bytes DMA-able memory filled with
+ *		key extractions to be used as the QoS criteria by calling
+ *		dpni_prepare_key_cfg()
+ * @discard_on_miss: Set to '1' to discard frames in case of no match (miss);
+ *		'0' to use the 'default_tc' in such cases
+ * @default_tc: Used in case of no-match and 'discard_on_miss'= 0
+ */
+struct dpni_qos_tbl_cfg {
+	uint64_t	key_cfg_iova;
+	int		discard_on_miss;
+	uint8_t	default_tc;
+};
+
+/**
+ * dpni_set_qos_table() - Set QoS mapping table
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @cfg:	QoS table configuration
+ *
+ * This function and all QoS-related functions require that
+ *'max_tcs > 1' was set at DPNI creation.
+ *
+ * warning: Before calling this function, call dpni_prepare_key_cfg() to
+ *			prepare the key_cfg_iova parameter
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_qos_table(struct fsl_mc_io		*mc_io,
+		       uint32_t			cmd_flags,
+		       uint16_t				token,
+		       const struct dpni_qos_tbl_cfg	*cfg);
+
+/**
+ * struct dpni_rule_cfg - Rule configuration for table lookup
+ * @key_iova: I/O virtual address of the key (must be in DMA-able memory)
+ * @mask_iova: I/O virtual address of the mask (must be in DMA-able memory)
+ * @key_size: key and mask size (in bytes)
+ */
+struct dpni_rule_cfg {
+	uint64_t	key_iova;
+	uint64_t	mask_iova;
+	uint8_t	key_size;
+};
+
+/**
+ * dpni_add_qos_entry() - Add QoS mapping entry (to select a traffic class)
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @cfg:	QoS rule to add
+ * @tc_id:	Traffic class selection (0-7)
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_add_qos_entry(struct fsl_mc_io		*mc_io,
+		       uint32_t			cmd_flags,
+		       uint16_t				token,
+		       const struct dpni_rule_cfg	*cfg,
+		       uint8_t				tc_id);
+
+/**
+ * dpni_remove_qos_entry() - Remove QoS mapping entry
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @cfg:	QoS rule to remove
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_remove_qos_entry(struct fsl_mc_io		*mc_io,
+			  uint32_t			cmd_flags,
+			  uint16_t			token,
+			  const struct dpni_rule_cfg	*cfg);
+
+/**
+ * dpni_clear_qos_table() - Clear all QoS mapping entries
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ *
+ * Following this function call, all frames are directed to
+ * the default traffic class (0)
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_clear_qos_table(struct fsl_mc_io	*mc_io,
+			 uint32_t		cmd_flags,
+			 uint16_t		token);
+
+/**
+ * dpni_add_fs_entry() - Add Flow Steering entry for a specific traffic class
+ *			(to select a flow ID)
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @cfg:	Flow steering rule to add
+ * @flow_id:	Flow id selection (must be smaller than the
+ *			distribution size of the traffic class)
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_add_fs_entry(struct fsl_mc_io			*mc_io,
+		      uint32_t				cmd_flags,
+		      uint16_t				token,
+		      uint8_t				tc_id,
+		      const struct dpni_rule_cfg	*cfg,
+		      uint16_t				flow_id);
+
+/**
+ * dpni_remove_fs_entry() - Remove Flow Steering entry from a specific
+ *			traffic class
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ * @cfg:	Flow steering rule to remove
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_remove_fs_entry(struct fsl_mc_io		*mc_io,
+			 uint32_t			cmd_flags,
+			 uint16_t			token,
+			 uint8_t			tc_id,
+			 const struct dpni_rule_cfg	*cfg);
+
+/**
+ * dpni_clear_fs_entries() - Clear all Flow Steering entries of a specific
+ *			traffic class
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @tc_id:	Traffic class selection (0-7)
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_clear_fs_entries(struct fsl_mc_io	*mc_io,
+			  uint32_t		cmd_flags,
+			  uint16_t		token,
+			  uint8_t		tc_id);
+
+/**
+ * dpni_set_vlan_insertion() - Enable/disable VLAN insertion for egress frames
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Set to '1' to enable; '0' to disable
+ *
+ * Requires that the 'DPNI_OPT_VLAN_MANIPULATION' option is set
+ * at DPNI creation.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_vlan_insertion(struct fsl_mc_io	*mc_io,
+			    uint32_t		cmd_flags,
+			    uint16_t		token,
+			    int		en);
+
+/**
+ * dpni_set_vlan_removal() - Enable/disable VLAN removal for ingress frames
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Set to '1' to enable; '0' to disable
+ *
+ * Requires that the 'DPNI_OPT_VLAN_MANIPULATION' option is set
+ * at DPNI creation.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_vlan_removal(struct fsl_mc_io	*mc_io,
+			  uint32_t		cmd_flags,
+			  uint16_t		token,
+			  int			en);
+
+/**
+ * dpni_set_ipr() - Enable/disable IP reassembly of ingress frames
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Set to '1' to enable; '0' to disable
+ *
+ * Requires that the 'DPNI_OPT_IPR' option is set at DPNI creation.
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_ipr(struct fsl_mc_io	*mc_io,
+		 uint32_t		cmd_flags,
+		 uint16_t		token,
+		 int			en);
+
+/**
+ * dpni_set_ipf() - Enable/disable IP fragmentation of egress frames
+ * @mc_io:	Pointer to MC portal's I/O object
+ * @cmd_flags:	Command flags; one or more of 'MC_CMD_FLAG_'
+ * @token:	Token of DPNI object
+ * @en:		Set to '1' to enable; '0' to disable
+ *
+ * Requires that the 'DPNI_OPT_IPF' option is set at DPNI
+ * creation. Fragmentation is performed according to MTU value
+ * set by dpni_set_mtu() function
+ *
+ * Return:	'0' on Success; Error code otherwise.
+ */
+int dpni_set_ipf(struct fsl_mc_io	*mc_io,
+		 uint32_t		cmd_flags,
+		 uint16_t		token,
+		 int			en);
+
+#endif /* __FSL_DPNI_H */
--- a/drivers/staging/fsl-mc/include/mc-cmd.h
+++ b/drivers/staging/fsl-mc/include/mc-cmd.h
@@ -103,8 +103,11 @@ enum mc_cmd_status {
 #define MC_CMD_HDR_READ_FLAGS(_hdr) \
 	((u32)mc_dec((_hdr), MC_CMD_HDR_FLAGS_O, MC_CMD_HDR_FLAGS_S))
 
+#define MC_PREP_OP(_ext, _param, _offset, _width, _type, _arg) \
+	((_ext)[_param] |= cpu_to_le64(mc_enc((_offset), (_width), _arg)))
+
 #define MC_EXT_OP(_ext, _param, _offset, _width, _type, _arg) \
-	((_ext)[_param] |= mc_enc((_offset), (_width), _arg))
+	(_arg = (_type)mc_dec(cpu_to_le64(_ext[_param]), (_offset), (_width)))
 
 #define MC_CMD_OP(_cmd, _param, _offset, _width, _type, _arg) \
 	((_cmd).params[_param] |= mc_enc((_offset), (_width), _arg))
--- /dev/null
+++ b/drivers/staging/fsl-mc/include/net.h
@@ -0,0 +1,481 @@
+/* Copyright 2013-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the above-listed copyright holders nor the
+ * names of any contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __FSL_NET_H
+#define __FSL_NET_H
+
+#define LAST_HDR_INDEX 0xFFFFFFFF
+
+/*****************************************************************************/
+/*                Protocol fields                                            */
+/*****************************************************************************/
+
+/*************************  Ethernet fields  *********************************/
+#define NH_FLD_ETH_DA                         (1)
+#define NH_FLD_ETH_SA                         (NH_FLD_ETH_DA << 1)
+#define NH_FLD_ETH_LENGTH                     (NH_FLD_ETH_DA << 2)
+#define NH_FLD_ETH_TYPE                       (NH_FLD_ETH_DA << 3)
+#define NH_FLD_ETH_FINAL_CKSUM                (NH_FLD_ETH_DA << 4)
+#define NH_FLD_ETH_PADDING                    (NH_FLD_ETH_DA << 5)
+#define NH_FLD_ETH_ALL_FIELDS                 ((NH_FLD_ETH_DA << 6) - 1)
+
+#define NH_FLD_ETH_ADDR_SIZE                 6
+
+/***************************  VLAN fields  ***********************************/
+#define NH_FLD_VLAN_VPRI                      (1)
+#define NH_FLD_VLAN_CFI                       (NH_FLD_VLAN_VPRI << 1)
+#define NH_FLD_VLAN_VID                       (NH_FLD_VLAN_VPRI << 2)
+#define NH_FLD_VLAN_LENGTH                    (NH_FLD_VLAN_VPRI << 3)
+#define NH_FLD_VLAN_TYPE                      (NH_FLD_VLAN_VPRI << 4)
+#define NH_FLD_VLAN_ALL_FIELDS                ((NH_FLD_VLAN_VPRI << 5) - 1)
+
+#define NH_FLD_VLAN_TCI                       (NH_FLD_VLAN_VPRI | \
+					       NH_FLD_VLAN_CFI | \
+					       NH_FLD_VLAN_VID)
+
+/************************  IP (generic) fields  ******************************/
+#define NH_FLD_IP_VER                         (1)
+#define NH_FLD_IP_DSCP                        (NH_FLD_IP_VER << 2)
+#define NH_FLD_IP_ECN                         (NH_FLD_IP_VER << 3)
+#define NH_FLD_IP_PROTO                       (NH_FLD_IP_VER << 4)
+#define NH_FLD_IP_SRC                         (NH_FLD_IP_VER << 5)
+#define NH_FLD_IP_DST                         (NH_FLD_IP_VER << 6)
+#define NH_FLD_IP_TOS_TC                      (NH_FLD_IP_VER << 7)
+#define NH_FLD_IP_ID                          (NH_FLD_IP_VER << 8)
+#define NH_FLD_IP_ALL_FIELDS                  ((NH_FLD_IP_VER << 9) - 1)
+
+#define NH_FLD_IP_PROTO_SIZE                  1
+
+/*****************************  IPV4 fields  *********************************/
+#define NH_FLD_IPV4_VER                       (1)
+#define NH_FLD_IPV4_HDR_LEN                   (NH_FLD_IPV4_VER << 1)
+#define NH_FLD_IPV4_TOS                       (NH_FLD_IPV4_VER << 2)
+#define NH_FLD_IPV4_TOTAL_LEN                 (NH_FLD_IPV4_VER << 3)
+#define NH_FLD_IPV4_ID                        (NH_FLD_IPV4_VER << 4)
+#define NH_FLD_IPV4_FLAG_D                    (NH_FLD_IPV4_VER << 5)
+#define NH_FLD_IPV4_FLAG_M                    (NH_FLD_IPV4_VER << 6)
+#define NH_FLD_IPV4_OFFSET                    (NH_FLD_IPV4_VER << 7)
+#define NH_FLD_IPV4_TTL                       (NH_FLD_IPV4_VER << 8)
+#define NH_FLD_IPV4_PROTO                     (NH_FLD_IPV4_VER << 9)
+#define NH_FLD_IPV4_CKSUM                     (NH_FLD_IPV4_VER << 10)
+#define NH_FLD_IPV4_SRC_IP                    (NH_FLD_IPV4_VER << 11)
+#define NH_FLD_IPV4_DST_IP                    (NH_FLD_IPV4_VER << 12)
+#define NH_FLD_IPV4_OPTS                      (NH_FLD_IPV4_VER << 13)
+#define NH_FLD_IPV4_OPTS_COUNT                (NH_FLD_IPV4_VER << 14)
+#define NH_FLD_IPV4_ALL_FIELDS                ((NH_FLD_IPV4_VER << 15) - 1)
+
+#define NH_FLD_IPV4_ADDR_SIZE                 4
+#define NH_FLD_IPV4_PROTO_SIZE                1
+
+/*****************************  IPV6 fields  *********************************/
+#define NH_FLD_IPV6_VER                       (1)
+#define NH_FLD_IPV6_TC                        (NH_FLD_IPV6_VER << 1)
+#define NH_FLD_IPV6_SRC_IP                    (NH_FLD_IPV6_VER << 2)
+#define NH_FLD_IPV6_DST_IP                    (NH_FLD_IPV6_VER << 3)
+#define NH_FLD_IPV6_NEXT_HDR                  (NH_FLD_IPV6_VER << 4)
+#define NH_FLD_IPV6_FL                        (NH_FLD_IPV6_VER << 5)
+#define NH_FLD_IPV6_HOP_LIMIT                 (NH_FLD_IPV6_VER << 6)
+#define NH_FLD_IPV6_ID			      (NH_FLD_IPV6_VER << 7)
+#define NH_FLD_IPV6_ALL_FIELDS                ((NH_FLD_IPV6_VER << 8) - 1)
+
+#define NH_FLD_IPV6_ADDR_SIZE                 16
+#define NH_FLD_IPV6_NEXT_HDR_SIZE             1
+
+/*****************************  ICMP fields  *********************************/
+#define NH_FLD_ICMP_TYPE                      (1)
+#define NH_FLD_ICMP_CODE                      (NH_FLD_ICMP_TYPE << 1)
+#define NH_FLD_ICMP_CKSUM                     (NH_FLD_ICMP_TYPE << 2)
+#define NH_FLD_ICMP_ID                        (NH_FLD_ICMP_TYPE << 3)
+#define NH_FLD_ICMP_SQ_NUM                    (NH_FLD_ICMP_TYPE << 4)
+#define NH_FLD_ICMP_ALL_FIELDS                ((NH_FLD_ICMP_TYPE << 5) - 1)
+
+#define NH_FLD_ICMP_CODE_SIZE                 1
+#define NH_FLD_ICMP_TYPE_SIZE                 1
+
+/*****************************  IGMP fields  *********************************/
+#define NH_FLD_IGMP_VERSION                   (1)
+#define NH_FLD_IGMP_TYPE                      (NH_FLD_IGMP_VERSION << 1)
+#define NH_FLD_IGMP_CKSUM                     (NH_FLD_IGMP_VERSION << 2)
+#define NH_FLD_IGMP_DATA                      (NH_FLD_IGMP_VERSION << 3)
+#define NH_FLD_IGMP_ALL_FIELDS                ((NH_FLD_IGMP_VERSION << 4) - 1)
+
+/*****************************  TCP fields  **********************************/
+#define NH_FLD_TCP_PORT_SRC                   (1)
+#define NH_FLD_TCP_PORT_DST                   (NH_FLD_TCP_PORT_SRC << 1)
+#define NH_FLD_TCP_SEQ                        (NH_FLD_TCP_PORT_SRC << 2)
+#define NH_FLD_TCP_ACK                        (NH_FLD_TCP_PORT_SRC << 3)
+#define NH_FLD_TCP_OFFSET                     (NH_FLD_TCP_PORT_SRC << 4)
+#define NH_FLD_TCP_FLAGS                      (NH_FLD_TCP_PORT_SRC << 5)
+#define NH_FLD_TCP_WINDOW                     (NH_FLD_TCP_PORT_SRC << 6)
+#define NH_FLD_TCP_CKSUM                      (NH_FLD_TCP_PORT_SRC << 7)
+#define NH_FLD_TCP_URGPTR                     (NH_FLD_TCP_PORT_SRC << 8)
+#define NH_FLD_TCP_OPTS                       (NH_FLD_TCP_PORT_SRC << 9)
+#define NH_FLD_TCP_OPTS_COUNT                 (NH_FLD_TCP_PORT_SRC << 10)
+#define NH_FLD_TCP_ALL_FIELDS                 ((NH_FLD_TCP_PORT_SRC << 11) - 1)
+
+#define NH_FLD_TCP_PORT_SIZE                  2
+
+/*****************************  UDP fields  **********************************/
+#define NH_FLD_UDP_PORT_SRC                   (1)
+#define NH_FLD_UDP_PORT_DST                   (NH_FLD_UDP_PORT_SRC << 1)
+#define NH_FLD_UDP_LEN                        (NH_FLD_UDP_PORT_SRC << 2)
+#define NH_FLD_UDP_CKSUM                      (NH_FLD_UDP_PORT_SRC << 3)
+#define NH_FLD_UDP_ALL_FIELDS                 ((NH_FLD_UDP_PORT_SRC << 4) - 1)
+
+#define NH_FLD_UDP_PORT_SIZE                  2
+
+/***************************  UDP-lite fields  *******************************/
+#define NH_FLD_UDP_LITE_PORT_SRC              (1)
+#define NH_FLD_UDP_LITE_PORT_DST              (NH_FLD_UDP_LITE_PORT_SRC << 1)
+#define NH_FLD_UDP_LITE_ALL_FIELDS \
+	((NH_FLD_UDP_LITE_PORT_SRC << 2) - 1)
+
+#define NH_FLD_UDP_LITE_PORT_SIZE             2
+
+/***************************  UDP-encap-ESP fields  **************************/
+#define NH_FLD_UDP_ENC_ESP_PORT_SRC         (1)
+#define NH_FLD_UDP_ENC_ESP_PORT_DST         (NH_FLD_UDP_ENC_ESP_PORT_SRC << 1)
+#define NH_FLD_UDP_ENC_ESP_LEN              (NH_FLD_UDP_ENC_ESP_PORT_SRC << 2)
+#define NH_FLD_UDP_ENC_ESP_CKSUM            (NH_FLD_UDP_ENC_ESP_PORT_SRC << 3)
+#define NH_FLD_UDP_ENC_ESP_SPI              (NH_FLD_UDP_ENC_ESP_PORT_SRC << 4)
+#define NH_FLD_UDP_ENC_ESP_SEQUENCE_NUM     (NH_FLD_UDP_ENC_ESP_PORT_SRC << 5)
+#define NH_FLD_UDP_ENC_ESP_ALL_FIELDS \
+	((NH_FLD_UDP_ENC_ESP_PORT_SRC << 6) - 1)
+
+#define NH_FLD_UDP_ENC_ESP_PORT_SIZE        2
+#define NH_FLD_UDP_ENC_ESP_SPI_SIZE         4
+
+/*****************************  SCTP fields  *********************************/
+#define NH_FLD_SCTP_PORT_SRC                  (1)
+#define NH_FLD_SCTP_PORT_DST                  (NH_FLD_SCTP_PORT_SRC << 1)
+#define NH_FLD_SCTP_VER_TAG                   (NH_FLD_SCTP_PORT_SRC << 2)
+#define NH_FLD_SCTP_CKSUM                     (NH_FLD_SCTP_PORT_SRC << 3)
+#define NH_FLD_SCTP_ALL_FIELDS                ((NH_FLD_SCTP_PORT_SRC << 4) - 1)
+
+#define NH_FLD_SCTP_PORT_SIZE                 2
+
+/*****************************  DCCP fields  *********************************/
+#define NH_FLD_DCCP_PORT_SRC                  (1)
+#define NH_FLD_DCCP_PORT_DST                  (NH_FLD_DCCP_PORT_SRC << 1)
+#define NH_FLD_DCCP_ALL_FIELDS                ((NH_FLD_DCCP_PORT_SRC << 2) - 1)
+
+#define NH_FLD_DCCP_PORT_SIZE                 2
+
+/*****************************  IPHC fields  *********************************/
+#define NH_FLD_IPHC_CID                       (1)
+#define NH_FLD_IPHC_CID_TYPE                  (NH_FLD_IPHC_CID << 1)
+#define NH_FLD_IPHC_HCINDEX                   (NH_FLD_IPHC_CID << 2)
+#define NH_FLD_IPHC_GEN                       (NH_FLD_IPHC_CID << 3)
+#define NH_FLD_IPHC_D_BIT                     (NH_FLD_IPHC_CID << 4)
+#define NH_FLD_IPHC_ALL_FIELDS                ((NH_FLD_IPHC_CID << 5) - 1)
+
+/*****************************  SCTP fields  *********************************/
+#define NH_FLD_SCTP_CHUNK_DATA_TYPE           (1)
+#define NH_FLD_SCTP_CHUNK_DATA_FLAGS          (NH_FLD_SCTP_CHUNK_DATA_TYPE << 1)
+#define NH_FLD_SCTP_CHUNK_DATA_LENGTH         (NH_FLD_SCTP_CHUNK_DATA_TYPE << 2)
+#define NH_FLD_SCTP_CHUNK_DATA_TSN            (NH_FLD_SCTP_CHUNK_DATA_TYPE << 3)
+#define NH_FLD_SCTP_CHUNK_DATA_STREAM_ID      (NH_FLD_SCTP_CHUNK_DATA_TYPE << 4)
+#define NH_FLD_SCTP_CHUNK_DATA_STREAM_SQN     (NH_FLD_SCTP_CHUNK_DATA_TYPE << 5)
+#define NH_FLD_SCTP_CHUNK_DATA_PAYLOAD_PID    (NH_FLD_SCTP_CHUNK_DATA_TYPE << 6)
+#define NH_FLD_SCTP_CHUNK_DATA_UNORDERED      (NH_FLD_SCTP_CHUNK_DATA_TYPE << 7)
+#define NH_FLD_SCTP_CHUNK_DATA_BEGGINING      (NH_FLD_SCTP_CHUNK_DATA_TYPE << 8)
+#define NH_FLD_SCTP_CHUNK_DATA_END            (NH_FLD_SCTP_CHUNK_DATA_TYPE << 9)
+#define NH_FLD_SCTP_CHUNK_DATA_ALL_FIELDS \
+	((NH_FLD_SCTP_CHUNK_DATA_TYPE << 10) - 1)
+
+/***************************  L2TPV2 fields  *********************************/
+#define NH_FLD_L2TPV2_TYPE_BIT                (1)
+#define NH_FLD_L2TPV2_LENGTH_BIT              (NH_FLD_L2TPV2_TYPE_BIT << 1)
+#define NH_FLD_L2TPV2_SEQUENCE_BIT            (NH_FLD_L2TPV2_TYPE_BIT << 2)
+#define NH_FLD_L2TPV2_OFFSET_BIT              (NH_FLD_L2TPV2_TYPE_BIT << 3)
+#define NH_FLD_L2TPV2_PRIORITY_BIT            (NH_FLD_L2TPV2_TYPE_BIT << 4)
+#define NH_FLD_L2TPV2_VERSION                 (NH_FLD_L2TPV2_TYPE_BIT << 5)
+#define NH_FLD_L2TPV2_LEN                     (NH_FLD_L2TPV2_TYPE_BIT << 6)
+#define NH_FLD_L2TPV2_TUNNEL_ID               (NH_FLD_L2TPV2_TYPE_BIT << 7)
+#define NH_FLD_L2TPV2_SESSION_ID              (NH_FLD_L2TPV2_TYPE_BIT << 8)
+#define NH_FLD_L2TPV2_NS                      (NH_FLD_L2TPV2_TYPE_BIT << 9)
+#define NH_FLD_L2TPV2_NR                      (NH_FLD_L2TPV2_TYPE_BIT << 10)
+#define NH_FLD_L2TPV2_OFFSET_SIZE             (NH_FLD_L2TPV2_TYPE_BIT << 11)
+#define NH_FLD_L2TPV2_FIRST_BYTE              (NH_FLD_L2TPV2_TYPE_BIT << 12)
+#define NH_FLD_L2TPV2_ALL_FIELDS \
+	((NH_FLD_L2TPV2_TYPE_BIT << 13) - 1)
+
+/***************************  L2TPV3 fields  *********************************/
+#define NH_FLD_L2TPV3_CTRL_TYPE_BIT           (1)
+#define NH_FLD_L2TPV3_CTRL_LENGTH_BIT         (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 1)
+#define NH_FLD_L2TPV3_CTRL_SEQUENCE_BIT       (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 2)
+#define NH_FLD_L2TPV3_CTRL_VERSION            (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 3)
+#define NH_FLD_L2TPV3_CTRL_LENGTH             (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 4)
+#define NH_FLD_L2TPV3_CTRL_CONTROL            (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 5)
+#define NH_FLD_L2TPV3_CTRL_SENT               (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 6)
+#define NH_FLD_L2TPV3_CTRL_RECV               (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 7)
+#define NH_FLD_L2TPV3_CTRL_FIRST_BYTE         (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 8)
+#define NH_FLD_L2TPV3_CTRL_ALL_FIELDS \
+	((NH_FLD_L2TPV3_CTRL_TYPE_BIT << 9) - 1)
+
+#define NH_FLD_L2TPV3_SESS_TYPE_BIT           (1)
+#define NH_FLD_L2TPV3_SESS_VERSION            (NH_FLD_L2TPV3_SESS_TYPE_BIT << 1)
+#define NH_FLD_L2TPV3_SESS_ID                 (NH_FLD_L2TPV3_SESS_TYPE_BIT << 2)
+#define NH_FLD_L2TPV3_SESS_COOKIE             (NH_FLD_L2TPV3_SESS_TYPE_BIT << 3)
+#define NH_FLD_L2TPV3_SESS_ALL_FIELDS \
+	((NH_FLD_L2TPV3_SESS_TYPE_BIT << 4) - 1)
+
+/****************************  PPP fields  ***********************************/
+#define NH_FLD_PPP_PID                        (1)
+#define NH_FLD_PPP_COMPRESSED                 (NH_FLD_PPP_PID << 1)
+#define NH_FLD_PPP_ALL_FIELDS                 ((NH_FLD_PPP_PID << 2) - 1)
+
+/**************************  PPPoE fields  ***********************************/
+#define NH_FLD_PPPOE_VER                      (1)
+#define NH_FLD_PPPOE_TYPE                     (NH_FLD_PPPOE_VER << 1)
+#define NH_FLD_PPPOE_CODE                     (NH_FLD_PPPOE_VER << 2)
+#define NH_FLD_PPPOE_SID                      (NH_FLD_PPPOE_VER << 3)
+#define NH_FLD_PPPOE_LEN                      (NH_FLD_PPPOE_VER << 4)
+#define NH_FLD_PPPOE_SESSION                  (NH_FLD_PPPOE_VER << 5)
+#define NH_FLD_PPPOE_PID                      (NH_FLD_PPPOE_VER << 6)
+#define NH_FLD_PPPOE_ALL_FIELDS               ((NH_FLD_PPPOE_VER << 7) - 1)
+
+/*************************  PPP-Mux fields  **********************************/
+#define NH_FLD_PPPMUX_PID                     (1)
+#define NH_FLD_PPPMUX_CKSUM                   (NH_FLD_PPPMUX_PID << 1)
+#define NH_FLD_PPPMUX_COMPRESSED              (NH_FLD_PPPMUX_PID << 2)
+#define NH_FLD_PPPMUX_ALL_FIELDS              ((NH_FLD_PPPMUX_PID << 3) - 1)
+
+/***********************  PPP-Mux sub-frame fields  **************************/
+#define NH_FLD_PPPMUX_SUBFRM_PFF            (1)
+#define NH_FLD_PPPMUX_SUBFRM_LXT            (NH_FLD_PPPMUX_SUBFRM_PFF << 1)
+#define NH_FLD_PPPMUX_SUBFRM_LEN            (NH_FLD_PPPMUX_SUBFRM_PFF << 2)
+#define NH_FLD_PPPMUX_SUBFRM_PID            (NH_FLD_PPPMUX_SUBFRM_PFF << 3)
+#define NH_FLD_PPPMUX_SUBFRM_USE_PID        (NH_FLD_PPPMUX_SUBFRM_PFF << 4)
+#define NH_FLD_PPPMUX_SUBFRM_ALL_FIELDS \
+	((NH_FLD_PPPMUX_SUBFRM_PFF << 5) - 1)
+
+/***************************  LLC fields  ************************************/
+#define NH_FLD_LLC_DSAP                       (1)
+#define NH_FLD_LLC_SSAP                       (NH_FLD_LLC_DSAP << 1)
+#define NH_FLD_LLC_CTRL                       (NH_FLD_LLC_DSAP << 2)
+#define NH_FLD_LLC_ALL_FIELDS                 ((NH_FLD_LLC_DSAP << 3) - 1)
+
+/***************************  NLPID fields  **********************************/
+#define NH_FLD_NLPID_NLPID                    (1)
+#define NH_FLD_NLPID_ALL_FIELDS               ((NH_FLD_NLPID_NLPID << 1) - 1)
+
+/***************************  SNAP fields  ***********************************/
+#define NH_FLD_SNAP_OUI                       (1)
+#define NH_FLD_SNAP_PID                       (NH_FLD_SNAP_OUI << 1)
+#define NH_FLD_SNAP_ALL_FIELDS                ((NH_FLD_SNAP_OUI << 2) - 1)
+
+/***************************  LLC SNAP fields  *******************************/
+#define NH_FLD_LLC_SNAP_TYPE                  (1)
+#define NH_FLD_LLC_SNAP_ALL_FIELDS            ((NH_FLD_LLC_SNAP_TYPE << 1) - 1)
+
+#define NH_FLD_ARP_HTYPE                      (1)
+#define NH_FLD_ARP_PTYPE                      (NH_FLD_ARP_HTYPE << 1)
+#define NH_FLD_ARP_HLEN                       (NH_FLD_ARP_HTYPE << 2)
+#define NH_FLD_ARP_PLEN                       (NH_FLD_ARP_HTYPE << 3)
+#define NH_FLD_ARP_OPER                       (NH_FLD_ARP_HTYPE << 4)
+#define NH_FLD_ARP_SHA                        (NH_FLD_ARP_HTYPE << 5)
+#define NH_FLD_ARP_SPA                        (NH_FLD_ARP_HTYPE << 6)
+#define NH_FLD_ARP_THA                        (NH_FLD_ARP_HTYPE << 7)
+#define NH_FLD_ARP_TPA                        (NH_FLD_ARP_HTYPE << 8)
+#define NH_FLD_ARP_ALL_FIELDS                 ((NH_FLD_ARP_HTYPE << 9) - 1)
+
+/***************************  RFC2684 fields  ********************************/
+#define NH_FLD_RFC2684_LLC                    (1)
+#define NH_FLD_RFC2684_NLPID                  (NH_FLD_RFC2684_LLC << 1)
+#define NH_FLD_RFC2684_OUI                    (NH_FLD_RFC2684_LLC << 2)
+#define NH_FLD_RFC2684_PID                    (NH_FLD_RFC2684_LLC << 3)
+#define NH_FLD_RFC2684_VPN_OUI                (NH_FLD_RFC2684_LLC << 4)
+#define NH_FLD_RFC2684_VPN_IDX                (NH_FLD_RFC2684_LLC << 5)
+#define NH_FLD_RFC2684_ALL_FIELDS             ((NH_FLD_RFC2684_LLC << 6) - 1)
+
+/***************************  User defined fields  ***************************/
+#define NH_FLD_USER_DEFINED_SRCPORT           (1)
+#define NH_FLD_USER_DEFINED_PCDID             (NH_FLD_USER_DEFINED_SRCPORT << 1)
+#define NH_FLD_USER_DEFINED_ALL_FIELDS \
+	((NH_FLD_USER_DEFINED_SRCPORT << 2) - 1)
+
+/***************************  Payload fields  ********************************/
+#define NH_FLD_PAYLOAD_BUFFER                 (1)
+#define NH_FLD_PAYLOAD_SIZE                   (NH_FLD_PAYLOAD_BUFFER << 1)
+#define NH_FLD_MAX_FRM_SIZE                   (NH_FLD_PAYLOAD_BUFFER << 2)
+#define NH_FLD_MIN_FRM_SIZE                   (NH_FLD_PAYLOAD_BUFFER << 3)
+#define NH_FLD_PAYLOAD_TYPE                   (NH_FLD_PAYLOAD_BUFFER << 4)
+#define NH_FLD_FRAME_SIZE                     (NH_FLD_PAYLOAD_BUFFER << 5)
+#define NH_FLD_PAYLOAD_ALL_FIELDS             ((NH_FLD_PAYLOAD_BUFFER << 6) - 1)
+
+/***************************  GRE fields  ************************************/
+#define NH_FLD_GRE_TYPE                       (1)
+#define NH_FLD_GRE_ALL_FIELDS                 ((NH_FLD_GRE_TYPE << 1) - 1)
+
+/***************************  MINENCAP fields  *******************************/
+#define NH_FLD_MINENCAP_SRC_IP                (1)
+#define NH_FLD_MINENCAP_DST_IP                (NH_FLD_MINENCAP_SRC_IP << 1)
+#define NH_FLD_MINENCAP_TYPE                  (NH_FLD_MINENCAP_SRC_IP << 2)
+#define NH_FLD_MINENCAP_ALL_FIELDS \
+	((NH_FLD_MINENCAP_SRC_IP << 3) - 1)
+
+/***************************  IPSEC AH fields  *******************************/
+#define NH_FLD_IPSEC_AH_SPI                   (1)
+#define NH_FLD_IPSEC_AH_NH                    (NH_FLD_IPSEC_AH_SPI << 1)
+#define NH_FLD_IPSEC_AH_ALL_FIELDS            ((NH_FLD_IPSEC_AH_SPI << 2) - 1)
+
+/***************************  IPSEC ESP fields  ******************************/
+#define NH_FLD_IPSEC_ESP_SPI                  (1)
+#define NH_FLD_IPSEC_ESP_SEQUENCE_NUM         (NH_FLD_IPSEC_ESP_SPI << 1)
+#define NH_FLD_IPSEC_ESP_ALL_FIELDS           ((NH_FLD_IPSEC_ESP_SPI << 2) - 1)
+
+#define NH_FLD_IPSEC_ESP_SPI_SIZE             4
+
+/***************************  MPLS fields  ***********************************/
+#define NH_FLD_MPLS_LABEL_STACK               (1)
+#define NH_FLD_MPLS_LABEL_STACK_ALL_FIELDS \
+	((NH_FLD_MPLS_LABEL_STACK << 1) - 1)
+
+/***************************  MACSEC fields  *********************************/
+#define NH_FLD_MACSEC_SECTAG                  (1)
+#define NH_FLD_MACSEC_ALL_FIELDS              ((NH_FLD_MACSEC_SECTAG << 1) - 1)
+
+/***************************  GTP fields  ************************************/
+#define NH_FLD_GTP_TEID                       (1)
+
+
+/* Protocol options */
+
+/* Ethernet options */
+#define	NH_OPT_ETH_BROADCAST			1
+#define	NH_OPT_ETH_MULTICAST			2
+#define	NH_OPT_ETH_UNICAST			3
+#define	NH_OPT_ETH_BPDU				4
+
+#define NH_ETH_IS_MULTICAST_ADDR(addr) (addr[0] & 0x01)
+/* also applicable for broadcast */
+
+/* VLAN options */
+#define	NH_OPT_VLAN_CFI				1
+
+/* IPV4 options */
+#define	NH_OPT_IPV4_UNICAST			1
+#define	NH_OPT_IPV4_MULTICAST			2
+#define	NH_OPT_IPV4_BROADCAST			3
+#define	NH_OPT_IPV4_OPTION			4
+#define	NH_OPT_IPV4_FRAG			5
+#define	NH_OPT_IPV4_INITIAL_FRAG		6
+
+/* IPV6 options */
+#define	NH_OPT_IPV6_UNICAST			1
+#define	NH_OPT_IPV6_MULTICAST			2
+#define	NH_OPT_IPV6_OPTION			3
+#define	NH_OPT_IPV6_FRAG			4
+#define	NH_OPT_IPV6_INITIAL_FRAG		5
+
+/* General IP options (may be used for any version) */
+#define	NH_OPT_IP_FRAG				1
+#define	NH_OPT_IP_INITIAL_FRAG			2
+#define	NH_OPT_IP_OPTION			3
+
+/* Minenc. options */
+#define	NH_OPT_MINENCAP_SRC_ADDR_PRESENT	1
+
+/* GRE. options */
+#define	NH_OPT_GRE_ROUTING_PRESENT		1
+
+/* TCP options */
+#define	NH_OPT_TCP_OPTIONS			1
+#define	NH_OPT_TCP_CONTROL_HIGH_BITS		2
+#define	NH_OPT_TCP_CONTROL_LOW_BITS		3
+
+/* CAPWAP options */
+#define	NH_OPT_CAPWAP_DTLS			1
+
+enum net_prot {
+	NET_PROT_NONE = 0,
+	NET_PROT_PAYLOAD,
+	NET_PROT_ETH,
+	NET_PROT_VLAN,
+	NET_PROT_IPV4,
+	NET_PROT_IPV6,
+	NET_PROT_IP,
+	NET_PROT_TCP,
+	NET_PROT_UDP,
+	NET_PROT_UDP_LITE,
+	NET_PROT_IPHC,
+	NET_PROT_SCTP,
+	NET_PROT_SCTP_CHUNK_DATA,
+	NET_PROT_PPPOE,
+	NET_PROT_PPP,
+	NET_PROT_PPPMUX,
+	NET_PROT_PPPMUX_SUBFRM,
+	NET_PROT_L2TPV2,
+	NET_PROT_L2TPV3_CTRL,
+	NET_PROT_L2TPV3_SESS,
+	NET_PROT_LLC,
+	NET_PROT_LLC_SNAP,
+	NET_PROT_NLPID,
+	NET_PROT_SNAP,
+	NET_PROT_MPLS,
+	NET_PROT_IPSEC_AH,
+	NET_PROT_IPSEC_ESP,
+	NET_PROT_UDP_ENC_ESP, /* RFC 3948 */
+	NET_PROT_MACSEC,
+	NET_PROT_GRE,
+	NET_PROT_MINENCAP,
+	NET_PROT_DCCP,
+	NET_PROT_ICMP,
+	NET_PROT_IGMP,
+	NET_PROT_ARP,
+	NET_PROT_CAPWAP_DATA,
+	NET_PROT_CAPWAP_CTRL,
+	NET_PROT_RFC2684,
+	NET_PROT_ICMPV6,
+	NET_PROT_FCOE,
+	NET_PROT_FIP,
+	NET_PROT_ISCSI,
+	NET_PROT_GTP,
+	NET_PROT_USER_DEFINED_L2,
+	NET_PROT_USER_DEFINED_L3,
+	NET_PROT_USER_DEFINED_L4,
+	NET_PROT_USER_DEFINED_L5,
+	NET_PROT_USER_DEFINED_SHIM1,
+	NET_PROT_USER_DEFINED_SHIM2,
+
+	NET_PROT_DUMMY_LAST
+};
+
+/*! IEEE8021.Q */
+#define NH_IEEE8021Q_ETYPE  0x8100
+#define NH_IEEE8021Q_HDR(etype, pcp, dei, vlan_id)      \
+	    ((((uint32_t)(etype & 0xFFFF)) << 16) |       \
+	    (((uint32_t)(pcp & 0x07)) << 13) |          \
+	    (((uint32_t)(dei & 0x01)) << 12) |          \
+	    (((uint32_t)(vlan_id & 0xFFF))))
+
+#endif /* __FSL_NET_H */
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2790,6 +2790,7 @@ static struct sk_buff *pktgen_alloc_skb(
 	} else {
 		 skb = __netdev_alloc_skb(dev, size, GFP_NOWAIT);
 	}
+	skb_reserve(skb, LL_RESERVED_SPACE(dev));
 
 	/* the caller pre-fetches from skb->data and reserves for the mac hdr */
 	if (likely(skb))
